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