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