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