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