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