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