Reduce ifnet.if_serializer contention on output path:
[dragonfly.git] / sys / dev / netif / ie / if_ie.c
blobe027d9172e5ec8e0aec43b14694e394d547a124e
1 /*-
2 * Copyright (c) 1992, 1993, University of Vermont and State
3 * Agricultural College.
4 * Copyright (c) 1992, 1993, Garrett A. Wollman.
6 * Portions:
7 * Copyright (c) 1990, 1991, William F. Jolitz
8 * Copyright (c) 1990, The Regents of the University of California
10 * 3Com 3C507 support:
11 * Copyright (c) 1993, 1994, Charles M. Hannum
13 * EtherExpress 16 support:
14 * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
15 * Copyright (c) 1997, Aaron C. Smith
17 * All rights reserved.
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.
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.
50 * $FreeBSD: src/sys/dev/ie/if_ie.c,v 1.72.2.4 2003/03/27 21:01:49 mdodd Exp $
51 * $DragonFly: src/sys/dev/netif/ie/if_ie.c,v 1.33 2008/05/14 11:59:20 sephe Exp $
55 * Intel 82586 Ethernet chip
56 * Register, bit, and structure definitions.
58 * Written by GAW with reference to the Clarkson Packet Driver code for this
59 * chip written by Russ Nelson and others.
61 * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
65 * The i82586 is a very versatile chip, found in many implementations.
66 * Programming this chip is mostly the same, but certain details differ
67 * from card to card. This driver is written so that different cards
68 * can be automatically detected at run-time.
72 Mode of operation:
74 We run the 82586 in a standard Ethernet mode. We keep NFRAMES received
75 frame descriptors around for the receiver to use, and NRXBUFS associated
76 receive buffer descriptors, both in a circular list. Whenever a frame is
77 received, we rotate both lists as necessary. (The 586 treats both lists
78 as a simple queue.) We also keep a transmit command around so that packets
79 can be sent off quickly.
81 We configure the adapter in AL-LOC = 1 mode, which means that the
82 Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
83 rather than being split off into various fields in the RFD. This also
84 means that we must include this header in the transmit buffer as well.
86 By convention, all transmit commands, and only transmit commands, shall
87 have the I (IE_CMD_INTR) bit set in the command. This way, when an
88 interrupt arrives at ieintr(), it is immediately possible to tell
89 what precisely caused it. ANY OTHER command-sending routines should
90 run at splimp(), and should post an acknowledgement to every interrupt
91 they generate.
93 The 82586 has a 24-bit address space internally, and the adaptor's memory
94 is located at the top of this region. However, the value we are given in
95 configuration is normally the *bottom* of the adaptor RAM. So, we must go
96 through a few gyrations to come up with a kernel virtual address which
97 represents the actual beginning of the 586 address space. First, we
98 autosize the RAM by running through several possible sizes and trying to
99 initialize the adapter under the assumption that the selected size is
100 correct. Then, knowing the correct RAM size, we set up our pointers in
101 ie_softc[unit]. `iomem' represents the computed base of the 586 address
102 space. `iomembot' represents the actual configured base of adapter RAM.
103 Finally, `iosize' represents the calculated size of 586 RAM. Then, when
104 laying out commands, we use the interval [iomembot, iomembot + iosize); to
105 make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
106 iomem and and with 0xffff.
110 #include "use_ie.h"
111 #include "opt_inet.h"
112 #include "opt_ipx.h"
114 #include <sys/param.h>
115 #include <sys/systm.h>
116 #include <sys/eventhandler.h>
117 #include <sys/kernel.h>
118 #include <sys/malloc.h>
119 #include <sys/conf.h>
120 #include <sys/mbuf.h>
121 #include <sys/socket.h>
122 #include <sys/sockio.h>
123 #include <sys/syslog.h>
124 #include <sys/thread2.h>
126 #include <net/ethernet.h>
127 #include <net/if.h>
128 #include <net/ifq_var.h>
129 #include <net/if_types.h>
130 #include <net/if_dl.h>
132 #include <netinet/in.h>
133 #include <netinet/if_ether.h>
135 #include <machine/clock.h>
136 #include <machine/md_var.h>
138 #include <bus/isa/i386/isa_device.h>
139 #include <machine_base/isa/ic/i82586.h>
140 #include <machine_base/icu/icu.h>
141 #include "if_iereg.h"
142 #include "if_ie507.h"
143 #include "if_iee16.h"
144 #include "../elink_layer/elink.h"
146 #include <net/bpf.h>
148 #ifdef DEBUG
149 #define IED_RINT 0x01
150 #define IED_TINT 0x02
151 #define IED_RNR 0x04
152 #define IED_CNA 0x08
153 #define IED_READFRAME 0x10
154 static int ie_debug = IED_RNR;
156 #endif
158 DECLARE_DUMMY_MODULE(if_ie);
160 #define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */
162 /* Forward declaration */
163 struct ie_softc;
165 static int ieprobe(struct isa_device * dvp);
166 static int ieattach(struct isa_device * dvp);
167 static void ieintr(void *);
168 static int sl_probe(struct isa_device * dvp);
169 static int el_probe(struct isa_device * dvp);
170 static int ni_probe(struct isa_device * dvp);
171 static int ee16_probe(struct isa_device * dvp);
173 static int check_ie_present(int unit, caddr_t where, unsigned size);
174 static void ieinit(void *);
175 static void ie_stop(int unit);
176 static int ieioctl(struct ifnet * ifp, u_long command, caddr_t data,
177 struct ucred *);
178 static void iestart(struct ifnet * ifp);
180 static void el_reset_586(int unit);
181 static void el_chan_attn(int unit);
183 static void sl_reset_586(int unit);
184 static void sl_chan_attn(int unit);
186 static void ee16_reset_586(int unit);
187 static void ee16_chan_attn(int unit);
188 static __inline void ee16_interrupt_enable(struct ie_softc * ie);
189 static void ee16_eeprom_outbits(struct ie_softc * ie, int edata, int cnt);
190 static void ee16_eeprom_clock(struct ie_softc * ie, int state);
191 static u_short ee16_read_eeprom(struct ie_softc * ie, int location);
192 static int ee16_eeprom_inbits(struct ie_softc * ie);
193 static void ee16_shutdown(void *sc, int howto);
195 static void iereset(int unit);
196 static void ie_readframe(int unit, struct ie_softc * ie, int bufno);
197 static void ie_drop_packet_buffer(int unit, struct ie_softc * ie);
198 static void sl_read_ether(int unit, unsigned char addr[6]);
199 static void find_ie_mem_size(int unit);
200 static int command_and_wait(int unit, int command,
201 void volatile * pcmd, int);
202 static void run_tdr(int unit, volatile struct ie_tdr_cmd * cmd);
203 static int ierint(int unit, struct ie_softc * ie);
204 static int ietint(int unit, struct ie_softc * ie);
205 static int iernr(int unit, struct ie_softc * ie);
206 static void start_receiver(int unit);
207 static __inline int ieget(int, struct ie_softc *, struct mbuf **);
208 static v_caddr_t setup_rfa(v_caddr_t ptr, struct ie_softc * ie);
209 static int mc_setup(int, v_caddr_t, volatile struct ie_sys_ctl_block *);
210 static void ie_mc_reset(int unit);
212 #ifdef DEBUG
213 static void print_rbd(volatile struct ie_recv_buf_desc * rbd);
215 static int in_ierint = 0;
216 static int in_ietint = 0;
218 #endif
221 * This tells the autoconf code how to set us up.
223 struct isa_driver iedriver = {
224 ieprobe, ieattach, "ie",
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
237 static const char *ie_hardware_names[] = {
238 "StarLAN 10",
239 "EN100",
240 "StarLAN Fiber",
241 "3C507",
242 "NI5210",
243 "EtherExpress 16",
244 "Unknown"
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
257 NRXBUFS * sizeof(rbd) == NRXBUFS*(2+2+4+2+2) == NRXBUFS*12
258 NRXBUFS * IE_RBUF_SIZE == NRXBUFS*256
260 NRXBUFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
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!
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.
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 */
278 * Ethernet status, per interface.
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;
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 */
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;
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;
311 struct ie_en_addr mcast_addrs[MAXMCAST + 1];
312 int mcast_count;
314 u_short irq_encoded; /* encoded interrupt on IEE16 */
315 } ie_softc[NIE];
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))
320 #define PORT ie_softc[unit].port
321 #define MEM ie_softc[unit].iomem
324 ieprobe(struct isa_device *dvp)
326 int ret;
328 ret = sl_probe(dvp);
329 if (!ret)
330 ret = el_probe(dvp);
331 if (!ret)
332 ret = ni_probe(dvp);
333 if (!ret)
334 ret = ee16_probe(dvp);
336 return (ret);
339 static int
340 sl_probe(struct isa_device *dvp)
342 int unit = dvp->id_unit;
343 u_char c;
345 ie_softc[unit].port = dvp->id_iobase;
346 ie_softc[unit].iomembot = dvp->id_maddr;
347 ie_softc[unit].iomem = 0;
348 ie_softc[unit].bus_use = 0;
350 c = inb(PORT + IEATT_REVISION);
351 switch (SL_BOARD(c)) {
352 case SL10_BOARD:
353 ie_softc[unit].hard_type = IE_STARLAN10;
354 ie_softc[unit].ie_reset_586 = sl_reset_586;
355 ie_softc[unit].ie_chan_attn = sl_chan_attn;
356 break;
357 case EN100_BOARD:
358 ie_softc[unit].hard_type = IE_EN100;
359 ie_softc[unit].ie_reset_586 = sl_reset_586;
360 ie_softc[unit].ie_chan_attn = sl_chan_attn;
361 break;
362 case SLFIBER_BOARD:
363 ie_softc[unit].hard_type = IE_SLFIBER;
364 ie_softc[unit].ie_reset_586 = sl_reset_586;
365 ie_softc[unit].ie_chan_attn = sl_chan_attn;
366 break;
369 * Anything else is not recognized or cannot be used.
371 default:
372 return (0);
375 ie_softc[unit].hard_vers = SL_REV(c);
378 * Divine memory size on-board the card. Ususally 16k.
380 find_ie_mem_size(unit);
382 if (!ie_softc[unit].iosize) {
383 return (0);
385 dvp->id_msize = ie_softc[unit].iosize;
387 switch (ie_softc[unit].hard_type) {
388 case IE_EN100:
389 case IE_STARLAN10:
390 case IE_SLFIBER:
391 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
392 break;
394 default:
395 if (bootverbose)
396 kprintf("ie%d: unknown AT&T board type code %d\n", unit,
397 ie_softc[unit].hard_type);
398 return (0);
401 return (1);
405 static int
406 el_probe(struct isa_device *dvp)
408 struct ie_softc *sc = &ie_softc[dvp->id_unit];
409 u_char c;
410 int i;
411 u_char signature[] = "*3COM*";
412 int unit = dvp->id_unit;
414 sc->unit = unit;
415 sc->port = dvp->id_iobase;
416 sc->iomembot = dvp->id_maddr;
417 sc->bus_use = 0;
419 /* Need this for part of the probe. */
420 sc->ie_reset_586 = el_reset_586;
421 sc->ie_chan_attn = el_chan_attn;
423 /* Reset and put card in CONFIG state without changing address. */
424 elink_reset();
425 outb(ELINK_ID_PORT, 0x00);
426 elink_idseq(ELINK_507_POLY);
427 elink_idseq(ELINK_507_POLY);
428 outb(ELINK_ID_PORT, 0xff);
430 c = inb(PORT + IE507_MADDR);
431 if (c & 0x20) {
432 #ifdef DEBUG
433 kprintf("ie%d: can't map 3C507 RAM in high memory\n", unit);
434 #endif
435 return (0);
437 /* go to RUN state */
438 outb(ELINK_ID_PORT, 0x00);
439 elink_idseq(ELINK_507_POLY);
440 outb(ELINK_ID_PORT, 0x00);
442 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
444 for (i = 0; i < 6; i++)
445 if (inb(PORT + i) != signature[i])
446 return (0);
448 c = inb(PORT + IE507_IRQ) & 0x0f;
450 if (dvp->id_irq != (1 << c)) {
451 kprintf("ie%d: kernel configured irq %d "
452 "doesn't match board configured irq %d\n",
453 unit, ffs(dvp->id_irq) - 1, c);
454 return (0);
456 c = (inb(PORT + IE507_MADDR) & 0x1c) + 0xc0;
458 if (kvtop(dvp->id_maddr) != ((int) c << 12)) {
459 kprintf("ie%d: kernel configured maddr %llx "
460 "doesn't match board configured maddr %x\n",
461 unit, kvtop(dvp->id_maddr), (int) c << 12);
462 return (0);
464 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
466 sc->hard_type = IE_3C507;
467 sc->hard_vers = 0; /* 3C507 has no version number. */
470 * Divine memory size on-board the card.
472 find_ie_mem_size(unit);
474 if (!sc->iosize) {
475 kprintf("ie%d: can't find shared memory\n", unit);
476 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
477 return (0);
479 if (!dvp->id_msize)
480 dvp->id_msize = sc->iosize;
481 else if (dvp->id_msize != sc->iosize) {
482 kprintf("ie%d: kernel configured msize %d "
483 "doesn't match board configured msize %d\n",
484 unit, dvp->id_msize, sc->iosize);
485 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
486 return (0);
488 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
490 /* Clear the interrupt latch just in case. */
491 outb(PORT + IE507_ICTRL, 1);
493 return (16);
497 static int
498 ni_probe(struct isa_device *dvp)
500 int unit = dvp->id_unit;
501 int boardtype, c;
503 ie_softc[unit].port = dvp->id_iobase;
504 ie_softc[unit].iomembot = dvp->id_maddr;
505 ie_softc[unit].iomem = 0;
506 ie_softc[unit].bus_use = 1;
508 boardtype = inb(PORT + IEATT_REVISION);
509 c = inb(PORT + IEATT_REVISION + 1);
510 boardtype = boardtype + (c << 8);
511 switch (boardtype) {
512 case 0x5500: /* This is the magic cookie for the NI5210 */
513 ie_softc[unit].hard_type = IE_NI5210;
514 ie_softc[unit].ie_reset_586 = sl_reset_586;
515 ie_softc[unit].ie_chan_attn = sl_chan_attn;
516 break;
519 * Anything else is not recognized or cannot be used.
521 default:
522 return (0);
525 ie_softc[unit].hard_vers = 0;
528 * Divine memory size on-board the card. Either 8 or 16k.
530 find_ie_mem_size(unit);
532 if (!ie_softc[unit].iosize) {
533 return (0);
535 if (!dvp->id_msize)
536 dvp->id_msize = ie_softc[unit].iosize;
537 else if (dvp->id_msize != ie_softc[unit].iosize) {
538 kprintf("ie%d: kernel configured msize %d "
539 "doesn't match board configured msize %d\n",
540 unit, dvp->id_msize, ie_softc[unit].iosize);
541 return (0);
543 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
545 return (8);
550 static void
551 ee16_shutdown(void *sc, int howto)
553 struct ie_softc *ie = (struct ie_softc *)sc;
554 int unit = ie - &ie_softc[0];
556 ee16_reset_586(unit);
557 outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
558 outb(PORT + IEE16_ECTRL, 0);
562 /* Taken almost exactly from Rod's if_ix.c. */
565 ee16_probe(struct isa_device *dvp)
567 struct ie_softc *sc = &ie_softc[dvp->id_unit];
569 int i;
570 int unit = dvp->id_unit;
571 u_short board_id, id_var1, id_var2, checksum = 0;
572 u_short eaddrtemp, irq;
573 u_short pg, adjust, decode, edecode;
574 u_char bart_config;
575 u_long bd_maddr;
577 short irq_translate[] = {0, 1 << ICU_IRQ9, 1 << ICU_IRQ3,
578 1 << ICU_IRQ4, 1 << ICU_IRQ5,
579 1 << ICU_IRQ10, 1 << ICU_IRQ11, 0};
580 char irq_encode[] = {0, 0, 0, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0};
582 /* Need this for part of the probe. */
583 sc->ie_reset_586 = ee16_reset_586;
584 sc->ie_chan_attn = ee16_chan_attn;
586 /* unsure if this is necessary */
587 sc->bus_use = 0;
589 /* reset any ee16 at the current iobase */
590 outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
591 outb(dvp->id_iobase + IEE16_ECTRL, 0);
592 DELAY(240);
594 /* now look for ee16. */
595 board_id = id_var1 = id_var2 = 0;
596 for (i = 0; i < 4; i++) {
597 id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
598 id_var2 = ((id_var1 & 0x03) << 2);
599 board_id |= ((id_var1 >> 4) << id_var2);
602 if (board_id != IEE16_ID) {
603 if (bootverbose)
604 kprintf("ie%d: unknown board_id: %x\n", unit, board_id);
605 return (0);
607 /* need sc->port for ee16_read_eeprom */
608 sc->port = dvp->id_iobase;
609 sc->hard_type = IE_EE16;
612 * The shared RAM location on the EE16 is encoded into bits 3-7 of
613 * EEPROM location 6. We zero the upper byte, and shift the 5 bits
614 * right 3. The resulting number tells us the RAM location.
615 * Because the EE16 supports either 16k or 32k of shared RAM, we
616 * only worry about the 32k locations.
618 * NOTE: if a 64k EE16 exists, it should be added to this switch. then
619 * the ia->ia_msize would need to be set per case statement.
621 * value msize location ===== ===== ======== 0x03 0x8000
622 * 0xCC000 0x06 0x8000 0xD0000 0x0C 0x8000 0xD4000 0x18
623 * 0x8000 0xD8000
627 bd_maddr = 0;
628 i = (ee16_read_eeprom(sc, 6) & 0x00ff) >> 3;
629 switch (i) {
630 case 0x03:
631 bd_maddr = 0xCC000;
632 break;
633 case 0x06:
634 bd_maddr = 0xD0000;
635 break;
636 case 0x0c:
637 bd_maddr = 0xD4000;
638 break;
639 case 0x18:
640 bd_maddr = 0xD8000;
641 break;
642 default:
643 bd_maddr = 0;
644 break;
646 dvp->id_msize = 0x8000;
647 if (kvtop(dvp->id_maddr) != bd_maddr) {
648 kprintf("ie%d: kernel configured maddr %llx "
649 "doesn't match board configured maddr %lx\n",
650 unit, kvtop(dvp->id_maddr), bd_maddr);
652 sc->iomembot = dvp->id_maddr;
653 sc->iomem = 0; /* XXX some probes set this and some don't */
654 sc->iosize = dvp->id_msize;
656 /* need to put the 586 in RESET while we access the eeprom. */
657 outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
659 /* read the eeprom and checksum it, should == IEE16_ID */
660 for (i = 0; i < 0x40; i++)
661 checksum += ee16_read_eeprom(sc, i);
663 if (checksum != IEE16_ID) {
664 kprintf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
665 return (0);
668 * Size and test the memory on the board. The size of the memory
669 * can be one of 16k, 32k, 48k or 64k. It can be located in the
670 * address range 0xC0000 to 0xEFFFF on 16k boundaries.
672 * If the size does not match the passed in memory allocation size
673 * issue a warning, but continue with the minimum of the two sizes.
676 switch (dvp->id_msize) {
677 case 65536:
678 case 32768: /* XXX Only support 32k and 64k right now */
679 break;
680 case 16384:
681 case 49512:
682 default:
683 kprintf("ie%d: mapped memory size %d not supported\n", unit,
684 dvp->id_msize);
685 return (0);
686 break; /* NOTREACHED */
689 if ((kvtop(dvp->id_maddr) < 0xC0000) ||
690 (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
691 kprintf("ie%d: mapped memory location %p out of range\n", unit,
692 (void *)dvp->id_maddr);
693 return (0);
695 pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
696 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
697 decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
698 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
700 /* ZZZ This should be checked against eeprom location 6, low byte */
701 outb(PORT + IEE16_MEMDEC, decode & 0xFF);
702 /* ZZZ This should be checked against eeprom location 1, low byte */
703 outb(PORT + IEE16_MCTRL, adjust);
704 /* ZZZ Now if I could find this one I would have it made */
705 outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
706 /* ZZZ I think this is location 6, high byte */
707 outb(PORT + IEE16_MECTRL, edecode); /* XXX disable Exxx */
709 kvtop(dvp->id_maddr);
712 * first prime the stupid bart DRAM controller so that it works,
713 * then zero out all of memory.
715 bzero(sc->iomembot, 32);
716 bzero(sc->iomembot, sc->iosize);
719 * Get the encoded interrupt number from the EEPROM, check it
720 * against the passed in IRQ. Issue a warning if they do not match.
721 * Always use the passed in IRQ, not the one in the EEPROM.
723 irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
724 irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
725 irq = irq_translate[irq];
726 if (dvp->id_irq > 0) {
727 if (irq != dvp->id_irq) {
728 kprintf("ie%d: WARNING: board configured "
729 "at irq %u, using %u\n",
730 dvp->id_unit, dvp->id_irq, irq);
731 irq = dvp->id_unit;
733 } else {
734 dvp->id_irq = irq;
736 sc->irq_encoded = irq_encode[ffs(irq) - 1];
739 * Get the hardware ethernet address from the EEPROM and save it in
740 * the softc for use by the 586 setup code.
742 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
743 sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
744 sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
745 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
746 sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
747 sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
748 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
749 sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
750 sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
752 /* disable the board interrupts */
753 outb(PORT + IEE16_IRQ, sc->irq_encoded);
755 /* enable loopback to keep bad packets off the wire */
756 if (sc->hard_type == IE_EE16) {
757 bart_config = inb(PORT + IEE16_CONFIG);
758 bart_config |= IEE16_BART_LOOPBACK;
759 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
760 outb(PORT + IEE16_CONFIG, bart_config);
761 bart_config = inb(PORT + IEE16_CONFIG);
763 /* take the board out of reset state */
764 outb(PORT + IEE16_ECTRL, 0);
765 DELAY(100);
767 if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
768 return (0);
770 return (16); /* return the number of I/O ports */
774 * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
777 ieattach(struct isa_device *dvp)
779 int factor;
780 int unit = dvp->id_unit;
781 struct ie_softc *ie = &ie_softc[unit];
782 struct ifnet *ifp = &ie->arpcom.ac_if;
783 size_t allocsize;
785 dvp->id_intr = (inthand2_t *)ieintr;
788 * based on the amount of memory we have, allocate our tx and rx
789 * resources.
791 factor = dvp->id_msize / 16384;
792 ie->nframes = factor * NFRAMES;
793 ie->nrxbufs = factor * NRXBUFS;
794 ie->ntxbufs = factor * NTXBUFS;
797 * Since all of these guys are arrays of pointers, allocate as one
798 * big chunk and dole out accordingly.
800 allocsize = sizeof(void *) * (ie->nframes
801 + (ie->nrxbufs * 2)
802 + (ie->ntxbufs * 3));
803 ie->rframes = kmalloc(allocsize, M_DEVBUF, M_WAITOK);
804 ie->rbuffs =
805 (volatile struct ie_recv_buf_desc **)&ie->rframes[ie->nframes];
806 ie->cbuffs = (volatile u_char **)&ie->rbuffs[ie->nrxbufs];
807 ie->xmit_cmds =
808 (volatile struct ie_xmit_cmd **)&ie->cbuffs[ie->nrxbufs];
809 ie->xmit_buffs =
810 (volatile struct ie_xmit_buf **)&ie->xmit_cmds[ie->ntxbufs];
811 ie->xmit_cbuffs = (volatile u_char **)&ie->xmit_buffs[ie->ntxbufs];
813 ifp->if_softc = ie;
814 if_initname(ifp, iedriver.name, unit);
815 ifp->if_mtu = ETHERMTU;
816 if_printf(ifp, "<%s R%d>", ie_hardware_names[ie->hard_type],
817 ie->hard_vers + 1);
819 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
820 ifp->if_start = iestart;
821 ifp->if_ioctl = ieioctl;
822 ifp->if_init = ieinit;
823 ifp->if_type = IFT_ETHER;
824 ifp->if_addrlen = 6;
825 ifp->if_hdrlen = 14;
826 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
827 ifq_set_ready(&ifp->if_snd);
829 if (ie->hard_type == IE_EE16)
830 EVENTHANDLER_REGISTER(shutdown_post_sync, ee16_shutdown,
831 ie, SHUTDOWN_PRI_DRIVER);
833 ether_ifattach(ifp, ie->arpcom.ac_enaddr, NULL);
834 return (1);
838 * What to do upon receipt of an interrupt.
840 static void
841 ieintr(void *arg)
843 int unit = (int)arg;
844 struct ie_softc *ie = &ie_softc[unit];
845 u_short status;
847 lwkt_serialize_enter(ie->arpcom.ac_if.if_serializer);
849 /* Clear the interrupt latch on the 3C507. */
850 if (ie->hard_type == IE_3C507
851 && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
852 outb(PORT + IE507_ICTRL, 1);
854 /* disable interrupts on the EE16. */
855 if (ie->hard_type == IE_EE16)
856 outb(PORT + IEE16_IRQ, ie->irq_encoded);
858 status = ie->scb->ie_status;
860 loop:
862 /* Don't ack interrupts which we didn't receive */
863 ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
865 if (status & (IE_ST_RECV | IE_ST_RNR)) {
866 #ifdef DEBUG
867 in_ierint++;
868 if (ie_debug & IED_RINT)
869 kprintf("ie%d: rint\n", unit);
870 #endif
871 ierint(unit, ie);
872 #ifdef DEBUG
873 in_ierint--;
874 #endif
876 if (status & IE_ST_DONE) {
877 #ifdef DEBUG
878 in_ietint++;
879 if (ie_debug & IED_TINT)
880 kprintf("ie%d: tint\n", unit);
881 #endif
882 ietint(unit, ie);
883 #ifdef DEBUG
884 in_ietint--;
885 #endif
887 if (status & IE_ST_RNR) {
888 #ifdef DEBUG
889 if (ie_debug & IED_RNR)
890 kprintf("ie%d: rnr\n", unit);
891 #endif
892 iernr(unit, ie);
894 #ifdef DEBUG
895 if ((status & IE_ST_ALLDONE)
896 && (ie_debug & IED_CNA))
897 kprintf("ie%d: cna\n", unit);
898 #endif
900 if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
901 goto loop;
903 /* Clear the interrupt latch on the 3C507. */
904 if (ie->hard_type == IE_3C507)
905 outb(PORT + IE507_ICTRL, 1);
907 /* enable interrupts on the EE16. */
908 if (ie->hard_type == IE_EE16)
909 outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
911 lwkt_serialize_exit(ie->arpcom.ac_if.if_serializer);
915 * Process a received-frame interrupt.
917 static int
918 ierint(int unit, struct ie_softc *ie)
920 int i, status;
921 static int timesthru = 1024;
923 i = ie->rfhead;
924 while (1) {
925 status = ie->rframes[i]->ie_fd_status;
927 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
928 ie->arpcom.ac_if.if_ipackets++;
929 if (!--timesthru) {
930 ie->arpcom.ac_if.if_ierrors +=
931 ie->scb->ie_err_crc +
932 ie->scb->ie_err_align +
933 ie->scb->ie_err_resource +
934 ie->scb->ie_err_overrun;
935 ie->scb->ie_err_crc = 0;
936 ie->scb->ie_err_align = 0;
937 ie->scb->ie_err_resource = 0;
938 ie->scb->ie_err_overrun = 0;
939 timesthru = 1024;
941 ie_readframe(unit, ie, i);
942 } else {
943 if (status & IE_FD_RNR) {
944 if (!(ie->scb->ie_status & IE_RU_READY)) {
945 ie->rframes[0]->ie_fd_next =
946 MK_16(MEM, ie->rbuffs[0]);
947 ie->scb->ie_recv_list =
948 MK_16(MEM, ie->rframes[0]);
949 command_and_wait(unit, IE_RU_START,
950 0, 0);
953 break;
955 i = (i + 1) % ie->nframes;
957 return (0);
961 * Process a command-complete interrupt. These are only generated by
962 * the transmission of frames. This routine is deceptively simple, since
963 * most of the real work is done by iestart().
965 static int
966 ietint(int unit, struct ie_softc *ie)
968 int status;
969 int i;
971 ie->arpcom.ac_if.if_timer = 0;
972 ie->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
974 for (i = 0; i < ie->xmit_count; i++) {
975 status = ie->xmit_cmds[i]->ie_xmit_status;
977 if (status & IE_XS_LATECOLL) {
978 kprintf("ie%d: late collision\n", unit);
979 ie->arpcom.ac_if.if_collisions++;
980 ie->arpcom.ac_if.if_oerrors++;
981 } else if (status & IE_XS_NOCARRIER) {
982 kprintf("ie%d: no carrier\n", unit);
983 ie->arpcom.ac_if.if_oerrors++;
984 } else if (status & IE_XS_LOSTCTS) {
985 kprintf("ie%d: lost CTS\n", unit);
986 ie->arpcom.ac_if.if_oerrors++;
987 } else if (status & IE_XS_UNDERRUN) {
988 kprintf("ie%d: DMA underrun\n", unit);
989 ie->arpcom.ac_if.if_oerrors++;
990 } else if (status & IE_XS_EXCMAX) {
991 kprintf("ie%d: too many collisions\n", unit);
992 ie->arpcom.ac_if.if_collisions += 16;
993 ie->arpcom.ac_if.if_oerrors++;
994 } else {
995 ie->arpcom.ac_if.if_opackets++;
996 ie->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
999 ie->xmit_count = 0;
1002 * If multicast addresses were added or deleted while we were
1003 * transmitting, ie_mc_reset() set the want_mcsetup flag indicating
1004 * that we should do it.
1006 if (ie->want_mcsetup) {
1007 mc_setup(unit, (v_caddr_t) ie->xmit_cbuffs[0], ie->scb);
1008 ie->want_mcsetup = 0;
1010 /* Wish I knew why this seems to be necessary... */
1011 ie->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
1013 if_devstart(&ie->arpcom.ac_if);
1014 return (0); /* shouldn't be necessary */
1018 * Process a receiver-not-ready interrupt. I believe that we get these
1019 * when there aren't enough buffers to go around. For now (FIXME), we
1020 * just restart the receiver, and hope everything's ok.
1022 static int
1023 iernr(int unit, struct ie_softc *ie)
1025 #ifdef doesnt_work
1026 setup_rfa((v_caddr_t) ie->rframes[0], ie);
1028 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1029 command_and_wait(unit, IE_RU_START, 0, 0);
1030 #else
1031 /* This doesn't work either, but it doesn't hang either. */
1032 command_and_wait(unit, IE_RU_DISABLE, 0, 0); /* just in case */
1033 setup_rfa((v_caddr_t) ie->rframes[0], ie); /* ignore cast-qual */
1035 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1036 command_and_wait(unit, IE_RU_START, 0, 0); /* was ENABLE */
1038 #endif
1039 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
1041 ie->arpcom.ac_if.if_ierrors++;
1042 return (0);
1046 * Compare two Ether/802 addresses for equality, inlined and
1047 * unrolled for speed. I'd love to have an inline assembler
1048 * version of this...
1050 static __inline int
1051 ether_equal(u_char * one, u_char * two)
1053 if (one[0] != two[0])
1054 return (0);
1055 if (one[1] != two[1])
1056 return (0);
1057 if (one[2] != two[2])
1058 return (0);
1059 if (one[3] != two[3])
1060 return (0);
1061 if (one[4] != two[4])
1062 return (0);
1063 if (one[5] != two[5])
1064 return (0);
1065 return 1;
1069 * Determine quickly whether we should bother reading in this packet.
1070 * This depends on whether BPF and/or bridging is enabled, whether we
1071 * are receiving multicast address, and whether promiscuous mode is enabled.
1072 * We assume that if IFF_PROMISC is set, then *somebody* wants to see
1073 * all incoming packets.
1075 static __inline int
1076 check_eh(struct ie_softc *ie, struct ether_header *eh)
1078 /* Optimize the common case: normal operation. We've received
1079 either a unicast with our dest or a multicast packet. */
1080 if (ie->promisc == 0) {
1081 int i;
1083 /* If not multicast, it's definitely for us */
1084 if ((eh->ether_dhost[0] & 1) == 0)
1085 return (1);
1087 /* Accept broadcasts (loose but fast check) */
1088 if (eh->ether_dhost[0] == 0xff)
1089 return (1);
1091 /* Compare against our multicast addresses */
1092 for (i = 0; i < ie->mcast_count; i++) {
1093 if (ether_equal(eh->ether_dhost,
1094 (u_char *)&ie->mcast_addrs[i]))
1095 return (1);
1097 return (0);
1100 /* Always accept packets when in promiscuous mode */
1101 if ((ie->promisc & IFF_PROMISC) != 0)
1102 return (1);
1104 /* Always accept packets directed at us */
1105 if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
1106 return (1);
1108 /* Must have IFF_ALLMULTI but not IFF_PROMISC set. The chip is
1109 actually in promiscuous mode, so discard unicast packets. */
1110 return((eh->ether_dhost[0] & 1) != 0);
1114 * We want to isolate the bits that have meaning... This assumes that
1115 * IE_RBUF_SIZE is an even power of two. If somehow the act_len exceeds
1116 * the size of the buffer, then we are screwed anyway.
1118 static __inline int
1119 ie_buflen(struct ie_softc * ie, int head)
1121 return (ie->rbuffs[head]->ie_rbd_actual
1122 & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
1125 static __inline int
1126 ie_packet_len(int unit, struct ie_softc * ie)
1128 int i;
1129 int head = ie->rbhead;
1130 int acc = 0;
1132 do {
1133 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1134 #ifdef DEBUG
1135 print_rbd(ie->rbuffs[ie->rbhead]);
1136 #endif
1137 log(LOG_ERR,
1138 "ie%d: receive descriptors out of sync at %d\n",
1139 unit, ie->rbhead);
1140 iereset(unit);
1141 return (-1);
1143 i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
1145 acc += ie_buflen(ie, head);
1146 head = (head + 1) % ie->nrxbufs;
1147 } while (!i);
1149 return (acc);
1153 * Read data off the interface, and turn it into an mbuf chain.
1155 * This code is DRAMATICALLY different from the previous version; this
1156 * version tries to allocate the entire mbuf chain up front, given the
1157 * length of the data available. This enables us to allocate mbuf
1158 * clusters in many situations where before we would have had a long
1159 * chain of partially-full mbufs. This should help to speed up the
1160 * operation considerably. (Provided that it works, of course.)
1162 static __inline int
1163 ieget(int unit, struct ie_softc *ie, struct mbuf **mp)
1165 struct mbuf *m, *top, **mymp;
1166 struct ether_header eh;
1167 int i;
1168 int offset;
1169 int totlen, resid;
1170 int thismboff;
1171 int head;
1173 totlen = ie_packet_len(unit, ie);
1174 if (totlen <= 0)
1175 return (-1);
1177 i = ie->rbhead;
1180 * Snarf the Ethernet header.
1182 bcopy((v_caddr_t) ie->cbuffs[i], (caddr_t) &eh, sizeof eh);
1183 /* ignore cast-qual warning here */
1186 * As quickly as possible, check if this packet is for us. If not,
1187 * don't waste a single cycle copying the rest of the packet in.
1188 * This is only a consideration when FILTER is defined; i.e., when
1189 * we are either running BPF or doing multicasting.
1191 if (!check_eh(ie, &eh)) {
1192 ie_drop_packet_buffer(unit, ie);
1193 ie->arpcom.ac_if.if_ierrors--; /* just this case, it's not an
1194 * error
1196 return (-1);
1198 offset = 0;
1200 MGETHDR(*mp, MB_DONTWAIT, MT_DATA);
1201 if (!*mp) {
1202 ie_drop_packet_buffer(unit, ie);
1203 return (-1);
1205 m = *mp;
1206 m->m_len = MHLEN;
1207 resid = m->m_pkthdr.len = totlen;
1208 top = 0;
1209 mymp = &top;
1212 * This loop goes through and allocates mbufs for all the data we
1213 * will be copying in. It does not actually do the copying yet.
1215 do { /* while(resid > 0) */
1217 * Try to allocate an mbuf to hold the data that we have.
1218 * If we already allocated one, just get another one and
1219 * stick it on the end (eventually). If we don't already
1220 * have one, try to allocate an mbuf cluster big enough to
1221 * hold the whole packet, if we think it's reasonable, or a
1222 * single mbuf which may or may not be big enough. Got that?
1224 if (top) {
1225 MGET(m, MB_DONTWAIT, MT_DATA);
1226 if (!m) {
1227 m_freem(top);
1228 ie_drop_packet_buffer(unit, ie);
1229 return (-1);
1231 m->m_len = MLEN;
1233 if (resid >= MINCLSIZE) {
1234 MCLGET(m, MB_DONTWAIT);
1235 if (m->m_flags & M_EXT)
1236 m->m_len = min(resid, MCLBYTES);
1237 } else {
1238 if (resid < m->m_len) {
1239 if (!top && resid + max_linkhdr <= m->m_len)
1240 m->m_data += max_linkhdr;
1241 m->m_len = resid;
1244 resid -= m->m_len;
1245 *mymp = m;
1246 mymp = &m->m_next;
1247 } while (resid > 0);
1249 resid = totlen;
1250 m = top;
1251 thismboff = 0;
1252 head = ie->rbhead;
1255 * Now we take the mbuf chain (hopefully only one mbuf most of the
1256 * time) and stuff the data into it. There are no possible failures
1257 * at or after this point.
1259 while (resid > 0) { /* while there's stuff left */
1260 int thislen = ie_buflen(ie, head) - offset;
1263 * If too much data for the current mbuf, then fill the
1264 * current one up, go to the next one, and try again.
1266 if (thislen > m->m_len - thismboff) {
1267 int newlen = m->m_len - thismboff;
1269 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1270 mtod(m, v_caddr_t) +thismboff, (unsigned) newlen);
1271 /* ignore cast-qual warning */
1272 m = m->m_next;
1273 thismboff = 0; /* new mbuf, so no offset */
1274 offset += newlen; /* we are now this far into
1275 * the packet */
1276 resid -= newlen; /* so there is this much left
1277 * to get */
1278 continue;
1281 * If there is more than enough space in the mbuf to hold
1282 * the contents of this buffer, copy everything in, advance
1283 * pointers, and so on.
1285 if (thislen < m->m_len - thismboff) {
1286 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1287 mtod(m, caddr_t) +thismboff, (unsigned) thislen);
1288 thismboff += thislen; /* we are this far into the
1289 * mbuf */
1290 resid -= thislen; /* and this much is left */
1291 goto nextbuf;
1294 * Otherwise, there is exactly enough space to put this
1295 * buffer's contents into the current mbuf. Do the
1296 * combination of the above actions.
1298 bcopy((v_caddr_t) (ie->cbuffs[head] + offset),
1299 mtod(m, caddr_t) + thismboff, (unsigned) thislen);
1300 m = m->m_next;
1301 thismboff = 0; /* new mbuf, start at the beginning */
1302 resid -= thislen; /* and we are this far through */
1305 * Advance all the pointers. We can get here from either of
1306 * the last two cases, but never the first.
1308 nextbuf:
1309 offset = 0;
1310 ie->rbuffs[head]->ie_rbd_actual = 0;
1311 ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
1312 ie->rbhead = head = (head + 1) % ie->nrxbufs;
1313 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1314 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1318 * Unless something changed strangely while we were doing the copy,
1319 * we have now copied everything in from the shared memory. This
1320 * means that we are done.
1322 return (0);
1326 * Read frame NUM from unit UNIT (pre-cached as IE).
1328 * This routine reads the RFD at NUM, and copies in the buffers from
1329 * the list of RBD, then rotates the RBD and RFD lists so that the receiver
1330 * doesn't start complaining. Trailers are DROPPED---there's no point
1331 * in wasting time on confusing code to deal with them. Hopefully,
1332 * this machine will never ARP for trailers anyway.
1334 static void
1335 ie_readframe(int unit, struct ie_softc *ie, int num/* frame number to read */)
1337 struct ie_recv_frame_desc rfd;
1338 struct mbuf *m = NULL;
1340 bcopy((v_caddr_t) (ie->rframes[num]), &rfd,
1341 sizeof(struct ie_recv_frame_desc));
1344 * Immediately advance the RFD list, since we we have copied ours
1345 * now.
1347 ie->rframes[num]->ie_fd_status = 0;
1348 ie->rframes[num]->ie_fd_last |= IE_FD_LAST;
1349 ie->rframes[ie->rftail]->ie_fd_last &= ~IE_FD_LAST;
1350 ie->rftail = (ie->rftail + 1) % ie->nframes;
1351 ie->rfhead = (ie->rfhead + 1) % ie->nframes;
1353 if (rfd.ie_fd_status & IE_FD_OK) {
1354 if (ieget(unit, ie, &m)) {
1355 ie->arpcom.ac_if.if_ierrors++; /* this counts as an
1356 * error */
1357 return;
1361 if (!m)
1362 return;
1365 * Finally pass this packet up to higher layers.
1367 ie->arpcom.ac_if.if_input(&ie->arpcom.ac_if, m);
1370 static void
1371 ie_drop_packet_buffer(int unit, struct ie_softc * ie)
1373 int i;
1375 do {
1377 * This means we are somehow out of sync. So, we reset the
1378 * adapter.
1380 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1381 #ifdef DEBUG
1382 print_rbd(ie->rbuffs[ie->rbhead]);
1383 #endif
1384 log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
1385 unit, ie->rbhead);
1386 iereset(unit);
1387 return;
1389 i = ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_LAST;
1391 ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
1392 ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
1393 ie->rbhead = (ie->rbhead + 1) % ie->nrxbufs;
1394 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1395 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1396 } while (!i);
1401 * Start transmission on an interface.
1403 static void
1404 iestart(struct ifnet *ifp)
1406 struct ie_softc *ie = ifp->if_softc;
1407 struct mbuf *m0, *m;
1408 volatile unsigned char *buffer;
1409 u_short len;
1412 * This is not really volatile, in this routine, but it makes gcc
1413 * happy.
1415 volatile u_short *bptr = &ie->scb->ie_command_list;
1417 if (!(ifp->if_flags & IFF_RUNNING))
1418 return;
1419 if (ifp->if_flags & IFF_OACTIVE)
1420 return;
1422 do {
1423 m = ifq_dequeue(&ie->arpcom.ac_if.if_snd, NULL);
1424 if (m == NULL)
1425 break;
1427 buffer = ie->xmit_cbuffs[ie->xmit_count];
1428 len = 0;
1430 for (m0 = m; m && len < IE_BUF_LEN; m = m->m_next) {
1431 bcopy(mtod(m, caddr_t), buffer, m->m_len);
1432 buffer += m->m_len;
1433 len += m->m_len;
1436 m_freem(m0);
1437 len = max(len, ETHER_MIN_LEN);
1440 * See if bpf is listening on this interface, let it see the
1441 * packet before we commit it to the wire.
1443 BPF_TAP(&ie->arpcom.ac_if,
1444 __DEVOLATILE(u_char *, ie->xmit_cbuffs[ie->xmit_count]),
1445 len);
1447 ie->xmit_buffs[ie->xmit_count]->ie_xmit_flags =
1448 IE_XMIT_LAST|len;
1449 ie->xmit_buffs[ie->xmit_count]->ie_xmit_next = 0xffff;
1450 ie->xmit_buffs[ie->xmit_count]->ie_xmit_buf =
1451 MK_24(ie->iomem, ie->xmit_cbuffs[ie->xmit_count]);
1453 ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_cmd = IE_CMD_XMIT;
1454 ie->xmit_cmds[ie->xmit_count]->ie_xmit_status = 0;
1455 ie->xmit_cmds[ie->xmit_count]->ie_xmit_desc =
1456 MK_16(ie->iomem, ie->xmit_buffs[ie->xmit_count]);
1458 *bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
1459 bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
1460 ie->xmit_count++;
1461 } while (ie->xmit_count < ie->ntxbufs);
1464 * If we queued up anything for transmission, send it.
1466 if (ie->xmit_count) {
1467 ie->xmit_cmds[ie->xmit_count - 1]->com.ie_cmd_cmd |=
1468 IE_CMD_LAST | IE_CMD_INTR;
1471 * By passing the command pointer as a null, we tell
1472 * command_and_wait() to pretend that this isn't an action
1473 * command. I wish I understood what was happening here.
1475 command_and_wait(ifp->if_dunit, IE_CU_START, 0, 0);
1476 ifp->if_flags |= IFF_OACTIVE;
1478 return;
1482 * Check to see if there's an 82586 out there.
1484 static int
1485 check_ie_present(int unit, caddr_t where, unsigned size)
1487 volatile struct ie_sys_conf_ptr *scp;
1488 volatile struct ie_int_sys_conf_ptr *iscp;
1489 volatile struct ie_sys_ctl_block *scb;
1490 u_long realbase;
1492 realbase = (uintptr_t) where + size - (1 << 24);
1494 scp = (volatile struct ie_sys_conf_ptr *) (uintptr_t)
1495 (realbase + IE_SCP_ADDR);
1496 bzero((volatile char *) scp, sizeof *scp);
1499 * First we put the ISCP at the bottom of memory; this tests to make
1500 * sure that our idea of the size of memory is the same as the
1501 * controller's. This is NOT where the ISCP will be in normal
1502 * operation.
1504 iscp = (volatile struct ie_int_sys_conf_ptr *) where;
1505 bzero((volatile char *)iscp, sizeof *iscp);
1507 scb = (volatile struct ie_sys_ctl_block *) where;
1508 bzero((volatile char *)scb, sizeof *scb);
1510 scp->ie_bus_use = ie_softc[unit].bus_use; /* 8-bit or 16-bit */
1511 scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1512 ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1514 iscp->ie_busy = 1;
1515 iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
1517 (*ie_softc[unit].ie_reset_586) (unit);
1518 (*ie_softc[unit].ie_chan_attn) (unit);
1520 DELAY(100); /* wait a while... */
1522 if (iscp->ie_busy) {
1523 return (0);
1526 * Now relocate the ISCP to its real home, and reset the controller
1527 * again.
1529 iscp = (void *) Align((caddr_t) (uintptr_t)
1530 (realbase + IE_SCP_ADDR -
1531 sizeof(struct ie_int_sys_conf_ptr)));
1532 bzero((volatile char *) iscp, sizeof *iscp); /* ignore cast-qual */
1534 scp->ie_iscp_ptr = (caddr_t) (uintptr_t)
1535 ((volatile char *) iscp - (volatile char *) (uintptr_t) realbase);
1537 iscp->ie_busy = 1;
1538 iscp->ie_scb_offset = MK_16(realbase, scb);
1540 (*ie_softc[unit].ie_reset_586) (unit);
1541 (*ie_softc[unit].ie_chan_attn) (unit);
1543 DELAY(100);
1545 if (iscp->ie_busy) {
1546 return (0);
1548 ie_softc[unit].iosize = size;
1549 ie_softc[unit].iomem = (caddr_t) (uintptr_t) realbase;
1551 ie_softc[unit].iscp = iscp;
1552 ie_softc[unit].scb = scb;
1555 * Acknowledge any interrupts we may have caused...
1557 ie_ack(scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1559 return (1);
1563 * Divine the memory size of ie board UNIT.
1564 * Better hope there's nothing important hiding just below the ie card...
1566 static void
1567 find_ie_mem_size(int unit)
1569 unsigned size;
1571 ie_softc[unit].iosize = 0;
1573 for (size = 65536; size >= 8192; size -= 8192) {
1574 if (check_ie_present(unit, ie_softc[unit].iomembot, size)) {
1575 return;
1579 return;
1582 void
1583 el_reset_586(int unit)
1585 outb(PORT + IE507_CTRL, EL_CTRL_RESET);
1586 DELAY(100);
1587 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
1588 DELAY(100);
1591 void
1592 sl_reset_586(int unit)
1594 outb(PORT + IEATT_RESET, 0);
1597 void
1598 ee16_reset_586(int unit)
1600 outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
1601 DELAY(100);
1602 outb(PORT + IEE16_ECTRL, 0);
1603 DELAY(100);
1606 void
1607 el_chan_attn(int unit)
1609 outb(PORT + IE507_ATTN, 1);
1612 void
1613 sl_chan_attn(int unit)
1615 outb(PORT + IEATT_ATTN, 0);
1618 void
1619 ee16_chan_attn(int unit)
1621 outb(PORT + IEE16_ATTN, 0);
1624 u_short
1625 ee16_read_eeprom(struct ie_softc *sc, int location)
1627 int ectrl, edata;
1629 ectrl = inb(sc->port + IEE16_ECTRL);
1630 ectrl &= IEE16_ECTRL_MASK;
1631 ectrl |= IEE16_ECTRL_EECS;
1632 outb(sc->port + IEE16_ECTRL, ectrl);
1634 ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
1635 ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
1636 edata = ee16_eeprom_inbits(sc);
1637 ectrl = inb(sc->port + IEE16_ECTRL);
1638 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
1639 outb(sc->port + IEE16_ECTRL, ectrl);
1640 ee16_eeprom_clock(sc, 1);
1641 ee16_eeprom_clock(sc, 0);
1642 return edata;
1645 void
1646 ee16_eeprom_outbits(struct ie_softc *sc, int edata, int count)
1648 int ectrl, i;
1650 ectrl = inb(sc->port + IEE16_ECTRL);
1651 ectrl &= ~IEE16_RESET_ASIC;
1652 for (i = count - 1; i >= 0; i--) {
1653 ectrl &= ~IEE16_ECTRL_EEDI;
1654 if (edata & (1 << i)) {
1655 ectrl |= IEE16_ECTRL_EEDI;
1657 outb(sc->port + IEE16_ECTRL, ectrl);
1658 DELAY(1); /* eeprom data must be setup for 0.4 uSec */
1659 ee16_eeprom_clock(sc, 1);
1660 ee16_eeprom_clock(sc, 0);
1662 ectrl &= ~IEE16_ECTRL_EEDI;
1663 outb(sc->port + IEE16_ECTRL, ectrl);
1664 DELAY(1); /* eeprom data must be held for 0.4 uSec */
1668 ee16_eeprom_inbits(struct ie_softc *sc)
1670 int ectrl, edata, i;
1672 ectrl = inb(sc->port + IEE16_ECTRL);
1673 ectrl &= ~IEE16_RESET_ASIC;
1674 for (edata = 0, i = 0; i < 16; i++) {
1675 edata = edata << 1;
1676 ee16_eeprom_clock(sc, 1);
1677 ectrl = inb(sc->port + IEE16_ECTRL);
1678 if (ectrl & IEE16_ECTRL_EEDO) {
1679 edata |= 1;
1681 ee16_eeprom_clock(sc, 0);
1683 return (edata);
1686 void
1687 ee16_eeprom_clock(struct ie_softc *sc, int state)
1689 int ectrl;
1691 ectrl = inb(sc->port + IEE16_ECTRL);
1692 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
1693 if (state) {
1694 ectrl |= IEE16_ECTRL_EESK;
1696 outb(sc->port + IEE16_ECTRL, ectrl);
1697 DELAY(9); /* EESK must be stable for 8.38 uSec */
1700 static __inline void
1701 ee16_interrupt_enable(struct ie_softc *sc)
1703 DELAY(100);
1704 outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
1705 DELAY(100);
1708 void
1709 sl_read_ether(int unit, unsigned char addr[6])
1711 int i;
1713 for (i = 0; i < 6; i++)
1714 addr[i] = inb(PORT + i);
1718 static void
1719 iereset(int unit)
1721 if (unit >= NIE) {
1722 return;
1724 kprintf("ie%d: reset\n", unit);
1725 ie_softc[unit].arpcom.ac_if.if_flags &= ~IFF_UP;
1726 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
1729 * Stop i82586 dead in its tracks.
1731 if (command_and_wait(unit, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
1732 kprintf("ie%d: abort commands timed out\n", unit);
1734 if (command_and_wait(unit, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
1735 kprintf("ie%d: disable commands timed out\n", unit);
1737 #ifdef notdef
1738 if (!check_ie_present(unit, ie_softc[unit].iomembot,
1739 e_softc[unit].iosize))
1740 panic("ie disappeared!");
1741 #endif
1743 ie_softc[unit].arpcom.ac_if.if_flags |= IFF_UP;
1744 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0, (struct ucred *)NULL);
1748 * Send a command to the controller and wait for it to either
1749 * complete or be accepted, depending on the command. If the
1750 * command pointer is null, then pretend that the command is
1751 * not an action command. If the command pointer is not null,
1752 * and the command is an action command, wait for
1753 * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
1754 * to become true.
1756 static int
1757 command_and_wait(int unit, int cmd, volatile void *pcmd, int mask)
1759 volatile struct ie_cmd_common *cc = pcmd;
1761 ie_softc[unit].scb->ie_command = (u_short) cmd;
1763 if (IE_ACTION_COMMAND(cmd) && pcmd) {
1765 * According to the packet driver, the minimum timeout
1766 * should be .369 seconds.
1768 int timer = 370;
1770 (*ie_softc[unit].ie_chan_attn) (unit);
1773 * Now spin-lock waiting for status. This is not a very
1774 * nice thing to do, but I haven't figured out how, or
1775 * indeed if, we can put the process waiting for action to
1776 * sleep. (We may be getting called through some other
1777 * timeout running in the kernel.)
1779 while (--timer > 0) {
1780 if (cc->ie_cmd_status & mask)
1781 break;
1782 DELAY(1000);
1784 if (timer == 0)
1785 return(1);
1786 else
1787 return(0);
1788 } else {
1791 * Otherwise, just wait for the command to be accepted.
1793 (*ie_softc[unit].ie_chan_attn) (unit);
1795 while (ie_softc[unit].scb->ie_command); /* spin lock */
1797 return (0);
1802 * Run the time-domain reflectometer...
1804 static void
1805 run_tdr(int unit, volatile struct ie_tdr_cmd *cmd)
1807 int result;
1809 cmd->com.ie_cmd_status = 0;
1810 cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
1811 cmd->com.ie_cmd_link = 0xffff;
1812 cmd->ie_tdr_time = 0;
1814 ie_softc[unit].scb->ie_command_list = MK_16(MEM, cmd);
1815 cmd->ie_tdr_time = 0;
1817 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL))
1818 result = 0x2000;
1819 else
1820 result = cmd->ie_tdr_time;
1822 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit,
1823 ie_softc[unit].ie_chan_attn);
1825 if (result & IE_TDR_SUCCESS)
1826 return;
1828 if (result & IE_TDR_XCVR) {
1829 kprintf("ie%d: transceiver problem\n", unit);
1830 } else if (result & IE_TDR_OPEN) {
1831 kprintf("ie%d: TDR detected an open %d clocks away\n", unit,
1832 result & IE_TDR_TIME);
1833 } else if (result & IE_TDR_SHORT) {
1834 kprintf("ie%d: TDR detected a short %d clocks away\n", unit,
1835 result & IE_TDR_TIME);
1836 } else {
1837 kprintf("ie%d: TDR returned unknown status %x\n", unit, result);
1841 static void
1842 start_receiver(int unit)
1844 ie_softc[unit].scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1845 command_and_wait(unit, IE_RU_START, 0, 0);
1847 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1851 * Here is a helper routine for iernr() and ieinit(). This sets up
1852 * the RFA.
1854 static v_caddr_t
1855 setup_rfa(v_caddr_t ptr, struct ie_softc * ie)
1857 volatile struct ie_recv_frame_desc *rfd = (volatile void *)ptr;
1858 volatile struct ie_recv_buf_desc *rbd;
1859 int i;
1860 int unit = ie - &ie_softc[0];
1862 /* First lay them out */
1863 for (i = 0; i < ie->nframes; i++) {
1864 ie->rframes[i] = rfd;
1865 bzero((volatile char *) rfd, sizeof *rfd); /* ignore cast-qual */
1866 rfd++;
1869 ptr = Alignvol(rfd); /* ignore cast-qual */
1871 /* Now link them together */
1872 for (i = 0; i < ie->nframes; i++) {
1873 ie->rframes[i]->ie_fd_next =
1874 MK_16(MEM, ie->rframes[(i + 1) % ie->nframes]);
1877 /* Finally, set the EOL bit on the last one. */
1878 ie->rframes[ie->nframes - 1]->ie_fd_last |= IE_FD_LAST;
1881 * Now lay out some buffers for the incoming frames. Note that we
1882 * set aside a bit of slop in each buffer, to make sure that we have
1883 * enough space to hold a single frame in every buffer.
1885 rbd = (volatile void *) ptr;
1887 for (i = 0; i < ie->nrxbufs; i++) {
1888 ie->rbuffs[i] = rbd;
1889 bzero((volatile char *)rbd, sizeof *rbd);
1890 ptr = Alignvol(ptr + sizeof *rbd);
1891 rbd->ie_rbd_length = IE_RBUF_SIZE;
1892 rbd->ie_rbd_buffer = MK_24(MEM, ptr);
1893 ie->cbuffs[i] = (volatile void *) ptr;
1894 ptr += IE_RBUF_SIZE;
1895 rbd = (volatile void *) ptr;
1898 /* Now link them together */
1899 for (i = 0; i < ie->nrxbufs; i++) {
1900 ie->rbuffs[i]->ie_rbd_next =
1901 MK_16(MEM, ie->rbuffs[(i + 1) % ie->nrxbufs]);
1904 /* Tag EOF on the last one */
1905 ie->rbuffs[ie->nrxbufs - 1]->ie_rbd_length |= IE_RBD_LAST;
1908 * We use the head and tail pointers on receive to keep track of the
1909 * order in which RFDs and RBDs are used.
1911 ie->rfhead = 0;
1912 ie->rftail = ie->nframes - 1;
1913 ie->rbhead = 0;
1914 ie->rbtail = ie->nrxbufs - 1;
1916 ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
1917 ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
1919 ptr = Alignvol(ptr);
1920 return (ptr);
1924 * Run the multicast setup command.
1926 static int
1927 mc_setup(int unit, v_caddr_t ptr,
1928 volatile struct ie_sys_ctl_block * scb)
1930 struct ie_softc *ie = &ie_softc[unit];
1931 volatile struct ie_mcast_cmd *cmd = (volatile void *) ptr;
1933 cmd->com.ie_cmd_status = 0;
1934 cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
1935 cmd->com.ie_cmd_link = 0xffff;
1937 /* ignore cast-qual */
1938 bcopy((v_caddr_t) ie->mcast_addrs, (v_caddr_t) cmd->ie_mcast_addrs,
1939 ie->mcast_count * sizeof *ie->mcast_addrs);
1941 cmd->ie_mcast_bytes = ie->mcast_count * 6; /* grrr... */
1943 scb->ie_command_list = MK_16(MEM, cmd);
1944 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
1945 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1946 kprintf("ie%d: multicast address setup command failed\n", unit);
1947 return (0);
1949 return (1);
1953 * This routine takes the environment generated by check_ie_present()
1954 * and adds to it all the other structures we need to operate the adapter.
1955 * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
1956 * starting the receiver unit, and clearing interrupts.
1958 static void
1959 ieinit(void *xsc)
1961 struct ie_softc *ie = xsc;
1962 volatile struct ie_sys_ctl_block *scb = ie->scb;
1963 v_caddr_t ptr;
1964 int i;
1965 int unit = ie->unit;
1967 ptr = Alignvol((volatile char *) scb + sizeof *scb);
1970 * Send the configure command first.
1973 volatile struct ie_config_cmd *cmd = (volatile void *) ptr;
1975 ie_setup_config(cmd, ie->promisc,
1976 ie->hard_type == IE_STARLAN10);
1977 cmd->com.ie_cmd_status = 0;
1978 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
1979 cmd->com.ie_cmd_link = 0xffff;
1981 scb->ie_command_list = MK_16(MEM, cmd);
1983 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
1984 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1985 kprintf("ie%d: configure command failed\n", unit);
1986 return;
1990 * Now send the Individual Address Setup command.
1993 volatile struct ie_iasetup_cmd *cmd = (volatile void *) ptr;
1995 cmd->com.ie_cmd_status = 0;
1996 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
1997 cmd->com.ie_cmd_link = 0xffff;
1999 bcopy((volatile char *)ie_softc[unit].arpcom.ac_enaddr,
2000 (volatile char *)&cmd->ie_address, sizeof cmd->ie_address);
2001 scb->ie_command_list = MK_16(MEM, cmd);
2002 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2003 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2004 kprintf("ie%d: individual address "
2005 "setup command failed\n", unit);
2006 return;
2011 * Now run the time-domain reflectometer.
2013 run_tdr(unit, (volatile void *) ptr);
2016 * Acknowledge any interrupts we have generated thus far.
2018 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
2021 * Set up the RFA.
2023 ptr = setup_rfa(ptr, ie);
2026 * Finally, the transmit command and buffer are the last little bit
2027 * of work.
2030 /* transmit command buffers */
2031 for (i = 0; i < ie->ntxbufs; i++) {
2032 ie->xmit_cmds[i] = (volatile void *) ptr;
2033 ptr += sizeof *ie->xmit_cmds[i];
2034 ptr = Alignvol(ptr);
2035 ie->xmit_buffs[i] = (volatile void *)ptr;
2036 ptr += sizeof *ie->xmit_buffs[i];
2037 ptr = Alignvol(ptr);
2040 /* transmit buffers */
2041 for (i = 0; i < ie->ntxbufs - 1; i++) {
2042 ie->xmit_cbuffs[i] = (volatile void *)ptr;
2043 ptr += IE_BUF_LEN;
2044 ptr = Alignvol(ptr);
2046 ie->xmit_cbuffs[ie->ntxbufs - 1] = (volatile void *) ptr;
2048 for (i = 1; i < ie->ntxbufs; i++) {
2049 bzero((v_caddr_t) ie->xmit_cmds[i], sizeof *ie->xmit_cmds[i]);
2050 bzero((v_caddr_t) ie->xmit_buffs[i], sizeof *ie->xmit_buffs[i]);
2054 * This must be coordinated with iestart() and ietint().
2056 ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
2058 /* take the ee16 out of loopback */
2059 if (ie->hard_type == IE_EE16) {
2060 u_int8_t bart_config;
2062 bart_config = inb(PORT + IEE16_CONFIG);
2063 bart_config &= ~IEE16_BART_LOOPBACK;
2064 /* inb doesn't get bit! */
2065 bart_config |= IEE16_BART_MCS16_TEST;
2066 outb(PORT + IEE16_CONFIG, bart_config);
2067 ee16_interrupt_enable(ie);
2068 ee16_chan_attn(unit);
2070 ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels
2071 * we're here */
2072 start_receiver(unit);
2075 static void
2076 ie_stop(int unit)
2078 command_and_wait(unit, IE_RU_DISABLE, 0, 0);
2081 static int
2082 ieioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2084 int error = 0;
2086 switch (command) {
2087 case SIOCSIFFLAGS:
2089 * Note that this device doesn't have an "all multicast"
2090 * mode, so we must turn on promiscuous mode and do the
2091 * filtering manually.
2093 if ((ifp->if_flags & IFF_UP) == 0 &&
2094 (ifp->if_flags & IFF_RUNNING)) {
2095 ifp->if_flags &= ~IFF_RUNNING;
2096 ie_stop(ifp->if_dunit);
2097 } else if ((ifp->if_flags & IFF_UP) &&
2098 (ifp->if_flags & IFF_RUNNING) == 0) {
2099 ie_softc[ifp->if_dunit].promisc =
2100 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2101 ieinit(ifp->if_softc);
2102 } else if (ie_softc[ifp->if_dunit].promisc ^
2103 (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))) {
2104 ie_softc[ifp->if_dunit].promisc =
2105 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2106 ieinit(ifp->if_softc);
2108 break;
2110 case SIOCADDMULTI:
2111 case SIOCDELMULTI:
2113 * Update multicast listeners
2115 /* reset multicast filtering */
2116 ie_mc_reset(ifp->if_dunit);
2117 error = 0;
2118 break;
2120 default:
2121 error = ether_ioctl(ifp, command, data);
2122 break;
2124 return (error);
2127 static void
2128 ie_mc_reset(int unit)
2130 struct ie_softc *ie = &ie_softc[unit];
2131 struct ifmultiaddr *ifma;
2134 * Step through the list of addresses.
2136 ie->mcast_count = 0;
2137 LIST_FOREACH(ifma, &ie->arpcom.ac_if.if_multiaddrs, ifma_link) {
2138 if (ifma->ifma_addr->sa_family != AF_LINK)
2139 continue;
2141 /* XXX - this is broken... */
2142 if (ie->mcast_count >= MAXMCAST) {
2143 ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
2144 ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *) 0,
2145 (struct ucred *)NULL);
2146 goto setflag;
2148 bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
2149 &(ie->mcast_addrs[ie->mcast_count]), 6);
2150 ie->mcast_count++;
2153 setflag:
2154 ie->want_mcsetup = 1;
2158 #ifdef DEBUG
2159 static void
2160 print_rbd(volatile struct ie_recv_buf_desc * rbd)
2162 kprintf("RBD at %p:\n"
2163 "actual %04x, next %04x, buffer %p\n"
2164 "length %04x, mbz %04x\n",
2165 (volatile void *) rbd,
2166 rbd->ie_rbd_actual, rbd->ie_rbd_next,
2167 (void *) rbd->ie_rbd_buffer,
2168 rbd->ie_rbd_length, rbd->mbz);
2171 #endif /* DEBUG */