d45720a4da9ab6f81abd50757c7d71036f99f1d0
[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.16 2004/09/15 20:05:13 joerg Exp $
52  */
53
54 /*
55  * Intel 82586 Ethernet chip
56  * Register, bit, and structure definitions.
57  *
58  * Written by GAW with reference to the Clarkson Packet Driver code for this
59  * chip written by Russ Nelson and others.
60  *
61  * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
62  */
63
64 /*
65  * The i82586 is a very versatile chip, found in many implementations.
66  * Programming this chip is mostly the same, but certain details differ
67  * from card to card.  This driver is written so that different cards
68  * can be automatically detected at run-time.
69  */
70
71 /*
72 Mode of operation:
73
74 We run the 82586 in a standard Ethernet mode.  We keep NFRAMES received
75 frame descriptors around for the receiver to use, and NRXBUFS associated
76 receive buffer descriptors, both in a circular list.  Whenever a frame is
77 received, we rotate both lists as necessary.  (The 586 treats both lists
78 as a simple queue.)  We also keep a transmit command around so that packets
79 can be sent off quickly.
80
81 We configure the adapter in AL-LOC = 1 mode, which means that the
82 Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
83 rather than being split off into various fields in the RFD.  This also
84 means that we must include this header in the transmit buffer as well.
85
86 By convention, all transmit commands, and only transmit commands, shall
87 have the I (IE_CMD_INTR) bit set in the command.  This way, when an
88 interrupt arrives at ieintr(), it is immediately possible to tell
89 what precisely caused it.  ANY OTHER command-sending routines should
90 run at splimp(), and should post an acknowledgement to every interrupt
91 they generate.
92
93 The 82586 has a 24-bit address space internally, and the adaptor's memory
94 is located at the top of this region.  However, the value we are given in
95 configuration is normally the *bottom* of the adaptor RAM.  So, we must go
96 through a few gyrations to come up with a kernel virtual address which
97 represents the actual beginning of the 586 address space.  First, we
98 autosize the RAM by running through several possible sizes and trying to
99 initialize the adapter under the assumption that the selected size is
100 correct.  Then, knowing the correct RAM size, we set up our pointers in
101 ie_softc[unit].  `iomem' represents the computed base of the 586 address
102 space.  `iomembot' represents the actual configured base of adapter RAM.
103 Finally, `iosize' represents the calculated size of 586 RAM.  Then, when
104 laying out commands, we use the interval [iomembot, iomembot + iosize); to
105 make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
106 iomem and and with 0xffff.
107
108 */
109
110 #include "use_ie.h"
111 #include "opt_inet.h"
112 #include "opt_ipx.h"
113
114 #include <sys/param.h>
115 #include <sys/systm.h>
116 #include <sys/eventhandler.h>
117 #include <sys/kernel.h>
118 #include <sys/malloc.h>
119 #include <sys/conf.h>
120 #include <sys/mbuf.h>
121 #include <sys/socket.h>
122 #include <sys/sockio.h>
123 #include <sys/syslog.h>
124
125 #include <net/ethernet.h>
126 #include <net/if.h>
127 #include <net/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                         struct ucred *);
176 static void     iestart(struct ifnet * ifp);
177
178 static void     el_reset_586(int unit);
179 static void     el_chan_attn(int unit);
180
181 static void     sl_reset_586(int unit);
182 static void     sl_chan_attn(int unit);
183
184 static void     ee16_reset_586(int unit);
185 static void     ee16_chan_attn(int unit);
186 static __inline void ee16_interrupt_enable(struct ie_softc * ie);
187 static void     ee16_eeprom_outbits(struct ie_softc * ie, int edata, int cnt);
188 static void     ee16_eeprom_clock(struct ie_softc * ie, int state);
189 static u_short  ee16_read_eeprom(struct ie_softc * ie, int location);
190 static int      ee16_eeprom_inbits(struct ie_softc * ie);
191 static void     ee16_shutdown(void *sc, int howto);
192
193 static void     iereset(int unit);
194 static void     ie_readframe(int unit, struct ie_softc * ie, int bufno);
195 static void     ie_drop_packet_buffer(int unit, struct ie_softc * ie);
196 static void     sl_read_ether(int unit, unsigned char addr[6]);
197 static void     find_ie_mem_size(int unit);
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 %llx "
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 %llx "
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 = malloc(allocsize, M_DEVBUF, M_WAITOK);
801         ie->rbuffs =
802             (volatile struct ie_recv_buf_desc **)&ie->rframes[ie->nframes];
803         ie->cbuffs = (volatile u_char **)&ie->rbuffs[ie->nrxbufs];
804         ie->xmit_cmds =
805             (volatile struct ie_xmit_cmd **)&ie->cbuffs[ie->nrxbufs];
806         ie->xmit_buffs =
807             (volatile struct ie_xmit_buf **)&ie->xmit_cmds[ie->ntxbufs];
808         ie->xmit_cbuffs = (volatile u_char **)&ie->xmit_buffs[ie->ntxbufs];
809
810         ifp->if_softc = ie;
811         if_initname(ifp, iedriver.name, unit);
812         ifp->if_mtu = ETHERMTU;
813         if_printf(ifp, "<%s R%d>", ie_hardware_names[ie->hard_type],
814                   ie->hard_vers + 1);
815
816         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
817         ifp->if_start = iestart;
818         ifp->if_ioctl = ieioctl;
819         ifp->if_init = ieinit;
820         ifp->if_type = IFT_ETHER;
821         ifp->if_addrlen = 6;
822         ifp->if_hdrlen = 14;
823         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
824
825         if (ie->hard_type == IE_EE16)
826                 EVENTHANDLER_REGISTER(shutdown_post_sync, ee16_shutdown,
827                                       ie, SHUTDOWN_PRI_DEFAULT);
828
829         ether_ifattach(ifp, ie->arpcom.ac_enaddr);
830         return (1);
831 }
832
833 /*
834  * What to do upon receipt of an interrupt.
835  */
836 static void
837 ieintr(int unit)
838 {
839         struct ie_softc *ie = &ie_softc[unit];
840         u_short status;
841
842         /* Clear the interrupt latch on the 3C507. */
843         if (ie->hard_type == IE_3C507
844          && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
845                 outb(PORT + IE507_ICTRL, 1);
846
847         /* disable interrupts on the EE16. */
848         if (ie->hard_type == IE_EE16)
849                 outb(PORT + IEE16_IRQ, ie->irq_encoded);
850
851         status = ie->scb->ie_status;
852
853 loop:
854
855         /* Don't ack interrupts which we didn't receive */
856         ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
857
858         if (status & (IE_ST_RECV | IE_ST_RNR)) {
859 #ifdef DEBUG
860                 in_ierint++;
861                 if (ie_debug & IED_RINT)
862                         printf("ie%d: rint\n", unit);
863 #endif
864                 ierint(unit, ie);
865 #ifdef DEBUG
866                 in_ierint--;
867 #endif
868         }
869         if (status & IE_ST_DONE) {
870 #ifdef DEBUG
871                 in_ietint++;
872                 if (ie_debug & IED_TINT)
873                         printf("ie%d: tint\n", unit);
874 #endif
875                 ietint(unit, ie);
876 #ifdef DEBUG
877                 in_ietint--;
878 #endif
879         }
880         if (status & IE_ST_RNR) {
881 #ifdef DEBUG
882                 if (ie_debug & IED_RNR)
883                         printf("ie%d: rnr\n", unit);
884 #endif
885                 iernr(unit, ie);
886         }
887 #ifdef DEBUG
888         if ((status & IE_ST_ALLDONE)
889             && (ie_debug & IED_CNA))
890                 printf("ie%d: cna\n", unit);
891 #endif
892
893         if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
894                 goto loop;
895
896         /* Clear the interrupt latch on the 3C507. */
897         if (ie->hard_type == IE_3C507)
898                 outb(PORT + IE507_ICTRL, 1);
899
900         /* enable interrupts on the EE16. */
901         if (ie->hard_type == IE_EE16)
902                 outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
903
904 }
905
906 /*
907  * Process a received-frame interrupt.
908  */
909 static int
910 ierint(int unit, struct ie_softc *ie)
911 {
912         int     i, status;
913         static int timesthru = 1024;
914
915         i = ie->rfhead;
916         while (1) {
917                 status = ie->rframes[i]->ie_fd_status;
918
919                 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
920                         ie->arpcom.ac_if.if_ipackets++;
921                         if (!--timesthru) {
922                                 ie->arpcom.ac_if.if_ierrors +=
923                                     ie->scb->ie_err_crc +
924                                     ie->scb->ie_err_align +
925                                     ie->scb->ie_err_resource +
926                                     ie->scb->ie_err_overrun;
927                                 ie->scb->ie_err_crc = 0;
928                                 ie->scb->ie_err_align = 0;
929                                 ie->scb->ie_err_resource = 0;
930                                 ie->scb->ie_err_overrun = 0;
931                                 timesthru = 1024;
932                         }
933                         ie_readframe(unit, ie, i);
934                 } else {
935                         if (status & IE_FD_RNR) {
936                                 if (!(ie->scb->ie_status & IE_RU_READY)) {
937                                         ie->rframes[0]->ie_fd_next =
938                                             MK_16(MEM, ie->rbuffs[0]);
939                                         ie->scb->ie_recv_list =
940                                             MK_16(MEM, ie->rframes[0]);
941                                         command_and_wait(unit, IE_RU_START,
942                                                          0, 0);
943                                 }
944                         }
945                         break;
946                 }
947                 i = (i + 1) % ie->nframes;
948         }
949         return (0);
950 }
951
952 /*
953  * Process a command-complete interrupt.  These are only generated by
954  * the transmission of frames.  This routine is deceptively simple, since
955  * most of the real work is done by iestart().
956  */
957 static int
958 ietint(int unit, struct ie_softc *ie)
959 {
960         int     status;
961         int     i;
962
963         ie->arpcom.ac_if.if_timer = 0;
964         ie->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
965
966         for (i = 0; i < ie->xmit_count; i++) {
967                 status = ie->xmit_cmds[i]->ie_xmit_status;
968
969                 if (status & IE_XS_LATECOLL) {
970                         printf("ie%d: late collision\n", unit);
971                         ie->arpcom.ac_if.if_collisions++;
972                         ie->arpcom.ac_if.if_oerrors++;
973                 } else if (status & IE_XS_NOCARRIER) {
974                         printf("ie%d: no carrier\n", unit);
975                         ie->arpcom.ac_if.if_oerrors++;
976                 } else if (status & IE_XS_LOSTCTS) {
977                         printf("ie%d: lost CTS\n", unit);
978                         ie->arpcom.ac_if.if_oerrors++;
979                 } else if (status & IE_XS_UNDERRUN) {
980                         printf("ie%d: DMA underrun\n", unit);
981                         ie->arpcom.ac_if.if_oerrors++;
982                 } else if (status & IE_XS_EXCMAX) {
983                         printf("ie%d: too many collisions\n", unit);
984                         ie->arpcom.ac_if.if_collisions += 16;
985                         ie->arpcom.ac_if.if_oerrors++;
986                 } else {
987                         ie->arpcom.ac_if.if_opackets++;
988                         ie->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
989                 }
990         }
991         ie->xmit_count = 0;
992
993         /*
994          * If multicast addresses were added or deleted while we were
995          * transmitting, ie_mc_reset() set the want_mcsetup flag indicating
996          * that we should do it.
997          */
998         if (ie->want_mcsetup) {
999                 mc_setup(unit, (v_caddr_t) ie->xmit_cbuffs[0], ie->scb);
1000                 ie->want_mcsetup = 0;
1001         }
1002         /* Wish I knew why this seems to be necessary... */
1003         ie->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
1004
1005         iestart(&ie->arpcom.ac_if);
1006         return (0);             /* shouldn't be necessary */
1007 }
1008
1009 /*
1010  * Process a receiver-not-ready interrupt.  I believe that we get these
1011  * when there aren't enough buffers to go around.  For now (FIXME), we
1012  * just restart the receiver, and hope everything's ok.
1013  */
1014 static int
1015 iernr(int unit, struct ie_softc *ie)
1016 {
1017 #ifdef doesnt_work
1018         setup_rfa((v_caddr_t) ie->rframes[0], ie);
1019
1020         ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1021         command_and_wait(unit, IE_RU_START, 0, 0);
1022 #else
1023         /* This doesn't work either, but it doesn't hang either. */
1024         command_and_wait(unit, IE_RU_DISABLE, 0, 0);    /* just in case */
1025         setup_rfa((v_caddr_t) ie->rframes[0], ie);      /* ignore cast-qual */
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);      /* was ENABLE */
1029
1030 #endif
1031         ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
1032
1033         ie->arpcom.ac_if.if_ierrors++;
1034         return (0);
1035 }
1036
1037 /*
1038  * Compare two Ether/802 addresses for equality, inlined and
1039  * unrolled for speed.  I'd love to have an inline assembler
1040  * version of this...
1041  */
1042 static __inline int
1043 ether_equal(u_char * one, u_char * two)
1044 {
1045         if (one[0] != two[0])
1046                 return (0);
1047         if (one[1] != two[1])
1048                 return (0);
1049         if (one[2] != two[2])
1050                 return (0);
1051         if (one[3] != two[3])
1052                 return (0);
1053         if (one[4] != two[4])
1054                 return (0);
1055         if (one[5] != two[5])
1056                 return (0);
1057         return 1;
1058 }
1059
1060 /*
1061  * Determine quickly whether we should bother reading in this packet.
1062  * This depends on whether BPF and/or bridging is enabled, whether we
1063  * are receiving multicast address, and whether promiscuous mode is enabled.
1064  * We assume that if IFF_PROMISC is set, then *somebody* wants to see
1065  * all incoming packets.
1066  */
1067 static __inline int
1068 check_eh(struct ie_softc *ie, struct ether_header *eh)
1069 {
1070         /* Optimize the common case: normal operation. We've received
1071            either a unicast with our dest or a multicast packet. */
1072         if (ie->promisc == 0) {
1073                 int i;
1074
1075                 /* If not multicast, it's definitely for us */
1076                 if ((eh->ether_dhost[0] & 1) == 0)
1077                         return (1);
1078
1079                 /* Accept broadcasts (loose but fast check) */
1080                 if (eh->ether_dhost[0] == 0xff)
1081                         return (1);
1082
1083                 /* Compare against our multicast addresses */
1084                 for (i = 0; i < ie->mcast_count; i++) {
1085                         if (ether_equal(eh->ether_dhost,
1086                             (u_char *)&ie->mcast_addrs[i]))
1087                                 return (1);
1088                 }
1089                 return (0);
1090         }
1091
1092         /* Always accept packets when in promiscuous mode */
1093         if ((ie->promisc & IFF_PROMISC) != 0)
1094                 return (1);
1095
1096         /* Always accept packets directed at us */
1097         if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
1098                 return (1);
1099
1100         /* Must have IFF_ALLMULTI but not IFF_PROMISC set. The chip is
1101            actually in promiscuous mode, so discard unicast packets. */
1102         return((eh->ether_dhost[0] & 1) != 0);
1103 }
1104
1105 /*
1106  * We want to isolate the bits that have meaning...  This assumes that
1107  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
1108  * the size of the buffer, then we are screwed anyway.
1109  */
1110 static __inline int
1111 ie_buflen(struct ie_softc * ie, int head)
1112 {
1113         return (ie->rbuffs[head]->ie_rbd_actual
1114                 & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
1115 }
1116
1117 static __inline int
1118 ie_packet_len(int unit, struct ie_softc * ie)
1119 {
1120         int     i;
1121         int     head = ie->rbhead;
1122         int     acc = 0;
1123
1124         do {
1125                 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1126 #ifdef DEBUG
1127                         print_rbd(ie->rbuffs[ie->rbhead]);
1128 #endif
1129                         log(LOG_ERR,
1130                             "ie%d: receive descriptors out of sync at %d\n",
1131                             unit, ie->rbhead);
1132                         iereset(unit);
1133                         return (-1);
1134                 }
1135                 i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
1136
1137                 acc += ie_buflen(ie, head);
1138                 head = (head + 1) % ie->nrxbufs;
1139         } while (!i);
1140
1141         return (acc);
1142 }
1143
1144 /*
1145  * Read data off the interface, and turn it into an mbuf chain.
1146  *
1147  * This code is DRAMATICALLY different from the previous version; this
1148  * version tries to allocate the entire mbuf chain up front, given the
1149  * length of the data available.  This enables us to allocate mbuf
1150  * clusters in many situations where before we would have had a long
1151  * chain of partially-full mbufs.  This should help to speed up the
1152  * operation considerably.  (Provided that it works, of course.)
1153  */
1154 static __inline int
1155 ieget(int unit, struct ie_softc *ie, struct mbuf **mp, struct ether_header *ehp)
1156 {
1157         struct  mbuf *m, *top, **mymp;
1158         int     i;
1159         int     offset;
1160         int     totlen, resid;
1161         int     thismboff;
1162         int     head;
1163
1164         totlen = ie_packet_len(unit, ie);
1165         if (totlen <= 0)
1166                 return (-1);
1167
1168         i = ie->rbhead;
1169
1170         /*
1171          * Snarf the Ethernet header.
1172          */
1173         bcopy((v_caddr_t) ie->cbuffs[i], (caddr_t) ehp, sizeof *ehp);
1174         /* ignore cast-qual warning here */
1175
1176         /*
1177          * As quickly as possible, check if this packet is for us. If not,
1178          * don't waste a single cycle copying the rest of the packet in.
1179          * This is only a consideration when FILTER is defined; i.e., when
1180          * we are either running BPF or doing multicasting.
1181          */
1182         if (!check_eh(ie, ehp)) {
1183                 ie_drop_packet_buffer(unit, ie);
1184                 ie->arpcom.ac_if.if_ierrors--;  /* just this case, it's not an
1185                                                  * error
1186                                                  */
1187                 return (-1);
1188         }
1189         totlen -= (offset = sizeof *ehp);
1190
1191         MGETHDR(*mp, MB_DONTWAIT, MT_DATA);
1192         if (!*mp) {
1193                 ie_drop_packet_buffer(unit, ie);
1194                 return (-1);
1195         }
1196         m = *mp;
1197         m->m_pkthdr.rcvif = &ie->arpcom.ac_if;
1198         m->m_len = MHLEN;
1199         resid = m->m_pkthdr.len = totlen;
1200         top = 0;
1201         mymp = &top;
1202
1203         /*
1204          * This loop goes through and allocates mbufs for all the data we
1205          * will be copying in.  It does not actually do the copying yet.
1206          */
1207         do {                    /* while(resid > 0) */
1208                 /*
1209                  * Try to allocate an mbuf to hold the data that we have.
1210                  * If we already allocated one, just get another one and
1211                  * stick it on the end (eventually).  If we don't already
1212                  * have one, try to allocate an mbuf cluster big enough to
1213                  * hold the whole packet, if we think it's reasonable, or a
1214                  * single mbuf which may or may not be big enough. Got that?
1215                  */
1216                 if (top) {
1217                         MGET(m, MB_DONTWAIT, MT_DATA);
1218                         if (!m) {
1219                                 m_freem(top);
1220                                 ie_drop_packet_buffer(unit, ie);
1221                                 return (-1);
1222                         }
1223                         m->m_len = MLEN;
1224                 }
1225                 if (resid >= MINCLSIZE) {
1226                         MCLGET(m, MB_DONTWAIT);
1227                         if (m->m_flags & M_EXT)
1228                                 m->m_len = min(resid, MCLBYTES);
1229                 } else {
1230                         if (resid < m->m_len) {
1231                                 if (!top && resid + max_linkhdr <= m->m_len)
1232                                         m->m_data += max_linkhdr;
1233                                 m->m_len = resid;
1234                         }
1235                 }
1236                 resid -= m->m_len;
1237                 *mymp = m;
1238                 mymp = &m->m_next;
1239         } while (resid > 0);
1240
1241         resid = totlen;
1242         m = top;
1243         thismboff = 0;
1244         head = ie->rbhead;
1245
1246         /*
1247          * Now we take the mbuf chain (hopefully only one mbuf most of the
1248          * time) and stuff the data into it.  There are no possible failures
1249          * at or after this point.
1250          */
1251         while (resid > 0) {     /* while there's stuff left */
1252                 int     thislen = ie_buflen(ie, head) - offset;
1253
1254                 /*
1255                  * If too much data for the current mbuf, then fill the
1256                  * current one up, go to the next one, and try again.
1257                  */
1258                 if (thislen > m->m_len - thismboff) {
1259                         int     newlen = m->m_len - thismboff;
1260
1261                         bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1262                               mtod(m, v_caddr_t) +thismboff, (unsigned) newlen);
1263                         /* ignore cast-qual warning */
1264                         m = m->m_next;
1265                         thismboff = 0;  /* new mbuf, so no offset */
1266                         offset += newlen;       /* we are now this far into
1267                                                  * the packet */
1268                         resid -= newlen;        /* so there is this much left
1269                                                  * to get */
1270                         continue;
1271                 }
1272                 /*
1273                  * If there is more than enough space in the mbuf to hold
1274                  * the contents of this buffer, copy everything in, advance
1275                  * pointers, and so on.
1276                  */
1277                 if (thislen < m->m_len - thismboff) {
1278                         bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1279                             mtod(m, caddr_t) +thismboff, (unsigned) thislen);
1280                         thismboff += thislen;   /* we are this far into the
1281                                                  * mbuf */
1282                         resid -= thislen;       /* and this much is left */
1283                         goto nextbuf;
1284                 }
1285                 /*
1286                  * Otherwise, there is exactly enough space to put this
1287                  * buffer's contents into the current mbuf.  Do the
1288                  * combination of the above actions.
1289                  */
1290                 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1291                       mtod(m, caddr_t) + thismboff, (unsigned) thislen);
1292                 m = m->m_next;
1293                 thismboff = 0;          /* new mbuf, start at the beginning */
1294                 resid -= thislen;       /* and we are this far through */
1295
1296                 /*
1297                  * Advance all the pointers.  We can get here from either of
1298                  * the last two cases, but never the first.
1299                  */
1300 nextbuf:
1301                 offset = 0;
1302                 ie->rbuffs[head]->ie_rbd_actual = 0;
1303                 ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
1304                 ie->rbhead = head = (head + 1) % ie->nrxbufs;
1305                 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1306                 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1307         }
1308
1309         /*
1310          * Unless something changed strangely while we were doing the copy,
1311          * we have now copied everything in from the shared memory. This
1312          * means that we are done.
1313          */
1314         return (0);
1315 }
1316
1317 /*
1318  * Read frame NUM from unit UNIT (pre-cached as IE).
1319  *
1320  * This routine reads the RFD at NUM, and copies in the buffers from
1321  * the list of RBD, then rotates the RBD and RFD lists so that the receiver
1322  * doesn't start complaining.  Trailers are DROPPED---there's no point
1323  * in wasting time on confusing code to deal with them.  Hopefully,
1324  * this machine will never ARP for trailers anyway.
1325  */
1326 static void
1327 ie_readframe(int unit, struct ie_softc *ie, int num/* frame number to read */)
1328 {
1329         struct ie_recv_frame_desc rfd;
1330         struct mbuf *m = 0;
1331         struct ether_header eh;
1332
1333         bcopy((v_caddr_t) (ie->rframes[num]), &rfd,
1334               sizeof(struct ie_recv_frame_desc));
1335
1336         /*
1337          * Immediately advance the RFD list, since we we have copied ours
1338          * now.
1339          */
1340         ie->rframes[num]->ie_fd_status = 0;
1341         ie->rframes[num]->ie_fd_last |= IE_FD_LAST;
1342         ie->rframes[ie->rftail]->ie_fd_last &= ~IE_FD_LAST;
1343         ie->rftail = (ie->rftail + 1) % ie->nframes;
1344         ie->rfhead = (ie->rfhead + 1) % ie->nframes;
1345
1346         if (rfd.ie_fd_status & IE_FD_OK) {
1347                 if (ieget(unit, ie, &m, &eh)) {
1348                         ie->arpcom.ac_if.if_ierrors++;  /* this counts as an
1349                                                          * error */
1350                         return;
1351                 }
1352         }
1353 #ifdef DEBUG
1354         if (ie_debug & IED_READFRAME) {
1355                 printf("ie%d: frame from ether %6D type %x\n", unit,
1356                        eh.ether_shost, ":", (unsigned) eh.ether_type);
1357         }
1358         if (ntohs(eh.ether_type) > ETHERTYPE_TRAIL
1359             && ntohs(eh.ether_type) < (ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER))
1360                 printf("received trailer!\n");
1361 #endif
1362
1363         if (!m)
1364                 return;
1365
1366         /*
1367          * Finally pass this packet up to higher layers.
1368          */
1369         ether_input(&ie->arpcom.ac_if, &eh, m);
1370 }
1371
1372 static void
1373 ie_drop_packet_buffer(int unit, struct ie_softc * ie)
1374 {
1375         int     i;
1376
1377         do {
1378                 /*
1379                  * This means we are somehow out of sync.  So, we reset the
1380                  * adapter.
1381                  */
1382                 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1383 #ifdef DEBUG
1384                         print_rbd(ie->rbuffs[ie->rbhead]);
1385 #endif
1386                         log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
1387                             unit, ie->rbhead);
1388                         iereset(unit);
1389                         return;
1390                 }
1391                 i = ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_LAST;
1392
1393                 ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
1394                 ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
1395                 ie->rbhead = (ie->rbhead + 1) % ie->nrxbufs;
1396                 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1397                 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1398         } while (!i);
1399 }
1400
1401
1402 /*
1403  * Start transmission on an interface.
1404  */
1405 static void
1406 iestart(struct ifnet *ifp)
1407 {
1408         struct   ie_softc *ie = ifp->if_softc;
1409         struct   mbuf *m0, *m;
1410         volatile unsigned char *buffer;
1411         u_short  len;
1412
1413         /*
1414          * This is not really volatile, in this routine, but it makes gcc
1415          * happy.
1416          */
1417         volatile u_short *bptr = &ie->scb->ie_command_list;
1418
1419         if (!(ifp->if_flags & IFF_RUNNING))
1420                 return;
1421         if (ifp->if_flags & IFF_OACTIVE)
1422                 return;
1423
1424         do {
1425                 IF_DEQUEUE(&ie->arpcom.ac_if.if_snd, m);
1426                 if (!m)
1427                         break;
1428
1429                 buffer = ie->xmit_cbuffs[ie->xmit_count];
1430                 len = 0;
1431
1432                 for (m0 = m; m && len < IE_BUF_LEN; m = m->m_next) {
1433                         bcopy(mtod(m, caddr_t), buffer, m->m_len);
1434                         buffer += m->m_len;
1435                         len += m->m_len;
1436                 }
1437
1438                 m_freem(m0);
1439                 len = max(len, ETHER_MIN_LEN);
1440
1441                 /*
1442                  * See if bpf is listening on this interface, let it see the
1443                  * packet before we commit it to the wire.
1444                  */
1445                 BPF_TAP(&ie->arpcom.ac_if,
1446                     __DEVOLATILE(u_char *, ie->xmit_cbuffs[ie->xmit_count]),
1447                     len);
1448
1449                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_flags =
1450                     IE_XMIT_LAST|len;
1451                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_next = 0xffff;
1452                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_buf =
1453                     MK_24(ie->iomem, ie->xmit_cbuffs[ie->xmit_count]);
1454
1455                 ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_cmd = IE_CMD_XMIT;
1456                 ie->xmit_cmds[ie->xmit_count]->ie_xmit_status = 0;
1457                 ie->xmit_cmds[ie->xmit_count]->ie_xmit_desc =
1458                     MK_16(ie->iomem, ie->xmit_buffs[ie->xmit_count]);
1459
1460                 *bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
1461                 bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
1462                 ie->xmit_count++;
1463         } while (ie->xmit_count < ie->ntxbufs);
1464
1465         /*
1466          * If we queued up anything for transmission, send it.
1467          */
1468         if (ie->xmit_count) {
1469                 ie->xmit_cmds[ie->xmit_count - 1]->com.ie_cmd_cmd |=
1470                     IE_CMD_LAST | IE_CMD_INTR;
1471
1472                 /*
1473                  * By passing the command pointer as a null, we tell
1474                  * command_and_wait() to pretend that this isn't an action
1475                  * command.  I wish I understood what was happening here.
1476                  */
1477                 command_and_wait(ifp->if_dunit, IE_CU_START, 0, 0);
1478                 ifp->if_flags |= IFF_OACTIVE;
1479         }
1480         return;
1481 }
1482
1483 /*
1484  * Check to see if there's an 82586 out there.
1485  */
1486 static int
1487 check_ie_present(int unit, caddr_t where, unsigned size)
1488 {
1489         volatile struct ie_sys_conf_ptr *scp;
1490         volatile struct ie_int_sys_conf_ptr *iscp;
1491         volatile struct ie_sys_ctl_block *scb;
1492         u_long  realbase;
1493         int     s;
1494
1495         s = splimp();
1496
1497         realbase = (uintptr_t) where + size - (1 << 24);
1498
1499         scp = (volatile struct ie_sys_conf_ptr *) (uintptr_t)
1500               (realbase + IE_SCP_ADDR);
1501         bzero((volatile char *) scp, sizeof *scp);
1502
1503         /*
1504          * First we put the ISCP at the bottom of memory; this tests to make
1505          * sure that our idea of the size of memory is the same as the
1506          * controller's. This is NOT where the ISCP will be in normal
1507          * operation.
1508          */
1509         iscp = (volatile struct ie_int_sys_conf_ptr *) where;
1510         bzero((volatile char *)iscp, sizeof *iscp);
1511
1512         scb = (volatile struct ie_sys_ctl_block *) where;
1513         bzero((volatile char *)scb, sizeof *scb);
1514
1515         scp->ie_bus_use = ie_softc[unit].bus_use;       /* 8-bit or 16-bit */
1516         scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1517             ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1518
1519         iscp->ie_busy = 1;
1520         iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
1521
1522         (*ie_softc[unit].ie_reset_586) (unit);
1523         (*ie_softc[unit].ie_chan_attn) (unit);
1524
1525         DELAY(100);             /* wait a while... */
1526
1527         if (iscp->ie_busy) {
1528                 splx(s);
1529                 return (0);
1530         }
1531         /*
1532          * Now relocate the ISCP to its real home, and reset the controller
1533          * again.
1534          */
1535         iscp = (void *) Align((caddr_t) (uintptr_t)
1536                               (realbase + IE_SCP_ADDR -
1537                                sizeof(struct ie_int_sys_conf_ptr)));
1538         bzero((volatile char *) iscp, sizeof *iscp);    /* ignore cast-qual */
1539
1540         scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1541             ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1542
1543         iscp->ie_busy = 1;
1544         iscp->ie_scb_offset = MK_16(realbase, scb);
1545
1546         (*ie_softc[unit].ie_reset_586) (unit);
1547         (*ie_softc[unit].ie_chan_attn) (unit);
1548
1549         DELAY(100);
1550
1551         if (iscp->ie_busy) {
1552                 splx(s);
1553                 return (0);
1554         }
1555         ie_softc[unit].iosize = size;
1556         ie_softc[unit].iomem = (caddr_t) (uintptr_t) realbase;
1557
1558         ie_softc[unit].iscp = iscp;
1559         ie_softc[unit].scb = scb;
1560
1561         /*
1562          * Acknowledge any interrupts we may have caused...
1563          */
1564         ie_ack(scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1565         splx(s);
1566
1567         return (1);
1568 }
1569
1570 /*
1571  * Divine the memory size of ie board UNIT.
1572  * Better hope there's nothing important hiding just below the ie card...
1573  */
1574 static void
1575 find_ie_mem_size(int unit)
1576 {
1577         unsigned size;
1578
1579         ie_softc[unit].iosize = 0;
1580
1581         for (size = 65536; size >= 8192; size -= 8192) {
1582                 if (check_ie_present(unit, ie_softc[unit].iomembot, size)) {
1583                         return;
1584                 }
1585         }
1586
1587         return;
1588 }
1589
1590 void
1591 el_reset_586(int unit)
1592 {
1593         outb(PORT + IE507_CTRL, EL_CTRL_RESET);
1594         DELAY(100);
1595         outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
1596         DELAY(100);
1597 }
1598
1599 void
1600 sl_reset_586(int unit)
1601 {
1602         outb(PORT + IEATT_RESET, 0);
1603 }
1604
1605 void
1606 ee16_reset_586(int unit)
1607 {
1608         outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
1609         DELAY(100);
1610         outb(PORT + IEE16_ECTRL, 0);
1611         DELAY(100);
1612 }
1613
1614 void
1615 el_chan_attn(int unit)
1616 {
1617         outb(PORT + IE507_ATTN, 1);
1618 }
1619
1620 void
1621 sl_chan_attn(int unit)
1622 {
1623         outb(PORT + IEATT_ATTN, 0);
1624 }
1625
1626 void
1627 ee16_chan_attn(int unit)
1628 {
1629         outb(PORT + IEE16_ATTN, 0);
1630 }
1631
1632 u_short
1633 ee16_read_eeprom(struct ie_softc *sc, int location)
1634 {
1635         int     ectrl, edata;
1636
1637         ectrl = inb(sc->port + IEE16_ECTRL);
1638         ectrl &= IEE16_ECTRL_MASK;
1639         ectrl |= IEE16_ECTRL_EECS;
1640         outb(sc->port + IEE16_ECTRL, ectrl);
1641
1642         ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
1643         ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
1644         edata = ee16_eeprom_inbits(sc);
1645         ectrl = inb(sc->port + IEE16_ECTRL);
1646         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
1647         outb(sc->port + IEE16_ECTRL, ectrl);
1648         ee16_eeprom_clock(sc, 1);
1649         ee16_eeprom_clock(sc, 0);
1650         return edata;
1651 }
1652
1653 void
1654 ee16_eeprom_outbits(struct ie_softc *sc, int edata, int count)
1655 {
1656         int     ectrl, i;
1657
1658         ectrl = inb(sc->port + IEE16_ECTRL);
1659         ectrl &= ~IEE16_RESET_ASIC;
1660         for (i = count - 1; i >= 0; i--) {
1661                 ectrl &= ~IEE16_ECTRL_EEDI;
1662                 if (edata & (1 << i)) {
1663                         ectrl |= IEE16_ECTRL_EEDI;
1664                 }
1665                 outb(sc->port + IEE16_ECTRL, ectrl);
1666                 DELAY(1);       /* eeprom data must be setup for 0.4 uSec */
1667                 ee16_eeprom_clock(sc, 1);
1668                 ee16_eeprom_clock(sc, 0);
1669         }
1670         ectrl &= ~IEE16_ECTRL_EEDI;
1671         outb(sc->port + IEE16_ECTRL, ectrl);
1672         DELAY(1);               /* eeprom data must be held for 0.4 uSec */
1673 }
1674
1675 int
1676 ee16_eeprom_inbits(struct ie_softc *sc)
1677 {
1678         int     ectrl, edata, i;
1679
1680         ectrl = inb(sc->port + IEE16_ECTRL);
1681         ectrl &= ~IEE16_RESET_ASIC;
1682         for (edata = 0, i = 0; i < 16; i++) {
1683                 edata = edata << 1;
1684                 ee16_eeprom_clock(sc, 1);
1685                 ectrl = inb(sc->port + IEE16_ECTRL);
1686                 if (ectrl & IEE16_ECTRL_EEDO) {
1687                         edata |= 1;
1688                 }
1689                 ee16_eeprom_clock(sc, 0);
1690         }
1691         return (edata);
1692 }
1693
1694 void
1695 ee16_eeprom_clock(struct ie_softc *sc, int state)
1696 {
1697         int     ectrl;
1698
1699         ectrl = inb(sc->port + IEE16_ECTRL);
1700         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
1701         if (state) {
1702                 ectrl |= IEE16_ECTRL_EESK;
1703         }
1704         outb(sc->port + IEE16_ECTRL, ectrl);
1705         DELAY(9);               /* EESK must be stable for 8.38 uSec */
1706 }
1707
1708 static __inline void
1709 ee16_interrupt_enable(struct ie_softc *sc)
1710 {
1711         DELAY(100);
1712         outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
1713         DELAY(100);
1714 }
1715
1716 void
1717 sl_read_ether(int unit, unsigned char addr[6])
1718 {
1719         int     i;
1720
1721         for (i = 0; i < 6; i++)
1722                 addr[i] = inb(PORT + i);
1723 }
1724
1725
1726 static void
1727 iereset(int unit)
1728 {
1729         int     s = splimp();
1730
1731         if (unit >= NIE) {
1732                 splx(s);
1733                 return;
1734         }
1735         printf("ie%d: reset\n", unit);
1736         ie_softc[unit].arpcom.ac_if.if_flags &= ~IFF_UP;
1737         ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
1738
1739         /*
1740          * Stop i82586 dead in its tracks.
1741          */
1742         if (command_and_wait(unit, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
1743                 printf("ie%d: abort commands timed out\n", unit);
1744
1745         if (command_and_wait(unit, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
1746                 printf("ie%d: disable commands timed out\n", unit);
1747
1748 #ifdef notdef
1749         if (!check_ie_present(unit, ie_softc[unit].iomembot,
1750                               e_softc[unit].iosize))
1751                 panic("ie disappeared!");
1752 #endif
1753
1754         ie_softc[unit].arpcom.ac_if.if_flags |= IFF_UP;
1755         ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
1756
1757         splx(s);
1758         return;
1759 }
1760
1761 /*
1762  * Send a command to the controller and wait for it to either
1763  * complete or be accepted, depending on the command.  If the
1764  * command pointer is null, then pretend that the command is
1765  * not an action command.  If the command pointer is not null,
1766  * and the command is an action command, wait for
1767  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
1768  * to become true.
1769  */
1770 static int
1771 command_and_wait(int unit, int cmd, volatile void *pcmd, int mask)
1772 {
1773         volatile struct ie_cmd_common *cc = pcmd;
1774
1775         ie_softc[unit].scb->ie_command = (u_short) cmd;
1776
1777         if (IE_ACTION_COMMAND(cmd) && pcmd) {
1778                 /*
1779                  * According to the packet driver, the minimum timeout
1780                  * should be .369 seconds.
1781                  */
1782                 int timer = 370;
1783
1784                 (*ie_softc[unit].ie_chan_attn) (unit);
1785
1786                 /*
1787                  * Now spin-lock waiting for status.  This is not a very
1788                  * nice thing to do, but I haven't figured out how, or
1789                  * indeed if, we can put the process waiting for action to
1790                  * sleep.  (We may be getting called through some other
1791                  * timeout running in the kernel.)
1792                  */
1793                 while (--timer > 0) {
1794                         if (cc->ie_cmd_status & mask)
1795                                 break;
1796                         DELAY(1000);
1797                 }
1798                 if (timer == 0)
1799                         return(1);
1800                 else
1801                         return(0);
1802         } else {
1803
1804                 /*
1805                  * Otherwise, just wait for the command to be accepted.
1806                  */
1807                 (*ie_softc[unit].ie_chan_attn) (unit);
1808
1809                 while (ie_softc[unit].scb->ie_command); /* spin lock */
1810
1811                 return (0);
1812         }
1813 }
1814
1815 /*
1816  * Run the time-domain reflectometer...
1817  */
1818 static void
1819 run_tdr(int unit, volatile struct ie_tdr_cmd *cmd)
1820 {
1821         int     result;
1822
1823         cmd->com.ie_cmd_status = 0;
1824         cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
1825         cmd->com.ie_cmd_link = 0xffff;
1826         cmd->ie_tdr_time = 0;
1827
1828         ie_softc[unit].scb->ie_command_list = MK_16(MEM, cmd);
1829         cmd->ie_tdr_time = 0;
1830
1831         if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL))
1832                 result = 0x2000;
1833         else
1834                 result = cmd->ie_tdr_time;
1835
1836         ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit,
1837                ie_softc[unit].ie_chan_attn);
1838
1839         if (result & IE_TDR_SUCCESS)
1840                 return;
1841
1842         if (result & IE_TDR_XCVR) {
1843                 printf("ie%d: transceiver problem\n", unit);
1844         } else if (result & IE_TDR_OPEN) {
1845                 printf("ie%d: TDR detected an open %d clocks away\n", unit,
1846                        result & IE_TDR_TIME);
1847         } else if (result & IE_TDR_SHORT) {
1848                 printf("ie%d: TDR detected a short %d clocks away\n", unit,
1849                        result & IE_TDR_TIME);
1850         } else {
1851                 printf("ie%d: TDR returned unknown status %x\n", unit, result);
1852         }
1853 }
1854
1855 static void
1856 start_receiver(int unit)
1857 {
1858         int     s = splimp();
1859
1860         ie_softc[unit].scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1861         command_and_wait(unit, IE_RU_START, 0, 0);
1862
1863         ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1864
1865         splx(s);
1866 }
1867
1868 /*
1869  * Here is a helper routine for iernr() and ieinit().  This sets up
1870  * the RFA.
1871  */
1872 static v_caddr_t
1873 setup_rfa(v_caddr_t ptr, struct ie_softc * ie)
1874 {
1875         volatile struct ie_recv_frame_desc *rfd = (volatile void *)ptr;
1876         volatile struct ie_recv_buf_desc *rbd;
1877         int     i;
1878         int     unit = ie - &ie_softc[0];
1879
1880         /* First lay them out */
1881         for (i = 0; i < ie->nframes; i++) {
1882                 ie->rframes[i] = rfd;
1883                 bzero((volatile char *) rfd, sizeof *rfd);      /* ignore cast-qual */
1884                 rfd++;
1885         }
1886
1887         ptr = Alignvol(rfd);            /* ignore cast-qual */
1888
1889         /* Now link them together */
1890         for (i = 0; i < ie->nframes; i++) {
1891                 ie->rframes[i]->ie_fd_next =
1892                     MK_16(MEM, ie->rframes[(i + 1) % ie->nframes]);
1893         }
1894
1895         /* Finally, set the EOL bit on the last one. */
1896         ie->rframes[ie->nframes - 1]->ie_fd_last |= IE_FD_LAST;
1897
1898         /*
1899          * Now lay out some buffers for the incoming frames.  Note that we
1900          * set aside a bit of slop in each buffer, to make sure that we have
1901          * enough space to hold a single frame in every buffer.
1902          */
1903         rbd = (volatile void *) ptr;
1904
1905         for (i = 0; i < ie->nrxbufs; i++) {
1906                 ie->rbuffs[i] = rbd;
1907                 bzero((volatile char *)rbd, sizeof *rbd);
1908                 ptr = Alignvol(ptr + sizeof *rbd);
1909                 rbd->ie_rbd_length = IE_RBUF_SIZE;
1910                 rbd->ie_rbd_buffer = MK_24(MEM, ptr);
1911                 ie->cbuffs[i] = (volatile void *) ptr;
1912                 ptr += IE_RBUF_SIZE;
1913                 rbd = (volatile void *) ptr;
1914         }
1915
1916         /* Now link them together */
1917         for (i = 0; i < ie->nrxbufs; i++) {
1918                 ie->rbuffs[i]->ie_rbd_next =
1919                     MK_16(MEM, ie->rbuffs[(i + 1) % ie->nrxbufs]);
1920         }
1921
1922         /* Tag EOF on the last one */
1923         ie->rbuffs[ie->nrxbufs - 1]->ie_rbd_length |= IE_RBD_LAST;
1924
1925         /*
1926          * We use the head and tail pointers on receive to keep track of the
1927          * order in which RFDs and RBDs are used.
1928          */
1929         ie->rfhead = 0;
1930         ie->rftail = ie->nframes - 1;
1931         ie->rbhead = 0;
1932         ie->rbtail = ie->nrxbufs - 1;
1933
1934         ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
1935         ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
1936
1937         ptr = Alignvol(ptr);
1938         return (ptr);
1939 }
1940
1941 /*
1942  * Run the multicast setup command.
1943  * Call at splimp().
1944  */
1945 static int
1946 mc_setup(int unit, v_caddr_t ptr,
1947          volatile struct ie_sys_ctl_block * scb)
1948 {
1949         struct ie_softc *ie = &ie_softc[unit];
1950         volatile struct ie_mcast_cmd *cmd = (volatile void *) ptr;
1951
1952         cmd->com.ie_cmd_status = 0;
1953         cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
1954         cmd->com.ie_cmd_link = 0xffff;
1955
1956         /* ignore cast-qual */
1957         bcopy((v_caddr_t) ie->mcast_addrs, (v_caddr_t) cmd->ie_mcast_addrs,
1958               ie->mcast_count * sizeof *ie->mcast_addrs);
1959
1960         cmd->ie_mcast_bytes = ie->mcast_count * 6;      /* grrr... */
1961
1962         scb->ie_command_list = MK_16(MEM, cmd);
1963         if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
1964             || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1965                 printf("ie%d: multicast address setup command failed\n", unit);
1966                 return (0);
1967         }
1968         return (1);
1969 }
1970
1971 /*
1972  * This routine takes the environment generated by check_ie_present()
1973  * and adds to it all the other structures we need to operate the adapter.
1974  * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
1975  * starting the receiver unit, and clearing interrupts.
1976  *
1977  * THIS ROUTINE MUST BE CALLED AT splimp() OR HIGHER.
1978  */
1979 static void
1980 ieinit(xsc)
1981         void *xsc;
1982 {
1983         struct ie_softc *ie = xsc;
1984         volatile struct ie_sys_ctl_block *scb = ie->scb;
1985         v_caddr_t ptr;
1986         int     i;
1987         int     unit = ie->unit;
1988
1989         ptr = Alignvol((volatile char *) scb + sizeof *scb);
1990
1991         /*
1992          * Send the configure command first.
1993          */
1994         {
1995                 volatile struct ie_config_cmd *cmd = (volatile void *) ptr;
1996
1997                 ie_setup_config(cmd, ie->promisc,
1998                                 ie->hard_type == IE_STARLAN10);
1999                 cmd->com.ie_cmd_status = 0;
2000                 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
2001                 cmd->com.ie_cmd_link = 0xffff;
2002
2003                 scb->ie_command_list = MK_16(MEM, cmd);
2004
2005                 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2006                  || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2007                         printf("ie%d: configure command failed\n", unit);
2008                         return;
2009                 }
2010         }
2011         /*
2012          * Now send the Individual Address Setup command.
2013          */
2014         {
2015                 volatile struct ie_iasetup_cmd *cmd = (volatile void *) ptr;
2016
2017                 cmd->com.ie_cmd_status = 0;
2018                 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
2019                 cmd->com.ie_cmd_link = 0xffff;
2020
2021                 bcopy((volatile char *)ie_softc[unit].arpcom.ac_enaddr,
2022                       (volatile char *)&cmd->ie_address, sizeof cmd->ie_address);
2023                 scb->ie_command_list = MK_16(MEM, cmd);
2024                 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2025                     || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2026                         printf("ie%d: individual address "
2027                                "setup command failed\n", unit);
2028                         return;
2029                 }
2030         }
2031
2032         /*
2033          * Now run the time-domain reflectometer.
2034          */
2035         run_tdr(unit, (volatile void *) ptr);
2036
2037         /*
2038          * Acknowledge any interrupts we have generated thus far.
2039          */
2040         ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
2041
2042         /*
2043          * Set up the RFA.
2044          */
2045         ptr = setup_rfa(ptr, ie);
2046
2047         /*
2048          * Finally, the transmit command and buffer are the last little bit
2049          * of work.
2050          */
2051
2052         /* transmit command buffers */
2053         for (i = 0; i < ie->ntxbufs; i++) {
2054                 ie->xmit_cmds[i] = (volatile void *) ptr;
2055                 ptr += sizeof *ie->xmit_cmds[i];
2056                 ptr = Alignvol(ptr);
2057                 ie->xmit_buffs[i] = (volatile void *)ptr;
2058                 ptr += sizeof *ie->xmit_buffs[i];
2059                 ptr = Alignvol(ptr);
2060         }
2061
2062         /* transmit buffers */
2063         for (i = 0; i < ie->ntxbufs - 1; i++) {
2064                 ie->xmit_cbuffs[i] = (volatile void *)ptr;
2065                 ptr += IE_BUF_LEN;
2066                 ptr = Alignvol(ptr);
2067         }
2068         ie->xmit_cbuffs[ie->ntxbufs - 1] = (volatile void *) ptr;
2069
2070         for (i = 1; i < ie->ntxbufs; i++) {
2071                 bzero((v_caddr_t) ie->xmit_cmds[i], sizeof *ie->xmit_cmds[i]);
2072                 bzero((v_caddr_t) ie->xmit_buffs[i], sizeof *ie->xmit_buffs[i]);
2073         }
2074
2075         /*
2076          * This must be coordinated with iestart() and ietint().
2077          */
2078         ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
2079
2080         /* take the ee16 out of loopback */
2081         if (ie->hard_type == IE_EE16) {
2082                 u_int8_t bart_config;
2083
2084                 bart_config = inb(PORT + IEE16_CONFIG);
2085                 bart_config &= ~IEE16_BART_LOOPBACK;
2086                 /* inb doesn't get bit! */
2087                 bart_config |= IEE16_BART_MCS16_TEST;
2088                 outb(PORT + IEE16_CONFIG, bart_config);
2089                 ee16_interrupt_enable(ie);
2090                 ee16_chan_attn(unit);
2091         }
2092         ie->arpcom.ac_if.if_flags |= IFF_RUNNING;       /* tell higher levels
2093                                                          * we're here */
2094         start_receiver(unit);
2095
2096         return;
2097 }
2098
2099 static void
2100 ie_stop(int unit)
2101 {
2102         command_and_wait(unit, IE_RU_DISABLE, 0, 0);
2103 }
2104
2105 static int
2106 ieioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2107 {
2108         int     s, error = 0;
2109
2110         s = splimp();
2111
2112         switch (command) {
2113         case SIOCSIFADDR:
2114         case SIOCGIFADDR:
2115         case SIOCSIFMTU:
2116                 error = ether_ioctl(ifp, command, data);
2117                 break;
2118
2119         case SIOCSIFFLAGS:
2120                 /*
2121                  * Note that this device doesn't have an "all multicast"
2122                  * mode, so we must turn on promiscuous mode and do the
2123                  * filtering manually.
2124                  */
2125                 if ((ifp->if_flags & IFF_UP) == 0 &&
2126                     (ifp->if_flags & IFF_RUNNING)) {
2127                         ifp->if_flags &= ~IFF_RUNNING;
2128                         ie_stop(ifp->if_dunit);
2129                 } else if ((ifp->if_flags & IFF_UP) &&
2130                            (ifp->if_flags & IFF_RUNNING) == 0) {
2131                         ie_softc[ifp->if_dunit].promisc =
2132                             ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2133                         ieinit(ifp->if_softc);
2134                 } else if (ie_softc[ifp->if_dunit].promisc ^
2135                            (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))) {
2136                         ie_softc[ifp->if_dunit].promisc =
2137                             ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2138                         ieinit(ifp->if_softc);
2139                 }
2140                 break;
2141
2142         case SIOCADDMULTI:
2143         case SIOCDELMULTI:
2144                 /*
2145                  * Update multicast listeners
2146                  */
2147                 /* reset multicast filtering */
2148                 ie_mc_reset(ifp->if_dunit);
2149                 error = 0;
2150                 break;
2151
2152         default:
2153                 error = EINVAL;
2154         }
2155
2156         splx(s);
2157         return (error);
2158 }
2159
2160 static void
2161 ie_mc_reset(int unit)
2162 {
2163         struct ie_softc *ie = &ie_softc[unit];
2164         struct ifmultiaddr *ifma;
2165
2166         /*
2167          * Step through the list of addresses.
2168          */
2169         ie->mcast_count = 0;
2170         for (ifma = ie->arpcom.ac_if.if_multiaddrs.lh_first; ifma;
2171              ifma = ifma->ifma_link.le_next) {
2172                 if (ifma->ifma_addr->sa_family != AF_LINK)
2173                         continue;
2174
2175                 /* XXX - this is broken... */
2176                 if (ie->mcast_count >= MAXMCAST) {
2177                         ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
2178                         ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *) 0,
2179                                 (struct ucred *)NULL);
2180                         goto setflag;
2181                 }
2182                 bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
2183                       &(ie->mcast_addrs[ie->mcast_count]), 6);
2184                 ie->mcast_count++;
2185         }
2186
2187 setflag:
2188         ie->want_mcsetup = 1;
2189 }
2190
2191
2192 #ifdef DEBUG
2193 static void
2194 print_rbd(volatile struct ie_recv_buf_desc * rbd)
2195 {
2196         printf("RBD at %p:\n"
2197                "actual %04x, next %04x, buffer %p\n"
2198                "length %04x, mbz %04x\n",
2199                (volatile void *) rbd,
2200                rbd->ie_rbd_actual, rbd->ie_rbd_next,
2201                (void *) rbd->ie_rbd_buffer,
2202                rbd->ie_rbd_length, rbd->mbz);
2203 }
2204
2205 #endif                          /* DEBUG */