Convert to critical sections.
[dragonfly.git] / sys / dev / netif / ie / if_ie.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1992, 1993, University of Vermont and State
3 * Agricultural College.
4 * Copyright (c) 1992, 1993, Garrett A. Wollman.
5 *
6 * Portions:
7 * Copyright (c) 1990, 1991, William F. Jolitz
8 * Copyright (c) 1990, The Regents of the University of California
9 *
10 * 3Com 3C507 support:
11 * Copyright (c) 1993, 1994, Charles M. Hannum
12 *
13 * EtherExpress 16 support:
14 * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
15 * Copyright (c) 1997, Aaron C. Smith
16 *
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * Vermont and State Agricultural College and Garrett A. Wollman, by
31 * William F. Jolitz, by the University of California, Berkeley,
32 * Lawrence Berkeley Laboratory, and their contributors, by
33 * Charles M. Hannum, by Rodney W. Grimes, and by Aaron C. Smith.
34 * 4. Neither the names of the Universities nor the names of the authors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * $FreeBSD: src/sys/dev/ie/if_ie.c,v 1.72.2.4 2003/03/27 21:01:49 mdodd Exp $
ec15e0df 51 * $DragonFly: src/sys/dev/netif/ie/if_ie.c,v 1.19 2005/06/14 15:30:58 joerg Exp $
984263bc
MD
52 */
53
54/*
55 * Intel 82586 Ethernet chip
56 * Register, bit, and structure definitions.
57 *
58 * Written by GAW with reference to the Clarkson Packet Driver code for this
59 * chip written by Russ Nelson and others.
60 *
61 * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
62 */
63
64/*
65 * The i82586 is a very versatile chip, found in many implementations.
66 * Programming this chip is mostly the same, but certain details differ
67 * from card to card. This driver is written so that different cards
68 * can be automatically detected at run-time.
69 */
70
71/*
72Mode of operation:
73
74We run the 82586 in a standard Ethernet mode. We keep NFRAMES received
75frame descriptors around for the receiver to use, and NRXBUFS associated
76receive buffer descriptors, both in a circular list. Whenever a frame is
77received, we rotate both lists as necessary. (The 586 treats both lists
78as a simple queue.) We also keep a transmit command around so that packets
79can be sent off quickly.
80
81We configure the adapter in AL-LOC = 1 mode, which means that the
82Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
83rather than being split off into various fields in the RFD. This also
84means that we must include this header in the transmit buffer as well.
85
86By convention, all transmit commands, and only transmit commands, shall
87have the I (IE_CMD_INTR) bit set in the command. This way, when an
88interrupt arrives at ieintr(), it is immediately possible to tell
89what precisely caused it. ANY OTHER command-sending routines should
90run at splimp(), and should post an acknowledgement to every interrupt
91they generate.
92
93The 82586 has a 24-bit address space internally, and the adaptor's memory
94is located at the top of this region. However, the value we are given in
95configuration is normally the *bottom* of the adaptor RAM. So, we must go
96through a few gyrations to come up with a kernel virtual address which
97represents the actual beginning of the 586 address space. First, we
98autosize the RAM by running through several possible sizes and trying to
99initialize the adapter under the assumption that the selected size is
100correct. Then, knowing the correct RAM size, we set up our pointers in
101ie_softc[unit]. `iomem' represents the computed base of the 586 address
102space. `iomembot' represents the actual configured base of adapter RAM.
103Finally, `iosize' represents the calculated size of 586 RAM. Then, when
104laying out commands, we use the interval [iomembot, iomembot + iosize); to
105make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
106iomem and and with 0xffff.
107
108*/
109
1f2de5d4 110#include "use_ie.h"
984263bc
MD
111#include "opt_inet.h"
112#include "opt_ipx.h"
113
114#include <sys/param.h>
115#include <sys/systm.h>
116#include <sys/eventhandler.h>
117#include <sys/kernel.h>
118#include <sys/malloc.h>
119#include <sys/conf.h>
120#include <sys/mbuf.h>
121#include <sys/socket.h>
122#include <sys/sockio.h>
123#include <sys/syslog.h>
ec15e0df 124#include <sys/thread2.h>
984263bc
MD
125
126#include <net/ethernet.h>
127#include <net/if.h>
2c4ce138 128#include <net/ifq_var.h>
984263bc
MD
129#include <net/if_types.h>
130#include <net/if_dl.h>
131
132#include <netinet/in.h>
133#include <netinet/if_ether.h>
134
135#include <machine/clock.h>
136#include <machine/md_var.h>
137
1f2de5d4 138#include <bus/isa/i386/isa_device.h>
984263bc
MD
139#include <i386/isa/ic/i82586.h>
140#include <i386/isa/icu.h>
1f2de5d4
MD
141#include "if_iereg.h"
142#include "if_ie507.h"
143#include "if_iee16.h"
144#include "../elink_layer/elink.h"
984263bc
MD
145
146#include <net/bpf.h>
147
148#ifdef DEBUG
149#define IED_RINT 0x01
150#define IED_TINT 0x02
151#define IED_RNR 0x04
152#define IED_CNA 0x08
153#define IED_READFRAME 0x10
154static int ie_debug = IED_RNR;
155
156#endif
157
32832096
MD
158DECLARE_DUMMY_MODULE(if_ie);
159
984263bc
MD
160#define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */
161
162/* Forward declaration */
163struct ie_softc;
164
165static int ieprobe(struct isa_device * dvp);
166static int ieattach(struct isa_device * dvp);
167static ointhand2_t ieintr;
168static int sl_probe(struct isa_device * dvp);
169static int el_probe(struct isa_device * dvp);
170static int ni_probe(struct isa_device * dvp);
171static int ee16_probe(struct isa_device * dvp);
172
173static int check_ie_present(int unit, caddr_t where, unsigned size);
174static void ieinit(void *);
175static void ie_stop(int unit);
bd4539cc
JH
176static int ieioctl(struct ifnet * ifp, u_long command, caddr_t data,
177 struct ucred *);
984263bc
MD
178static void iestart(struct ifnet * ifp);
179
180static void el_reset_586(int unit);
181static void el_chan_attn(int unit);
182
183static void sl_reset_586(int unit);
184static void sl_chan_attn(int unit);
185
186static void ee16_reset_586(int unit);
187static void ee16_chan_attn(int unit);
188static __inline void ee16_interrupt_enable(struct ie_softc * ie);
189static void ee16_eeprom_outbits(struct ie_softc * ie, int edata, int cnt);
190static void ee16_eeprom_clock(struct ie_softc * ie, int state);
191static u_short ee16_read_eeprom(struct ie_softc * ie, int location);
192static int ee16_eeprom_inbits(struct ie_softc * ie);
193static void ee16_shutdown(void *sc, int howto);
194
195static void iereset(int unit);
196static void ie_readframe(int unit, struct ie_softc * ie, int bufno);
197static void ie_drop_packet_buffer(int unit, struct ie_softc * ie);
198static void sl_read_ether(int unit, unsigned char addr[6]);
199static void find_ie_mem_size(int unit);
984263bc
MD
200static int command_and_wait(int unit, int command,
201 void volatile * pcmd, int);
202static void run_tdr(int unit, volatile struct ie_tdr_cmd * cmd);
203static int ierint(int unit, struct ie_softc * ie);
204static int ietint(int unit, struct ie_softc * ie);
205static int iernr(int unit, struct ie_softc * ie);
206static void start_receiver(int unit);
207static __inline int ieget(int, struct ie_softc *, struct mbuf **,
208 struct ether_header *);
209static v_caddr_t setup_rfa(v_caddr_t ptr, struct ie_softc * ie);
210static int mc_setup(int, v_caddr_t, volatile struct ie_sys_ctl_block *);
211static void ie_mc_reset(int unit);
212
213#ifdef DEBUG
214static void print_rbd(volatile struct ie_recv_buf_desc * rbd);
215
216static int in_ierint = 0;
217static int in_ietint = 0;
218
219#endif
220
221/*
222 * This tells the autoconf code how to set us up.
223 */
224struct isa_driver iedriver = {
225 ieprobe, ieattach, "ie",
226};
227
228enum ie_hardware {
229 IE_STARLAN10,
230 IE_EN100,
231 IE_SLFIBER,
232 IE_3C507,
233 IE_NI5210,
234 IE_EE16,
235 IE_UNKNOWN
236};
237
238static const char *ie_hardware_names[] = {
239 "StarLAN 10",
240 "EN100",
241 "StarLAN Fiber",
242 "3C507",
243 "NI5210",
244 "EtherExpress 16",
245 "Unknown"
246};
247
248/*
249sizeof(iscp) == 1+1+2+4 == 8
250sizeof(scb) == 2+2+2+2+2+2+2+2 == 16
251NFRAMES * sizeof(rfd) == NFRAMES*(2+2+2+2+6+6+2+2) == NFRAMES*24 == 384
252sizeof(xmit_cmd) == 2+2+2+2+6+2 == 18
253sizeof(transmit buffer) == 1512
254sizeof(transmit buffer desc) == 8
255-----
2561946
257
258NRXBUFS * sizeof(rbd) == NRXBUFS*(2+2+4+2+2) == NRXBUFS*12
259NRXBUFS * IE_RBUF_SIZE == NRXBUFS*256
260
261NRXBUFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
262
263With NRXBUFS == 48, this leaves us 1574 bytes for another command or
264more buffers. Another transmit command would be 18+8+1512 == 1538
265---just barely fits!
266
267Obviously all these would have to be reduced for smaller memory sizes.
268With a larger memory, it would be possible to roughly double the number of
269both transmit and receive buffers.
270*/
271
272#define NFRAMES 8 /* number of receive frames */
273#define NRXBUFS 48 /* number of buffers to allocate */
274#define IE_RBUF_SIZE 256 /* size of each buffer, MUST BE POWER OF TWO */
275#define NTXBUFS 2 /* number of transmit commands */
276#define IE_TBUF_SIZE ETHER_MAX_LEN /* size of transmit buffer */
277
278/*
279 * Ethernet status, per interface.
280 */
281static struct ie_softc {
282 struct arpcom arpcom;
283 void (*ie_reset_586) (int);
284 void (*ie_chan_attn) (int);
285 enum ie_hardware hard_type;
286 int hard_vers;
287 int unit;
288
289 u_short port; /* i/o base address for this interface */
290 caddr_t iomem; /* memory size */
291 caddr_t iomembot; /* memory base address */
292 unsigned iosize;
293 int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
294
295 int want_mcsetup;
296 int promisc;
297 int nframes;
298 int nrxbufs;
299 int ntxbufs;
300 volatile struct ie_int_sys_conf_ptr *iscp;
301 volatile struct ie_sys_ctl_block *scb;
302 volatile struct ie_recv_frame_desc **rframes; /* nframes worth */
303 volatile struct ie_recv_buf_desc **rbuffs; /* nrxbufs worth */
304 volatile u_char **cbuffs; /* nrxbufs worth */
305 int rfhead, rftail, rbhead, rbtail;
306
307 volatile struct ie_xmit_cmd **xmit_cmds; /* ntxbufs worth */
308 volatile struct ie_xmit_buf **xmit_buffs; /* ntxbufs worth */
309 volatile u_char **xmit_cbuffs; /* ntxbufs worth */
310 int xmit_count;
311
312 struct ie_en_addr mcast_addrs[MAXMCAST + 1];
313 int mcast_count;
314
315 u_short irq_encoded; /* encoded interrupt on IEE16 */
316} ie_softc[NIE];
317
318#define MK_24(base, ptr) ((caddr_t)((uintptr_t)ptr - (uintptr_t)base))
319#define MK_16(base, ptr) ((u_short)(uintptr_t)MK_24(base, ptr))
320
321#define PORT ie_softc[unit].port
322#define MEM ie_softc[unit].iomem
323
324int
325ieprobe(struct isa_device *dvp)
326{
327 int ret;
328
329 ret = sl_probe(dvp);
330 if (!ret)
331 ret = el_probe(dvp);
332 if (!ret)
333 ret = ni_probe(dvp);
334 if (!ret)
335 ret = ee16_probe(dvp);
336
337 return (ret);
338}
339
340static int
341sl_probe(struct isa_device *dvp)
342{
343 int unit = dvp->id_unit;
344 u_char c;
345
346 ie_softc[unit].port = dvp->id_iobase;
347 ie_softc[unit].iomembot = dvp->id_maddr;
348 ie_softc[unit].iomem = 0;
349 ie_softc[unit].bus_use = 0;
350
351 c = inb(PORT + IEATT_REVISION);
352 switch (SL_BOARD(c)) {
353 case SL10_BOARD:
354 ie_softc[unit].hard_type = IE_STARLAN10;
355 ie_softc[unit].ie_reset_586 = sl_reset_586;
356 ie_softc[unit].ie_chan_attn = sl_chan_attn;
357 break;
358 case EN100_BOARD:
359 ie_softc[unit].hard_type = IE_EN100;
360 ie_softc[unit].ie_reset_586 = sl_reset_586;
361 ie_softc[unit].ie_chan_attn = sl_chan_attn;
362 break;
363 case SLFIBER_BOARD:
364 ie_softc[unit].hard_type = IE_SLFIBER;
365 ie_softc[unit].ie_reset_586 = sl_reset_586;
366 ie_softc[unit].ie_chan_attn = sl_chan_attn;
367 break;
368
369 /*
370 * Anything else is not recognized or cannot be used.
371 */
372 default:
373 return (0);
374 }
375
376 ie_softc[unit].hard_vers = SL_REV(c);
377
378 /*
379 * Divine memory size on-board the card. Ususally 16k.
380 */
381 find_ie_mem_size(unit);
382
383 if (!ie_softc[unit].iosize) {
384 return (0);
385 }
386 dvp->id_msize = ie_softc[unit].iosize;
387
388 switch (ie_softc[unit].hard_type) {
389 case IE_EN100:
390 case IE_STARLAN10:
391 case IE_SLFIBER:
392 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
393 break;
394
395 default:
396 if (bootverbose)
397 printf("ie%d: unknown AT&T board type code %d\n", unit,
398 ie_softc[unit].hard_type);
399 return (0);
400 }
401
402 return (1);
403}
404
405
406static int
407el_probe(struct isa_device *dvp)
408{
409 struct ie_softc *sc = &ie_softc[dvp->id_unit];
410 u_char c;
411 int i;
412 u_char signature[] = "*3COM*";
413 int unit = dvp->id_unit;
414
415 sc->unit = unit;
416 sc->port = dvp->id_iobase;
417 sc->iomembot = dvp->id_maddr;
418 sc->bus_use = 0;
419
420 /* Need this for part of the probe. */
421 sc->ie_reset_586 = el_reset_586;
422 sc->ie_chan_attn = el_chan_attn;
423
424 /* Reset and put card in CONFIG state without changing address. */
425 elink_reset();
426 outb(ELINK_ID_PORT, 0x00);
427 elink_idseq(ELINK_507_POLY);
428 elink_idseq(ELINK_507_POLY);
429 outb(ELINK_ID_PORT, 0xff);
430
431 c = inb(PORT + IE507_MADDR);
432 if (c & 0x20) {
433#ifdef DEBUG
434 printf("ie%d: can't map 3C507 RAM in high memory\n", unit);
435#endif
436 return (0);
437 }
438 /* go to RUN state */
439 outb(ELINK_ID_PORT, 0x00);
440 elink_idseq(ELINK_507_POLY);
441 outb(ELINK_ID_PORT, 0x00);
442
443 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
444
445 for (i = 0; i < 6; i++)
446 if (inb(PORT + i) != signature[i])
447 return (0);
448
449 c = inb(PORT + IE507_IRQ) & 0x0f;
450
451 if (dvp->id_irq != (1 << c)) {
452 printf("ie%d: kernel configured irq %d "
453 "doesn't match board configured irq %d\n",
454 unit, ffs(dvp->id_irq) - 1, c);
455 return (0);
456 }
457 c = (inb(PORT + IE507_MADDR) & 0x1c) + 0xc0;
458
459 if (kvtop(dvp->id_maddr) != ((int) c << 12)) {
416148ae 460 printf("ie%d: kernel configured maddr %llx "
984263bc
MD
461 "doesn't match board configured maddr %x\n",
462 unit, kvtop(dvp->id_maddr), (int) c << 12);
463 return (0);
464 }
465 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
466
467 sc->hard_type = IE_3C507;
468 sc->hard_vers = 0; /* 3C507 has no version number. */
469
470 /*
471 * Divine memory size on-board the card.
472 */
473 find_ie_mem_size(unit);
474
475 if (!sc->iosize) {
476 printf("ie%d: can't find shared memory\n", unit);
477 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
478 return (0);
479 }
480 if (!dvp->id_msize)
481 dvp->id_msize = sc->iosize;
482 else if (dvp->id_msize != sc->iosize) {
483 printf("ie%d: kernel configured msize %d "
484 "doesn't match board configured msize %d\n",
485 unit, dvp->id_msize, sc->iosize);
486 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
487 return (0);
488 }
489 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
490
491 /* Clear the interrupt latch just in case. */
492 outb(PORT + IE507_ICTRL, 1);
493
494 return (16);
495}
496
497
498static int
499ni_probe(struct isa_device *dvp)
500{
501 int unit = dvp->id_unit;
502 int boardtype, c;
503
504 ie_softc[unit].port = dvp->id_iobase;
505 ie_softc[unit].iomembot = dvp->id_maddr;
506 ie_softc[unit].iomem = 0;
507 ie_softc[unit].bus_use = 1;
508
509 boardtype = inb(PORT + IEATT_REVISION);
510 c = inb(PORT + IEATT_REVISION + 1);
511 boardtype = boardtype + (c << 8);
512 switch (boardtype) {
513 case 0x5500: /* This is the magic cookie for the NI5210 */
514 ie_softc[unit].hard_type = IE_NI5210;
515 ie_softc[unit].ie_reset_586 = sl_reset_586;
516 ie_softc[unit].ie_chan_attn = sl_chan_attn;
517 break;
518
519 /*
520 * Anything else is not recognized or cannot be used.
521 */
522 default:
523 return (0);
524 }
525
526 ie_softc[unit].hard_vers = 0;
527
528 /*
529 * Divine memory size on-board the card. Either 8 or 16k.
530 */
531 find_ie_mem_size(unit);
532
533 if (!ie_softc[unit].iosize) {
534 return (0);
535 }
536 if (!dvp->id_msize)
537 dvp->id_msize = ie_softc[unit].iosize;
538 else if (dvp->id_msize != ie_softc[unit].iosize) {
539 printf("ie%d: kernel configured msize %d "
540 "doesn't match board configured msize %d\n",
541 unit, dvp->id_msize, ie_softc[unit].iosize);
542 return (0);
543 }
544 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
545
546 return (8);
547
548}
549
550
551static void
552ee16_shutdown(void *sc, int howto)
553{
554 struct ie_softc *ie = (struct ie_softc *)sc;
555 int unit = ie - &ie_softc[0];
556
557 ee16_reset_586(unit);
558 outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
559 outb(PORT + IEE16_ECTRL, 0);
560}
561
562
563/* Taken almost exactly from Rod's if_ix.c. */
564
565int
566ee16_probe(struct isa_device *dvp)
567{
568 struct ie_softc *sc = &ie_softc[dvp->id_unit];
569
570 int i;
571 int unit = dvp->id_unit;
572 u_short board_id, id_var1, id_var2, checksum = 0;
573 u_short eaddrtemp, irq;
574 u_short pg, adjust, decode, edecode;
575 u_char bart_config;
576 u_long bd_maddr;
577
578 short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
579 char irq_encode[] = {0, 0, 0, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0};
580
581 /* Need this for part of the probe. */
582 sc->ie_reset_586 = ee16_reset_586;
583 sc->ie_chan_attn = ee16_chan_attn;
584
585 /* unsure if this is necessary */
586 sc->bus_use = 0;
587
588 /* reset any ee16 at the current iobase */
589 outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
590 outb(dvp->id_iobase + IEE16_ECTRL, 0);
591 DELAY(240);
592
593 /* now look for ee16. */
594 board_id = id_var1 = id_var2 = 0;
595 for (i = 0; i < 4; i++) {
596 id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
597 id_var2 = ((id_var1 & 0x03) << 2);
598 board_id |= ((id_var1 >> 4) << id_var2);
599 }
600
601 if (board_id != IEE16_ID) {
602 if (bootverbose)
603 printf("ie%d: unknown board_id: %x\n", unit, board_id);
604 return (0);
605 }
606 /* need sc->port for ee16_read_eeprom */
607 sc->port = dvp->id_iobase;
608 sc->hard_type = IE_EE16;
609
610 /*
611 * The shared RAM location on the EE16 is encoded into bits 3-7 of
612 * EEPROM location 6. We zero the upper byte, and shift the 5 bits
613 * right 3. The resulting number tells us the RAM location.
614 * Because the EE16 supports either 16k or 32k of shared RAM, we
615 * only worry about the 32k locations.
616 *
617 * NOTE: if a 64k EE16 exists, it should be added to this switch. then
618 * the ia->ia_msize would need to be set per case statement.
619 *
620 * value msize location ===== ===== ======== 0x03 0x8000
621 * 0xCC000 0x06 0x8000 0xD0000 0x0C 0x8000 0xD4000 0x18
622 * 0x8000 0xD8000
623 *
624 */
625
626 bd_maddr = 0;
627 i = (ee16_read_eeprom(sc, 6) & 0x00ff) >> 3;
628 switch (i) {
629 case 0x03:
630 bd_maddr = 0xCC000;
631 break;
632 case 0x06:
633 bd_maddr = 0xD0000;
634 break;
635 case 0x0c:
636 bd_maddr = 0xD4000;
637 break;
638 case 0x18:
639 bd_maddr = 0xD8000;
640 break;
641 default:
642 bd_maddr = 0;
643 break;
644 }
645 dvp->id_msize = 0x8000;
646 if (kvtop(dvp->id_maddr) != bd_maddr) {
416148ae 647 printf("ie%d: kernel configured maddr %llx "
984263bc
MD
648 "doesn't match board configured maddr %lx\n",
649 unit, kvtop(dvp->id_maddr), bd_maddr);
650 }
651 sc->iomembot = dvp->id_maddr;
652 sc->iomem = 0; /* XXX some probes set this and some don't */
653 sc->iosize = dvp->id_msize;
654
655 /* need to put the 586 in RESET while we access the eeprom. */
656 outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
657
658 /* read the eeprom and checksum it, should == IEE16_ID */
659 for (i = 0; i < 0x40; i++)
660 checksum += ee16_read_eeprom(sc, i);
661
662 if (checksum != IEE16_ID) {
663 printf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
664 return (0);
665 }
666 /*
667 * Size and test the memory on the board. The size of the memory
668 * can be one of 16k, 32k, 48k or 64k. It can be located in the
669 * address range 0xC0000 to 0xEFFFF on 16k boundaries.
670 *
671 * If the size does not match the passed in memory allocation size
672 * issue a warning, but continue with the minimum of the two sizes.
673 */
674
675 switch (dvp->id_msize) {
676 case 65536:
677 case 32768: /* XXX Only support 32k and 64k right now */
678 break;
679 case 16384:
680 case 49512:
681 default:
682 printf("ie%d: mapped memory size %d not supported\n", unit,
683 dvp->id_msize);
684 return (0);
685 break; /* NOTREACHED */
686 }
687
688 if ((kvtop(dvp->id_maddr) < 0xC0000) ||
689 (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
690 printf("ie%d: mapped memory location %p out of range\n", unit,
691 (void *)dvp->id_maddr);
692 return (0);
693 }
694 pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
695 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
696 decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
697 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
698
699 /* ZZZ This should be checked against eeprom location 6, low byte */
700 outb(PORT + IEE16_MEMDEC, decode & 0xFF);
701 /* ZZZ This should be checked against eeprom location 1, low byte */
702 outb(PORT + IEE16_MCTRL, adjust);
703 /* ZZZ Now if I could find this one I would have it made */
704 outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
705 /* ZZZ I think this is location 6, high byte */
706 outb(PORT + IEE16_MECTRL, edecode); /* XXX disable Exxx */
707
708 (void) kvtop(dvp->id_maddr);
709
710 /*
711 * first prime the stupid bart DRAM controller so that it works,
712 * then zero out all of memory.
713 */
714 bzero(sc->iomembot, 32);
715 bzero(sc->iomembot, sc->iosize);
716
717 /*
718 * Get the encoded interrupt number from the EEPROM, check it
719 * against the passed in IRQ. Issue a warning if they do not match.
720 * Always use the passed in IRQ, not the one in the EEPROM.
721 */
722 irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
723 irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
724 irq = irq_translate[irq];
725 if (dvp->id_irq > 0) {
726 if (irq != dvp->id_irq) {
727 printf("ie%d: WARNING: board configured "
728 "at irq %u, using %u\n",
729 dvp->id_unit, dvp->id_irq, irq);
730 irq = dvp->id_unit;
731 }
732 } else {
733 dvp->id_irq = irq;
734 }
735 sc->irq_encoded = irq_encode[ffs(irq) - 1];
736
737 /*
738 * Get the hardware ethernet address from the EEPROM and save it in
739 * the softc for use by the 586 setup code.
740 */
741 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
742 sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
743 sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
744 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
745 sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
746 sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
747 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
748 sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
749 sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
750
751 /* disable the board interrupts */
752 outb(PORT + IEE16_IRQ, sc->irq_encoded);
753
754 /* enable loopback to keep bad packets off the wire */
755 if (sc->hard_type == IE_EE16) {
756 bart_config = inb(PORT + IEE16_CONFIG);
757 bart_config |= IEE16_BART_LOOPBACK;
758 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
759 outb(PORT + IEE16_CONFIG, bart_config);
760 bart_config = inb(PORT + IEE16_CONFIG);
761 }
762 /* take the board out of reset state */
763 outb(PORT + IEE16_ECTRL, 0);
764 DELAY(100);
765
766 if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
767 return (0);
768
769 return (16); /* return the number of I/O ports */
770}
771
772/*
773 * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
774 */
775int
776ieattach(struct isa_device *dvp)
777{
778 int factor;
779 int unit = dvp->id_unit;
780 struct ie_softc *ie = &ie_softc[unit];
781 struct ifnet *ifp = &ie->arpcom.ac_if;
782 size_t allocsize;
783
784 dvp->id_ointr = ieintr;
785
786 /*
787 * based on the amount of memory we have, allocate our tx and rx
788 * resources.
789 */
790 factor = dvp->id_msize / 16384;
791 ie->nframes = factor * NFRAMES;
792 ie->nrxbufs = factor * NRXBUFS;
793 ie->ntxbufs = factor * NTXBUFS;
794
795 /*
796 * Since all of these guys are arrays of pointers, allocate as one
797 * big chunk and dole out accordingly.
798 */
799 allocsize = sizeof(void *) * (ie->nframes
800 + (ie->nrxbufs * 2)
801 + (ie->ntxbufs * 3));
c5541aee 802 ie->rframes = malloc(allocsize, M_DEVBUF, M_WAITOK);
984263bc
MD
803 ie->rbuffs =
804 (volatile struct ie_recv_buf_desc **)&ie->rframes[ie->nframes];
805 ie->cbuffs = (volatile u_char **)&ie->rbuffs[ie->nrxbufs];
806 ie->xmit_cmds =
807 (volatile struct ie_xmit_cmd **)&ie->cbuffs[ie->nrxbufs];
808 ie->xmit_buffs =
809 (volatile struct ie_xmit_buf **)&ie->xmit_cmds[ie->ntxbufs];
810 ie->xmit_cbuffs = (volatile u_char **)&ie->xmit_buffs[ie->ntxbufs];
811
812 ifp->if_softc = ie;
3e4a09e7 813 if_initname(ifp, iedriver.name, unit);
984263bc 814 ifp->if_mtu = ETHERMTU;
267caeeb
JS
815 if_printf(ifp, "<%s R%d>", ie_hardware_names[ie->hard_type],
816 ie->hard_vers + 1);
984263bc
MD
817
818 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
984263bc
MD
819 ifp->if_start = iestart;
820 ifp->if_ioctl = ieioctl;
821 ifp->if_init = ieinit;
822 ifp->if_type = IFT_ETHER;
823 ifp->if_addrlen = 6;
824 ifp->if_hdrlen = 14;
2c4ce138
JS
825 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
826 ifq_set_ready(&ifp->if_snd);
984263bc
MD
827
828 if (ie->hard_type == IE_EE16)
829 EVENTHANDLER_REGISTER(shutdown_post_sync, ee16_shutdown,
830 ie, SHUTDOWN_PRI_DEFAULT);
831
0a8b5977 832 ether_ifattach(ifp, ie->arpcom.ac_enaddr);
984263bc
MD
833 return (1);
834}
835
836/*
837 * What to do upon receipt of an interrupt.
838 */
839static void
840ieintr(int unit)
841{
f96d6c88
RG
842 struct ie_softc *ie = &ie_softc[unit];
843 u_short status;
984263bc
MD
844
845 /* Clear the interrupt latch on the 3C507. */
846 if (ie->hard_type == IE_3C507
847 && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
848 outb(PORT + IE507_ICTRL, 1);
849
850 /* disable interrupts on the EE16. */
851 if (ie->hard_type == IE_EE16)
852 outb(PORT + IEE16_IRQ, ie->irq_encoded);
853
854 status = ie->scb->ie_status;
855
856loop:
857
858 /* Don't ack interrupts which we didn't receive */
859 ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
860
861 if (status & (IE_ST_RECV | IE_ST_RNR)) {
862#ifdef DEBUG
863 in_ierint++;
864 if (ie_debug & IED_RINT)
865 printf("ie%d: rint\n", unit);
866#endif
867 ierint(unit, ie);
868#ifdef DEBUG
869 in_ierint--;
870#endif
871 }
872 if (status & IE_ST_DONE) {
873#ifdef DEBUG
874 in_ietint++;
875 if (ie_debug & IED_TINT)
876 printf("ie%d: tint\n", unit);
877#endif
878 ietint(unit, ie);
879#ifdef DEBUG
880 in_ietint--;
881#endif
882 }
883 if (status & IE_ST_RNR) {
884#ifdef DEBUG
885 if (ie_debug & IED_RNR)
886 printf("ie%d: rnr\n", unit);
887#endif
888 iernr(unit, ie);
889 }
890#ifdef DEBUG
891 if ((status & IE_ST_ALLDONE)
892 && (ie_debug & IED_CNA))
893 printf("ie%d: cna\n", unit);
894#endif
895
896 if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
897 goto loop;
898
899 /* Clear the interrupt latch on the 3C507. */
900 if (ie->hard_type == IE_3C507)
901 outb(PORT + IE507_ICTRL, 1);
902
903 /* enable interrupts on the EE16. */
904 if (ie->hard_type == IE_EE16)
905 outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
906
907}
908
909/*
910 * Process a received-frame interrupt.
911 */
912static int
913ierint(int unit, struct ie_softc *ie)
914{
915 int i, status;
916 static int timesthru = 1024;
917
918 i = ie->rfhead;
919 while (1) {
920 status = ie->rframes[i]->ie_fd_status;
921
922 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
923 ie->arpcom.ac_if.if_ipackets++;
924 if (!--timesthru) {
925 ie->arpcom.ac_if.if_ierrors +=
926 ie->scb->ie_err_crc +
927 ie->scb->ie_err_align +
928 ie->scb->ie_err_resource +
929 ie->scb->ie_err_overrun;
930 ie->scb->ie_err_crc = 0;
931 ie->scb->ie_err_align = 0;
932 ie->scb->ie_err_resource = 0;
933 ie->scb->ie_err_overrun = 0;
934 timesthru = 1024;
935 }
936 ie_readframe(unit, ie, i);
937 } else {
938 if (status & IE_FD_RNR) {
939 if (!(ie->scb->ie_status & IE_RU_READY)) {
940 ie->rframes[0]->ie_fd_next =
941 MK_16(MEM, ie->rbuffs[0]);
942 ie->scb->ie_recv_list =
943 MK_16(MEM, ie->rframes[0]);
944 command_and_wait(unit, IE_RU_START,
945 0, 0);
946 }
947 }
948 break;
949 }
950 i = (i + 1) % ie->nframes;
951 }
952 return (0);
953}
954
955/*
956 * Process a command-complete interrupt. These are only generated by
957 * the transmission of frames. This routine is deceptively simple, since
958 * most of the real work is done by iestart().
959 */
960static int
961ietint(int unit, struct ie_softc *ie)
962{
963 int status;
964 int i;
965
966 ie->arpcom.ac_if.if_timer = 0;
967 ie->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
968
969 for (i = 0; i < ie->xmit_count; i++) {
970 status = ie->xmit_cmds[i]->ie_xmit_status;
971
972 if (status & IE_XS_LATECOLL) {
973 printf("ie%d: late collision\n", unit);
974 ie->arpcom.ac_if.if_collisions++;
975 ie->arpcom.ac_if.if_oerrors++;
976 } else if (status & IE_XS_NOCARRIER) {
977 printf("ie%d: no carrier\n", unit);
978 ie->arpcom.ac_if.if_oerrors++;
979 } else if (status & IE_XS_LOSTCTS) {
980 printf("ie%d: lost CTS\n", unit);
981 ie->arpcom.ac_if.if_oerrors++;
982 } else if (status & IE_XS_UNDERRUN) {
983 printf("ie%d: DMA underrun\n", unit);
984 ie->arpcom.ac_if.if_oerrors++;
985 } else if (status & IE_XS_EXCMAX) {
986 printf("ie%d: too many collisions\n", unit);
987 ie->arpcom.ac_if.if_collisions += 16;
988 ie->arpcom.ac_if.if_oerrors++;
989 } else {
990 ie->arpcom.ac_if.if_opackets++;
991 ie->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
992 }
993 }
994 ie->xmit_count = 0;
995
996 /*
997 * If multicast addresses were added or deleted while we were
998 * transmitting, ie_mc_reset() set the want_mcsetup flag indicating
999 * that we should do it.
1000 */
1001 if (ie->want_mcsetup) {
1002 mc_setup(unit, (v_caddr_t) ie->xmit_cbuffs[0], ie->scb);
1003 ie->want_mcsetup = 0;
1004 }
1005 /* Wish I knew why this seems to be necessary... */
1006 ie->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
1007
1008 iestart(&ie->arpcom.ac_if);
1009 return (0); /* shouldn't be necessary */
1010}
1011
1012/*
1013 * Process a receiver-not-ready interrupt. I believe that we get these
1014 * when there aren't enough buffers to go around. For now (FIXME), we
1015 * just restart the receiver, and hope everything's ok.
1016 */
1017static int
1018iernr(int unit, struct ie_softc *ie)
1019{
1020#ifdef doesnt_work
1021 setup_rfa((v_caddr_t) ie->rframes[0], ie);
1022
1023 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1024 command_and_wait(unit, IE_RU_START, 0, 0);
1025#else
1026 /* This doesn't work either, but it doesn't hang either. */
1027 command_and_wait(unit, IE_RU_DISABLE, 0, 0); /* just in case */
1028 setup_rfa((v_caddr_t) ie->rframes[0], ie); /* ignore cast-qual */
1029
1030 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1031 command_and_wait(unit, IE_RU_START, 0, 0); /* was ENABLE */
1032
1033#endif
1034 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
1035
1036 ie->arpcom.ac_if.if_ierrors++;
1037 return (0);
1038}
1039
1040/*
1041 * Compare two Ether/802 addresses for equality, inlined and
1042 * unrolled for speed. I'd love to have an inline assembler
1043 * version of this...
1044 */
1045static __inline int
1046ether_equal(u_char * one, u_char * two)
1047{
1048 if (one[0] != two[0])
1049 return (0);
1050 if (one[1] != two[1])
1051 return (0);
1052 if (one[2] != two[2])
1053 return (0);
1054 if (one[3] != two[3])
1055 return (0);
1056 if (one[4] != two[4])
1057 return (0);
1058 if (one[5] != two[5])
1059 return (0);
1060 return 1;
1061}
1062
1063/*
1064 * Determine quickly whether we should bother reading in this packet.
1065 * This depends on whether BPF and/or bridging is enabled, whether we
1066 * are receiving multicast address, and whether promiscuous mode is enabled.
1067 * We assume that if IFF_PROMISC is set, then *somebody* wants to see
1068 * all incoming packets.
1069 */
1070static __inline int
1071check_eh(struct ie_softc *ie, struct ether_header *eh)
1072{
1073 /* Optimize the common case: normal operation. We've received
1074 either a unicast with our dest or a multicast packet. */
1075 if (ie->promisc == 0) {
1076 int i;
1077
1078 /* If not multicast, it's definitely for us */
1079 if ((eh->ether_dhost[0] & 1) == 0)
1080 return (1);
1081
1082 /* Accept broadcasts (loose but fast check) */
1083 if (eh->ether_dhost[0] == 0xff)
1084 return (1);
1085
1086 /* Compare against our multicast addresses */
1087 for (i = 0; i < ie->mcast_count; i++) {
1088 if (ether_equal(eh->ether_dhost,
1089 (u_char *)&ie->mcast_addrs[i]))
1090 return (1);
1091 }
1092 return (0);
1093 }
1094
1095 /* Always accept packets when in promiscuous mode */
1096 if ((ie->promisc & IFF_PROMISC) != 0)
1097 return (1);
1098
1099 /* Always accept packets directed at us */
1100 if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
1101 return (1);
1102
1103 /* Must have IFF_ALLMULTI but not IFF_PROMISC set. The chip is
1104 actually in promiscuous mode, so discard unicast packets. */
1105 return((eh->ether_dhost[0] & 1) != 0);
1106}
1107
1108/*
1109 * We want to isolate the bits that have meaning... This assumes that
1110 * IE_RBUF_SIZE is an even power of two. If somehow the act_len exceeds
1111 * the size of the buffer, then we are screwed anyway.
1112 */
1113static __inline int
1114ie_buflen(struct ie_softc * ie, int head)
1115{
1116 return (ie->rbuffs[head]->ie_rbd_actual
1117 & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
1118}
1119
1120static __inline int
1121ie_packet_len(int unit, struct ie_softc * ie)
1122{
1123 int i;
1124 int head = ie->rbhead;
1125 int acc = 0;
1126
1127 do {
1128 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1129#ifdef DEBUG
1130 print_rbd(ie->rbuffs[ie->rbhead]);
1131#endif
1132 log(LOG_ERR,
1133 "ie%d: receive descriptors out of sync at %d\n",
1134 unit, ie->rbhead);
1135 iereset(unit);
1136 return (-1);
1137 }
1138 i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
1139
1140 acc += ie_buflen(ie, head);
1141 head = (head + 1) % ie->nrxbufs;
1142 } while (!i);
1143
1144 return (acc);
1145}
1146
1147/*
1148 * Read data off the interface, and turn it into an mbuf chain.
1149 *
1150 * This code is DRAMATICALLY different from the previous version; this
1151 * version tries to allocate the entire mbuf chain up front, given the
1152 * length of the data available. This enables us to allocate mbuf
1153 * clusters in many situations where before we would have had a long
1154 * chain of partially-full mbufs. This should help to speed up the
1155 * operation considerably. (Provided that it works, of course.)
1156 */
1157static __inline int
1158ieget(int unit, struct ie_softc *ie, struct mbuf **mp, struct ether_header *ehp)
1159{
1160 struct mbuf *m, *top, **mymp;
1161 int i;
1162 int offset;
1163 int totlen, resid;
1164 int thismboff;
1165 int head;
1166
1167 totlen = ie_packet_len(unit, ie);
1168 if (totlen <= 0)
1169 return (-1);
1170
1171 i = ie->rbhead;
1172
1173 /*
1174 * Snarf the Ethernet header.
1175 */
1176 bcopy((v_caddr_t) ie->cbuffs[i], (caddr_t) ehp, sizeof *ehp);
1177 /* ignore cast-qual warning here */
1178
1179 /*
1180 * As quickly as possible, check if this packet is for us. If not,
1181 * don't waste a single cycle copying the rest of the packet in.
1182 * This is only a consideration when FILTER is defined; i.e., when
1183 * we are either running BPF or doing multicasting.
1184 */
1185 if (!check_eh(ie, ehp)) {
1186 ie_drop_packet_buffer(unit, ie);
1187 ie->arpcom.ac_if.if_ierrors--; /* just this case, it's not an
1188 * error
1189 */
1190 return (-1);
1191 }
1192 totlen -= (offset = sizeof *ehp);
1193
74f1caca 1194 MGETHDR(*mp, MB_DONTWAIT, MT_DATA);
984263bc
MD
1195 if (!*mp) {
1196 ie_drop_packet_buffer(unit, ie);
1197 return (-1);
1198 }
1199 m = *mp;
1200 m->m_pkthdr.rcvif = &ie->arpcom.ac_if;
1201 m->m_len = MHLEN;
1202 resid = m->m_pkthdr.len = totlen;
1203 top = 0;
1204 mymp = &top;
1205
1206 /*
1207 * This loop goes through and allocates mbufs for all the data we
1208 * will be copying in. It does not actually do the copying yet.
1209 */
1210 do { /* while(resid > 0) */
1211 /*
1212 * Try to allocate an mbuf to hold the data that we have.
1213 * If we already allocated one, just get another one and
1214 * stick it on the end (eventually). If we don't already
1215 * have one, try to allocate an mbuf cluster big enough to
1216 * hold the whole packet, if we think it's reasonable, or a
1217 * single mbuf which may or may not be big enough. Got that?
1218 */
1219 if (top) {
74f1caca 1220 MGET(m, MB_DONTWAIT, MT_DATA);
984263bc
MD
1221 if (!m) {
1222 m_freem(top);
1223 ie_drop_packet_buffer(unit, ie);
1224 return (-1);
1225 }
1226 m->m_len = MLEN;
1227 }
1228 if (resid >= MINCLSIZE) {
74f1caca 1229 MCLGET(m, MB_DONTWAIT);
984263bc
MD
1230 if (m->m_flags & M_EXT)
1231 m->m_len = min(resid, MCLBYTES);
1232 } else {
1233 if (resid < m->m_len) {
1234 if (!top && resid + max_linkhdr <= m->m_len)
1235 m->m_data += max_linkhdr;
1236 m->m_len = resid;
1237 }
1238 }
1239 resid -= m->m_len;
1240 *mymp = m;
1241 mymp = &m->m_next;
1242 } while (resid > 0);
1243
1244 resid = totlen;
1245 m = top;
1246 thismboff = 0;
1247 head = ie->rbhead;
1248
1249 /*
1250 * Now we take the mbuf chain (hopefully only one mbuf most of the
1251 * time) and stuff the data into it. There are no possible failures
1252 * at or after this point.
1253 */
1254 while (resid > 0) { /* while there's stuff left */
1255 int thislen = ie_buflen(ie, head) - offset;
1256
1257 /*
1258 * If too much data for the current mbuf, then fill the
1259 * current one up, go to the next one, and try again.
1260 */
1261 if (thislen > m->m_len - thismboff) {
1262 int newlen = m->m_len - thismboff;
1263
1264 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1265 mtod(m, v_caddr_t) +thismboff, (unsigned) newlen);
1266 /* ignore cast-qual warning */
1267 m = m->m_next;
1268 thismboff = 0; /* new mbuf, so no offset */
1269 offset += newlen; /* we are now this far into
1270 * the packet */
1271 resid -= newlen; /* so there is this much left
1272 * to get */
1273 continue;
1274 }
1275 /*
1276 * If there is more than enough space in the mbuf to hold
1277 * the contents of this buffer, copy everything in, advance
1278 * pointers, and so on.
1279 */
1280 if (thislen < m->m_len - thismboff) {
1281 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1282 mtod(m, caddr_t) +thismboff, (unsigned) thislen);
1283 thismboff += thislen; /* we are this far into the
1284 * mbuf */
1285 resid -= thislen; /* and this much is left */
1286 goto nextbuf;
1287 }
1288 /*
1289 * Otherwise, there is exactly enough space to put this
1290 * buffer's contents into the current mbuf. Do the
1291 * combination of the above actions.
1292 */
1293 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1294 mtod(m, caddr_t) + thismboff, (unsigned) thislen);
1295 m = m->m_next;
1296 thismboff = 0; /* new mbuf, start at the beginning */
1297 resid -= thislen; /* and we are this far through */
1298
1299 /*
1300 * Advance all the pointers. We can get here from either of
1301 * the last two cases, but never the first.
1302 */
1303nextbuf:
1304 offset = 0;
1305 ie->rbuffs[head]->ie_rbd_actual = 0;
1306 ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
1307 ie->rbhead = head = (head + 1) % ie->nrxbufs;
1308 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1309 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1310 }
1311
1312 /*
1313 * Unless something changed strangely while we were doing the copy,
1314 * we have now copied everything in from the shared memory. This
1315 * means that we are done.
1316 */
1317 return (0);
1318}
1319
1320/*
1321 * Read frame NUM from unit UNIT (pre-cached as IE).
1322 *
1323 * This routine reads the RFD at NUM, and copies in the buffers from
1324 * the list of RBD, then rotates the RBD and RFD lists so that the receiver
1325 * doesn't start complaining. Trailers are DROPPED---there's no point
1326 * in wasting time on confusing code to deal with them. Hopefully,
1327 * this machine will never ARP for trailers anyway.
1328 */
1329static void
1330ie_readframe(int unit, struct ie_softc *ie, int num/* frame number to read */)
1331{
1332 struct ie_recv_frame_desc rfd;
1333 struct mbuf *m = 0;
1334 struct ether_header eh;
1335
1336 bcopy((v_caddr_t) (ie->rframes[num]), &rfd,
1337 sizeof(struct ie_recv_frame_desc));
1338
1339 /*
1340 * Immediately advance the RFD list, since we we have copied ours
1341 * now.
1342 */
1343 ie->rframes[num]->ie_fd_status = 0;
1344 ie->rframes[num]->ie_fd_last |= IE_FD_LAST;
1345 ie->rframes[ie->rftail]->ie_fd_last &= ~IE_FD_LAST;
1346 ie->rftail = (ie->rftail + 1) % ie->nframes;
1347 ie->rfhead = (ie->rfhead + 1) % ie->nframes;
1348
1349 if (rfd.ie_fd_status & IE_FD_OK) {
1350 if (ieget(unit, ie, &m, &eh)) {
1351 ie->arpcom.ac_if.if_ierrors++; /* this counts as an
1352 * error */
1353 return;
1354 }
1355 }
1356#ifdef DEBUG
1357 if (ie_debug & IED_READFRAME) {
1358 printf("ie%d: frame from ether %6D type %x\n", unit,
1359 eh.ether_shost, ":", (unsigned) eh.ether_type);
1360 }
1361 if (ntohs(eh.ether_type) > ETHERTYPE_TRAIL
1362 && ntohs(eh.ether_type) < (ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER))
1363 printf("received trailer!\n");
1364#endif
1365
1366 if (!m)
1367 return;
1368
1369 /*
1370 * Finally pass this packet up to higher layers.
1371 */
1372 ether_input(&ie->arpcom.ac_if, &eh, m);
1373}
1374
1375static void
1376ie_drop_packet_buffer(int unit, struct ie_softc * ie)
1377{
1378 int i;
1379
1380 do {
1381 /*
1382 * This means we are somehow out of sync. So, we reset the
1383 * adapter.
1384 */
1385 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1386#ifdef DEBUG
1387 print_rbd(ie->rbuffs[ie->rbhead]);
1388#endif
1389 log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
1390 unit, ie->rbhead);
1391 iereset(unit);
1392 return;
1393 }
1394 i = ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_LAST;
1395
1396 ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
1397 ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
1398 ie->rbhead = (ie->rbhead + 1) % ie->nrxbufs;
1399 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1400 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1401 } while (!i);
1402}
1403
1404
1405/*
1406 * Start transmission on an interface.
1407 */
1408static void
1409iestart(struct ifnet *ifp)
1410{
1411 struct ie_softc *ie = ifp->if_softc;
1412 struct mbuf *m0, *m;
1413 volatile unsigned char *buffer;
1414 u_short len;
1415
1416 /*
1417 * This is not really volatile, in this routine, but it makes gcc
1418 * happy.
1419 */
1420 volatile u_short *bptr = &ie->scb->ie_command_list;
1421
1422 if (!(ifp->if_flags & IFF_RUNNING))
1423 return;
1424 if (ifp->if_flags & IFF_OACTIVE)
1425 return;
1426
1427 do {
2c4ce138
JS
1428 m = ifq_dequeue(&ie->arpcom.ac_if.if_snd);
1429 if (m == NULL)
984263bc
MD
1430 break;
1431
1432 buffer = ie->xmit_cbuffs[ie->xmit_count];
1433 len = 0;
1434
1435 for (m0 = m; m && len < IE_BUF_LEN; m = m->m_next) {
1436 bcopy(mtod(m, caddr_t), buffer, m->m_len);
1437 buffer += m->m_len;
1438 len += m->m_len;
1439 }
1440
1441 m_freem(m0);
1442 len = max(len, ETHER_MIN_LEN);
1443
1444 /*
1445 * See if bpf is listening on this interface, let it see the
1446 * packet before we commit it to the wire.
1447 */
c633dd13
JS
1448 BPF_TAP(&ie->arpcom.ac_if,
1449 __DEVOLATILE(u_char *, ie->xmit_cbuffs[ie->xmit_count]),
1450 len);
984263bc
MD
1451
1452 ie->xmit_buffs[ie->xmit_count]->ie_xmit_flags =
1453 IE_XMIT_LAST|len;
1454 ie->xmit_buffs[ie->xmit_count]->ie_xmit_next = 0xffff;
1455 ie->xmit_buffs[ie->xmit_count]->ie_xmit_buf =
1456 MK_24(ie->iomem, ie->xmit_cbuffs[ie->xmit_count]);
1457
1458 ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_cmd = IE_CMD_XMIT;
1459 ie->xmit_cmds[ie->xmit_count]->ie_xmit_status = 0;
1460 ie->xmit_cmds[ie->xmit_count]->ie_xmit_desc =
1461 MK_16(ie->iomem, ie->xmit_buffs[ie->xmit_count]);
1462
1463 *bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
1464 bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
1465 ie->xmit_count++;
1466 } while (ie->xmit_count < ie->ntxbufs);
1467
1468 /*
1469 * If we queued up anything for transmission, send it.
1470 */
1471 if (ie->xmit_count) {
1472 ie->xmit_cmds[ie->xmit_count - 1]->com.ie_cmd_cmd |=
1473 IE_CMD_LAST | IE_CMD_INTR;
1474
1475 /*
1476 * By passing the command pointer as a null, we tell
1477 * command_and_wait() to pretend that this isn't an action
1478 * command. I wish I understood what was happening here.
1479 */
3e4a09e7 1480 command_and_wait(ifp->if_dunit, IE_CU_START, 0, 0);
984263bc
MD
1481 ifp->if_flags |= IFF_OACTIVE;
1482 }
1483 return;
1484}
1485
1486/*
1487 * Check to see if there's an 82586 out there.
1488 */
1489static int
1490check_ie_present(int unit, caddr_t where, unsigned size)
1491{
1492 volatile struct ie_sys_conf_ptr *scp;
1493 volatile struct ie_int_sys_conf_ptr *iscp;
1494 volatile struct ie_sys_ctl_block *scb;
1495 u_long realbase;
984263bc 1496
ec15e0df 1497 crit_exit();
984263bc
MD
1498
1499 realbase = (uintptr_t) where + size - (1 << 24);
1500
1501 scp = (volatile struct ie_sys_conf_ptr *) (uintptr_t)
1502 (realbase + IE_SCP_ADDR);
1503 bzero((volatile char *) scp, sizeof *scp);
1504
1505 /*
1506 * First we put the ISCP at the bottom of memory; this tests to make
1507 * sure that our idea of the size of memory is the same as the
1508 * controller's. This is NOT where the ISCP will be in normal
1509 * operation.
1510 */
1511 iscp = (volatile struct ie_int_sys_conf_ptr *) where;
1512 bzero((volatile char *)iscp, sizeof *iscp);
1513
1514 scb = (volatile struct ie_sys_ctl_block *) where;
1515 bzero((volatile char *)scb, sizeof *scb);
1516
1517 scp->ie_bus_use = ie_softc[unit].bus_use; /* 8-bit or 16-bit */
1518 scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1519 ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1520
1521 iscp->ie_busy = 1;
1522 iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
1523
1524 (*ie_softc[unit].ie_reset_586) (unit);
1525 (*ie_softc[unit].ie_chan_attn) (unit);
1526
1527 DELAY(100); /* wait a while... */
1528
1529 if (iscp->ie_busy) {
ec15e0df 1530 crit_exit();
984263bc
MD
1531 return (0);
1532 }
1533 /*
1534 * Now relocate the ISCP to its real home, and reset the controller
1535 * again.
1536 */
1537 iscp = (void *) Align((caddr_t) (uintptr_t)
1538 (realbase + IE_SCP_ADDR -
1539 sizeof(struct ie_int_sys_conf_ptr)));
1540 bzero((volatile char *) iscp, sizeof *iscp); /* ignore cast-qual */
1541
1542 scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1543 ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1544
1545 iscp->ie_busy = 1;
1546 iscp->ie_scb_offset = MK_16(realbase, scb);
1547
1548 (*ie_softc[unit].ie_reset_586) (unit);
1549 (*ie_softc[unit].ie_chan_attn) (unit);
1550
1551 DELAY(100);
1552
1553 if (iscp->ie_busy) {
ec15e0df 1554 crit_exit();
984263bc
MD
1555 return (0);
1556 }
1557 ie_softc[unit].iosize = size;
1558 ie_softc[unit].iomem = (caddr_t) (uintptr_t) realbase;
1559
1560 ie_softc[unit].iscp = iscp;
1561 ie_softc[unit].scb = scb;
1562
1563 /*
1564 * Acknowledge any interrupts we may have caused...
1565 */
1566 ie_ack(scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
ec15e0df
JS
1567
1568 crit_exit();
984263bc
MD
1569
1570 return (1);
1571}
1572
1573/*
1574 * Divine the memory size of ie board UNIT.
1575 * Better hope there's nothing important hiding just below the ie card...
1576 */
1577static void
1578find_ie_mem_size(int unit)
1579{
1580 unsigned size;
1581
1582 ie_softc[unit].iosize = 0;
1583
1584 for (size = 65536; size >= 8192; size -= 8192) {
1585 if (check_ie_present(unit, ie_softc[unit].iomembot, size)) {
1586 return;
1587 }
1588 }
1589
1590 return;
1591}
1592
1593void
1594el_reset_586(int unit)
1595{
1596 outb(PORT + IE507_CTRL, EL_CTRL_RESET);
1597 DELAY(100);
1598 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
1599 DELAY(100);
1600}
1601
1602void
1603sl_reset_586(int unit)
1604{
1605 outb(PORT + IEATT_RESET, 0);
1606}
1607
1608void
1609ee16_reset_586(int unit)
1610{
1611 outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
1612 DELAY(100);
1613 outb(PORT + IEE16_ECTRL, 0);
1614 DELAY(100);
1615}
1616
1617void
1618el_chan_attn(int unit)
1619{
1620 outb(PORT + IE507_ATTN, 1);
1621}
1622
1623void
1624sl_chan_attn(int unit)
1625{
1626 outb(PORT + IEATT_ATTN, 0);
1627}
1628
1629void
1630ee16_chan_attn(int unit)
1631{
1632 outb(PORT + IEE16_ATTN, 0);
1633}
1634
1635u_short
1636ee16_read_eeprom(struct ie_softc *sc, int location)
1637{
1638 int ectrl, edata;
1639
1640 ectrl = inb(sc->port + IEE16_ECTRL);
1641 ectrl &= IEE16_ECTRL_MASK;
1642 ectrl |= IEE16_ECTRL_EECS;
1643 outb(sc->port + IEE16_ECTRL, ectrl);
1644
1645 ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
1646 ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
1647 edata = ee16_eeprom_inbits(sc);
1648 ectrl = inb(sc->port + IEE16_ECTRL);
1649 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
1650 outb(sc->port + IEE16_ECTRL, ectrl);
1651 ee16_eeprom_clock(sc, 1);
1652 ee16_eeprom_clock(sc, 0);
1653 return edata;
1654}
1655
1656void
1657ee16_eeprom_outbits(struct ie_softc *sc, int edata, int count)
1658{
1659 int ectrl, i;
1660
1661 ectrl = inb(sc->port + IEE16_ECTRL);
1662 ectrl &= ~IEE16_RESET_ASIC;
1663 for (i = count - 1; i >= 0; i--) {
1664 ectrl &= ~IEE16_ECTRL_EEDI;
1665 if (edata & (1 << i)) {
1666 ectrl |= IEE16_ECTRL_EEDI;
1667 }
1668 outb(sc->port + IEE16_ECTRL, ectrl);
1669 DELAY(1); /* eeprom data must be setup for 0.4 uSec */
1670 ee16_eeprom_clock(sc, 1);
1671 ee16_eeprom_clock(sc, 0);
1672 }
1673 ectrl &= ~IEE16_ECTRL_EEDI;
1674 outb(sc->port + IEE16_ECTRL, ectrl);
1675 DELAY(1); /* eeprom data must be held for 0.4 uSec */
1676}
1677
1678int
1679ee16_eeprom_inbits(struct ie_softc *sc)
1680{
1681 int ectrl, edata, i;
1682
1683 ectrl = inb(sc->port + IEE16_ECTRL);
1684 ectrl &= ~IEE16_RESET_ASIC;
1685 for (edata = 0, i = 0; i < 16; i++) {
1686 edata = edata << 1;
1687 ee16_eeprom_clock(sc, 1);
1688 ectrl = inb(sc->port + IEE16_ECTRL);
1689 if (ectrl & IEE16_ECTRL_EEDO) {
1690 edata |= 1;
1691 }
1692 ee16_eeprom_clock(sc, 0);
1693 }
1694 return (edata);
1695}
1696
1697void
1698ee16_eeprom_clock(struct ie_softc *sc, int state)
1699{
1700 int ectrl;
1701
1702 ectrl = inb(sc->port + IEE16_ECTRL);
1703 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
1704 if (state) {
1705 ectrl |= IEE16_ECTRL_EESK;
1706 }
1707 outb(sc->port + IEE16_ECTRL, ectrl);
1708 DELAY(9); /* EESK must be stable for 8.38 uSec */
1709}
1710
1711static __inline void
1712ee16_interrupt_enable(struct ie_softc *sc)
1713{
1714 DELAY(100);
1715 outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
1716 DELAY(100);
1717}
1718
1719void
1720sl_read_ether(int unit, unsigned char addr[6])
1721{
1722 int i;
1723
1724 for (i = 0; i < 6; i++)
1725 addr[i] = inb(PORT + i);
1726}
1727
1728
1729static void
1730iereset(int unit)
1731{
ec15e0df 1732 crit_enter();
984263bc
MD
1733
1734 if (unit >= NIE) {
ec15e0df 1735 crit_exit();
984263bc
MD
1736 return;
1737 }
1738 printf("ie%d: reset\n", unit);
1739 ie_softc[unit].arpcom.ac_if.if_flags &= ~IFF_UP;
bd4539cc 1740 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
984263bc
MD
1741
1742 /*
1743 * Stop i82586 dead in its tracks.
1744 */
1745 if (command_and_wait(unit, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
1746 printf("ie%d: abort commands timed out\n", unit);
1747
1748 if (command_and_wait(unit, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
1749 printf("ie%d: disable commands timed out\n", unit);
1750
1751#ifdef notdef
1752 if (!check_ie_present(unit, ie_softc[unit].iomembot,
1753 e_softc[unit].iosize))
1754 panic("ie disappeared!");
1755#endif
1756
1757 ie_softc[unit].arpcom.ac_if.if_flags |= IFF_UP;
bd4539cc 1758 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
984263bc 1759
ec15e0df 1760 crit_exit();
984263bc
MD
1761}
1762
984263bc
MD
1763/*
1764 * Send a command to the controller and wait for it to either
1765 * complete or be accepted, depending on the command. If the
1766 * command pointer is null, then pretend that the command is
1767 * not an action command. If the command pointer is not null,
1768 * and the command is an action command, wait for
1769 * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
1770 * to become true.
1771 */
1772static int
1773command_and_wait(int unit, int cmd, volatile void *pcmd, int mask)
1774{
1775 volatile struct ie_cmd_common *cc = pcmd;
984263bc
MD
1776
1777 ie_softc[unit].scb->ie_command = (u_short) cmd;
1778
1779 if (IE_ACTION_COMMAND(cmd) && pcmd) {
984263bc
MD
1780 /*
1781 * According to the packet driver, the minimum timeout
163f45a6 1782 * should be .369 seconds.
984263bc 1783 */
163f45a6 1784 int timer = 370;
984263bc 1785
92e62798
JS
1786 (*ie_softc[unit].ie_chan_attn) (unit);
1787
984263bc
MD
1788 /*
1789 * Now spin-lock waiting for status. This is not a very
1790 * nice thing to do, but I haven't figured out how, or
1791 * indeed if, we can put the process waiting for action to
1792 * sleep. (We may be getting called through some other
1793 * timeout running in the kernel.)
1794 */
163f45a6
JS
1795 while (--timer > 0) {
1796 if (cc->ie_cmd_status & mask)
984263bc 1797 break;
163f45a6 1798 DELAY(1000);
984263bc 1799 }
163f45a6
JS
1800 if (timer == 0)
1801 return(1);
1802 else
1803 return(0);
984263bc
MD
1804 } else {
1805
1806 /*
1807 * Otherwise, just wait for the command to be accepted.
1808 */
1809 (*ie_softc[unit].ie_chan_attn) (unit);
1810
1811 while (ie_softc[unit].scb->ie_command); /* spin lock */
1812
1813 return (0);
1814 }
1815}
1816
1817/*
1818 * Run the time-domain reflectometer...
1819 */
1820static void
1821run_tdr(int unit, volatile struct ie_tdr_cmd *cmd)
1822{
1823 int result;
1824
1825 cmd->com.ie_cmd_status = 0;
1826 cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
1827 cmd->com.ie_cmd_link = 0xffff;
1828 cmd->ie_tdr_time = 0;
1829
1830 ie_softc[unit].scb->ie_command_list = MK_16(MEM, cmd);
1831 cmd->ie_tdr_time = 0;
1832
1833 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL))
1834 result = 0x2000;
1835 else
1836 result = cmd->ie_tdr_time;
1837
1838 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit,
1839 ie_softc[unit].ie_chan_attn);
1840
1841 if (result & IE_TDR_SUCCESS)
1842 return;
1843
1844 if (result & IE_TDR_XCVR) {
1845 printf("ie%d: transceiver problem\n", unit);
1846 } else if (result & IE_TDR_OPEN) {
1847 printf("ie%d: TDR detected an open %d clocks away\n", unit,
1848 result & IE_TDR_TIME);
1849 } else if (result & IE_TDR_SHORT) {
1850 printf("ie%d: TDR detected a short %d clocks away\n", unit,
1851 result & IE_TDR_TIME);
1852 } else {
1853 printf("ie%d: TDR returned unknown status %x\n", unit, result);
1854 }
1855}
1856
1857static void
1858start_receiver(int unit)
1859{
ec15e0df 1860 crit_enter();
984263bc
MD
1861
1862 ie_softc[unit].scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1863 command_and_wait(unit, IE_RU_START, 0, 0);
1864
1865 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1866
ec15e0df 1867 crit_exit();
984263bc
MD
1868}
1869
1870/*
1871 * Here is a helper routine for iernr() and ieinit(). This sets up
1872 * the RFA.
1873 */
1874static v_caddr_t
1875setup_rfa(v_caddr_t ptr, struct ie_softc * ie)
1876{
1877 volatile struct ie_recv_frame_desc *rfd = (volatile void *)ptr;
1878 volatile struct ie_recv_buf_desc *rbd;
1879 int i;
1880 int unit = ie - &ie_softc[0];
1881
1882 /* First lay them out */
1883 for (i = 0; i < ie->nframes; i++) {
1884 ie->rframes[i] = rfd;
1885 bzero((volatile char *) rfd, sizeof *rfd); /* ignore cast-qual */
1886 rfd++;
1887 }
1888
1889 ptr = Alignvol(rfd); /* ignore cast-qual */
1890
1891 /* Now link them together */
1892 for (i = 0; i < ie->nframes; i++) {
1893 ie->rframes[i]->ie_fd_next =
1894 MK_16(MEM, ie->rframes[(i + 1) % ie->nframes]);
1895 }
1896
1897 /* Finally, set the EOL bit on the last one. */
1898 ie->rframes[ie->nframes - 1]->ie_fd_last |= IE_FD_LAST;
1899
1900 /*
1901 * Now lay out some buffers for the incoming frames. Note that we
1902 * set aside a bit of slop in each buffer, to make sure that we have
1903 * enough space to hold a single frame in every buffer.
1904 */
1905 rbd = (volatile void *) ptr;
1906
1907 for (i = 0; i < ie->nrxbufs; i++) {
1908 ie->rbuffs[i] = rbd;
1909 bzero((volatile char *)rbd, sizeof *rbd);
1910 ptr = Alignvol(ptr + sizeof *rbd);
1911 rbd->ie_rbd_length = IE_RBUF_SIZE;
1912 rbd->ie_rbd_buffer = MK_24(MEM, ptr);
1913 ie->cbuffs[i] = (volatile void *) ptr;
1914 ptr += IE_RBUF_SIZE;
1915 rbd = (volatile void *) ptr;
1916 }
1917
1918 /* Now link them together */
1919 for (i = 0; i < ie->nrxbufs; i++) {
1920 ie->rbuffs[i]->ie_rbd_next =
1921 MK_16(MEM, ie->rbuffs[(i + 1) % ie->nrxbufs]);
1922 }
1923
1924 /* Tag EOF on the last one */
1925 ie->rbuffs[ie->nrxbufs - 1]->ie_rbd_length |= IE_RBD_LAST;
1926
1927 /*
1928 * We use the head and tail pointers on receive to keep track of the
1929 * order in which RFDs and RBDs are used.
1930 */
1931 ie->rfhead = 0;
1932 ie->rftail = ie->nframes - 1;
1933 ie->rbhead = 0;
1934 ie->rbtail = ie->nrxbufs - 1;
1935
1936 ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
1937 ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
1938
1939 ptr = Alignvol(ptr);
1940 return (ptr);
1941}
1942
1943/*
1944 * Run the multicast setup command.
984263bc
MD
1945 */
1946static int
1947mc_setup(int unit, v_caddr_t ptr,
1948 volatile struct ie_sys_ctl_block * scb)
1949{
1950 struct ie_softc *ie = &ie_softc[unit];
1951 volatile struct ie_mcast_cmd *cmd = (volatile void *) ptr;
1952
1953 cmd->com.ie_cmd_status = 0;
1954 cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
1955 cmd->com.ie_cmd_link = 0xffff;
1956
1957 /* ignore cast-qual */
1958 bcopy((v_caddr_t) ie->mcast_addrs, (v_caddr_t) cmd->ie_mcast_addrs,
1959 ie->mcast_count * sizeof *ie->mcast_addrs);
1960
1961 cmd->ie_mcast_bytes = ie->mcast_count * 6; /* grrr... */
1962
1963 scb->ie_command_list = MK_16(MEM, cmd);
1964 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
1965 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1966 printf("ie%d: multicast address setup command failed\n", unit);
1967 return (0);
1968 }
1969 return (1);
1970}
1971
1972/*
1973 * This routine takes the environment generated by check_ie_present()
1974 * and adds to it all the other structures we need to operate the adapter.
1975 * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
1976 * starting the receiver unit, and clearing interrupts.
984263bc
MD
1977 */
1978static void
1979ieinit(xsc)
1980 void *xsc;
1981{
1982 struct ie_softc *ie = xsc;
1983 volatile struct ie_sys_ctl_block *scb = ie->scb;
1984 v_caddr_t ptr;
1985 int i;
1986 int unit = ie->unit;
1987
ec15e0df
JS
1988 crit_enter();
1989
984263bc
MD
1990 ptr = Alignvol((volatile char *) scb + sizeof *scb);
1991
1992 /*
1993 * Send the configure command first.
1994 */
1995 {
1996 volatile struct ie_config_cmd *cmd = (volatile void *) ptr;
1997
1998 ie_setup_config(cmd, ie->promisc,
1999 ie->hard_type == IE_STARLAN10);
2000 cmd->com.ie_cmd_status = 0;
2001 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
2002 cmd->com.ie_cmd_link = 0xffff;
2003
2004 scb->ie_command_list = MK_16(MEM, cmd);
2005
2006 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2007 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
ec15e0df 2008 crit_exit();
984263bc
MD
2009 printf("ie%d: configure command failed\n", unit);
2010 return;
2011 }
2012 }
2013 /*
2014 * Now send the Individual Address Setup command.
2015 */
2016 {
2017 volatile struct ie_iasetup_cmd *cmd = (volatile void *) ptr;
2018
2019 cmd->com.ie_cmd_status = 0;
2020 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
2021 cmd->com.ie_cmd_link = 0xffff;
2022
2023 bcopy((volatile char *)ie_softc[unit].arpcom.ac_enaddr,
2024 (volatile char *)&cmd->ie_address, sizeof cmd->ie_address);
2025 scb->ie_command_list = MK_16(MEM, cmd);
2026 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2027 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
ec15e0df 2028 crit_exit();
984263bc
MD
2029 printf("ie%d: individual address "
2030 "setup command failed\n", unit);
2031 return;
2032 }
2033 }
2034
2035 /*
2036 * Now run the time-domain reflectometer.
2037 */
2038 run_tdr(unit, (volatile void *) ptr);
2039
2040 /*
2041 * Acknowledge any interrupts we have generated thus far.
2042 */
2043 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
2044
2045 /*
2046 * Set up the RFA.
2047 */
2048 ptr = setup_rfa(ptr, ie);
2049
2050 /*
2051 * Finally, the transmit command and buffer are the last little bit
2052 * of work.
2053 */
2054
2055 /* transmit command buffers */
2056 for (i = 0; i < ie->ntxbufs; i++) {
2057 ie->xmit_cmds[i] = (volatile void *) ptr;
2058 ptr += sizeof *ie->xmit_cmds[i];
2059 ptr = Alignvol(ptr);
2060 ie->xmit_buffs[i] = (volatile void *)ptr;
2061 ptr += sizeof *ie->xmit_buffs[i];
2062 ptr = Alignvol(ptr);
2063 }
2064
2065 /* transmit buffers */
2066 for (i = 0; i < ie->ntxbufs - 1; i++) {
2067 ie->xmit_cbuffs[i] = (volatile void *)ptr;
2068 ptr += IE_BUF_LEN;
2069 ptr = Alignvol(ptr);
2070 }
2071 ie->xmit_cbuffs[ie->ntxbufs - 1] = (volatile void *) ptr;
2072
2073 for (i = 1; i < ie->ntxbufs; i++) {
2074 bzero((v_caddr_t) ie->xmit_cmds[i], sizeof *ie->xmit_cmds[i]);
2075 bzero((v_caddr_t) ie->xmit_buffs[i], sizeof *ie->xmit_buffs[i]);
2076 }
2077
2078 /*
2079 * This must be coordinated with iestart() and ietint().
2080 */
2081 ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
2082
2083 /* take the ee16 out of loopback */
2084 if (ie->hard_type == IE_EE16) {
2085 u_int8_t bart_config;
2086
2087 bart_config = inb(PORT + IEE16_CONFIG);
2088 bart_config &= ~IEE16_BART_LOOPBACK;
2089 /* inb doesn't get bit! */
2090 bart_config |= IEE16_BART_MCS16_TEST;
2091 outb(PORT + IEE16_CONFIG, bart_config);
2092 ee16_interrupt_enable(ie);
2093 ee16_chan_attn(unit);
2094 }
2095 ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels
2096 * we're here */
2097 start_receiver(unit);
2098
ec15e0df 2099 crit_exit();
984263bc
MD
2100}
2101
2102static void
2103ie_stop(int unit)
2104{
2105 command_and_wait(unit, IE_RU_DISABLE, 0, 0);
2106}
2107
2108static int
bd4539cc 2109ieioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
984263bc 2110{
ec15e0df 2111 int error = 0;
984263bc 2112
ec15e0df 2113 crit_enter();
984263bc
MD
2114
2115 switch (command) {
984263bc
MD
2116 case SIOCSIFFLAGS:
2117 /*
2118 * Note that this device doesn't have an "all multicast"
2119 * mode, so we must turn on promiscuous mode and do the
2120 * filtering manually.
2121 */
2122 if ((ifp->if_flags & IFF_UP) == 0 &&
2123 (ifp->if_flags & IFF_RUNNING)) {
2124 ifp->if_flags &= ~IFF_RUNNING;
3e4a09e7 2125 ie_stop(ifp->if_dunit);
984263bc
MD
2126 } else if ((ifp->if_flags & IFF_UP) &&
2127 (ifp->if_flags & IFF_RUNNING) == 0) {
3e4a09e7 2128 ie_softc[ifp->if_dunit].promisc =
984263bc
MD
2129 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2130 ieinit(ifp->if_softc);
3e4a09e7 2131 } else if (ie_softc[ifp->if_dunit].promisc ^
984263bc 2132 (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))) {
3e4a09e7 2133 ie_softc[ifp->if_dunit].promisc =
984263bc
MD
2134 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2135 ieinit(ifp->if_softc);
2136 }
2137 break;
2138
2139 case SIOCADDMULTI:
2140 case SIOCDELMULTI:
2141 /*
2142 * Update multicast listeners
2143 */
2144 /* reset multicast filtering */
3e4a09e7 2145 ie_mc_reset(ifp->if_dunit);
984263bc
MD
2146 error = 0;
2147 break;
2148
2149 default:
4cde4dd5
JS
2150 error = ether_ioctl(ifp, command, data);
2151 break;
984263bc
MD
2152 }
2153
ec15e0df 2154 crit_exit();
984263bc
MD
2155 return (error);
2156}
2157
2158static void
2159ie_mc_reset(int unit)
2160{
2161 struct ie_softc *ie = &ie_softc[unit];
2162 struct ifmultiaddr *ifma;
2163
2164 /*
2165 * Step through the list of addresses.
2166 */
2167 ie->mcast_count = 0;
2168 for (ifma = ie->arpcom.ac_if.if_multiaddrs.lh_first; ifma;
2169 ifma = ifma->ifma_link.le_next) {
2170 if (ifma->ifma_addr->sa_family != AF_LINK)
2171 continue;
2172
2173 /* XXX - this is broken... */
2174 if (ie->mcast_count >= MAXMCAST) {
2175 ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
bd4539cc
JH
2176 ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *) 0,
2177 (struct ucred *)NULL);
984263bc
MD
2178 goto setflag;
2179 }
2180 bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
2181 &(ie->mcast_addrs[ie->mcast_count]), 6);
2182 ie->mcast_count++;
2183 }
2184
2185setflag:
2186 ie->want_mcsetup = 1;
2187}
2188
2189
2190#ifdef DEBUG
2191static void
2192print_rbd(volatile struct ie_recv_buf_desc * rbd)
2193{
2194 printf("RBD at %p:\n"
2195 "actual %04x, next %04x, buffer %p\n"
2196 "length %04x, mbz %04x\n",
2197 (volatile void *) rbd,
2198 rbd->ie_rbd_actual, rbd->ie_rbd_next,
2199 (void *) rbd->ie_rbd_buffer,
2200 rbd->ie_rbd_length, rbd->mbz);
2201}
2202
2203#endif /* DEBUG */