xref: /freebsd-12.1/sys/dev/vx/if_vx.c (revision 578d29dd)
1 /*
2  * Copyright (c) 1994 Herb Peyerl <[email protected]>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Herb Peyerl.
16  * 4. The name of Herb Peyerl may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  *
32  */
33 
34 /*
35  * Created from if_ep.c driver by Fred Gray ([email protected]) to support
36  * the 3c590 family.
37  */
38 
39 /*
40  *	Modified from the FreeBSD 1.1.5.1 version by:
41  *		 	Andres Vega Garcia
42  *			INRIA - Sophia Antipolis, France
43  *			[email protected]
44  */
45 
46 /*
47  *  Promiscuous mode added and interrupt logic slightly changed
48  *  to reduce the number of adapter failures. Transceiver select
49  *  logic changed to use value from EEPROM. Autoconfiguration
50  *  features added.
51  *  Done by:
52  *          Serge Babkin
53  *          Chelindbank (Chelyabinsk, Russia)
54  *          [email protected]
55  */
56 
57 #include "vx.h"
58 #if NVX > 0
59 
60 #if NVX < 4	/* These cost 4 bytes apiece, so give us 4 */
61 #undef NVX
62 #define NVX 4
63 #endif
64 
65 #include "bpf.h"
66 
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/sockio.h>
70 #include <sys/malloc.h>
71 #include <sys/mbuf.h>
72 #include <sys/socket.h>
73 
74 #include <net/if.h>
75 
76 #include <net/ethernet.h>
77 #include <net/if_arp.h>
78 
79 #if NBPF > 0
80 #include <net/bpf.h>
81 #endif
82 
83 #include <machine/clock.h>
84 
85 #include <dev/vx/if_vxreg.h>
86 
87 #define ETHER_MAX_LEN	1518
88 #define ETHER_ADDR_LEN	6
89 
90 struct vx_softc *vx_softc[NVX];
91 
92 u_long vx_count;	/* both PCI and EISA */
93 
94 static struct connector_entry {
95   int bit;
96   char *name;
97 } conn_tab[VX_CONNECTORS] = {
98 #define CONNECTOR_UTP	0
99   { 0x08, "utp"},
100 #define CONNECTOR_AUI	1
101   { 0x20, "aui"},
102 /* dummy */
103   { 0, "???"},
104 #define CONNECTOR_BNC	3
105   { 0x10, "bnc"},
106 #define CONNECTOR_TX	4
107   { 0x02, "tx"},
108 #define CONNECTOR_FX	5
109   { 0x04, "fx"},
110 #define CONNECTOR_MII	6
111   { 0x40, "mii"},
112   { 0, "???"}
113 };
114 
115 /* struct vx_softc *vxalloc __P((int)); */
116 /* void *vxfree __P((struct vx_softc *)); */
117 /* int vxattach __P((struct vx_softc *)); */
118 static void vxtxstat __P((struct vx_softc *));
119 static int vxstatus __P((struct vx_softc *));
120 static void vxinit __P((void *));
121 static int vxioctl __P((struct ifnet *, u_long, caddr_t));
122 static void vxstart __P((struct ifnet *ifp));
123 static void vxwatchdog __P((struct ifnet *));
124 static void vxreset __P((struct vx_softc *));
125 /* void vxstop __P((struct vx_softc *)); */
126 static void vxread __P((struct vx_softc *));
127 static struct mbuf *vxget __P((struct vx_softc *, u_int));
128 static void vxmbuffill __P((void *));
129 static void vxmbufempty __P((struct vx_softc *));
130 static void vxsetfilter __P((struct vx_softc *));
131 static void vxgetlink __P((struct vx_softc *));
132 static void vxsetlink __P((struct vx_softc *));
133 /* int vxbusyeeprom __P((struct vx_softc *)); */
134 
135 struct vx_softc *
136 vxalloc(unit)
137     int unit;
138 {
139     struct vx_softc *sc;
140 
141     if (unit >= NVX) {
142 	printf("vx%d: unit number too high.\n", unit);
143 	return NULL;
144     }
145 
146     if (vx_softc[unit]) {
147 	printf("vx%d: already allocated.\n", unit);
148 	return NULL;
149     }
150 
151     sc = malloc(sizeof(struct vx_softc), M_DEVBUF, M_NOWAIT);
152     if (sc == NULL) {
153 	printf("vx%d: cannot malloc.\n", unit);
154 	return NULL;
155     }
156     bzero(sc, sizeof(struct vx_softc));
157     callout_handle_init(&sc->ch);
158 
159     vx_softc[unit] = sc;
160     sc->unit = unit;
161     return (sc);
162 }
163 
164 void
165 vxfree(sc)
166     struct vx_softc *sc;
167 {
168     vx_softc[sc->unit] = NULL;
169     free(sc, M_DEVBUF);
170     return;
171 }
172 
173 int
174 vxattach(sc)
175     struct vx_softc *sc;
176 {
177     struct ifnet *ifp = &sc->arpcom.ac_if;
178     int i;
179 
180     GO_WINDOW(0);
181     outw(VX_COMMAND, GLOBAL_RESET);
182     VX_BUSY_WAIT;
183 
184     vxgetlink(sc);
185 
186     /*
187      * Read the station address from the eeprom
188      */
189     GO_WINDOW(0);
190     for (i = 0; i < 3; i++) {
191         int x;
192         if (vxbusyeeprom(sc))
193             return 0;
194         outw(BASE + VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD
195 	     | (EEPROM_OEM_ADDR_0 + i));
196         if (vxbusyeeprom(sc))
197             return 0;
198         x = inw(BASE + VX_W0_EEPROM_DATA);
199         sc->arpcom.ac_enaddr[(i << 1)] = x >> 8;
200         sc->arpcom.ac_enaddr[(i << 1) + 1] = x;
201     }
202 
203     printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
204 
205     ifp->if_unit = sc->unit;
206     ifp->if_name = "vx";
207     ifp->if_mtu = ETHERMTU;
208     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
209     ifp->if_output = ether_output;
210     ifp->if_start = vxstart;
211     ifp->if_ioctl = vxioctl;
212     ifp->if_init = vxinit;
213     ifp->if_watchdog = vxwatchdog;
214     ifp->if_softc = sc;
215 
216     if_attach(ifp);
217     ether_ifattach(ifp);
218 
219 #if NBPF > 0
220     bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
221 #endif
222 
223     sc->tx_start_thresh = 20;	/* probably a good starting point. */
224 
225     vxstop(sc);
226 
227     return 1;
228 }
229 
230 
231 
232 /*
233  * The order in here seems important. Otherwise we may not receive
234  * interrupts. ?!
235  */
236 static void
237 vxinit(xsc)
238 	void *xsc;
239 {
240     struct vx_softc *sc = (struct vx_softc *) xsc;
241     struct ifnet *ifp = &sc->arpcom.ac_if;
242     int i;
243 
244     VX_BUSY_WAIT;
245 
246     GO_WINDOW(2);
247 
248     for (i = 0; i < 6; i++) /* Reload the ether_addr. */
249 	outb(BASE + VX_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
250 
251     outw(BASE + VX_COMMAND, RX_RESET);
252     VX_BUSY_WAIT;
253     outw(BASE + VX_COMMAND, TX_RESET);
254     VX_BUSY_WAIT;
255 
256     GO_WINDOW(1);	/* Window 1 is operating window */
257     for (i = 0; i < 31; i++)
258 	inb(BASE + VX_W1_TX_STATUS);
259 
260     outw(BASE + VX_COMMAND,SET_RD_0_MASK | S_CARD_FAILURE |
261 			S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
262     outw(BASE + VX_COMMAND,SET_INTR_MASK | S_CARD_FAILURE |
263 			S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
264 
265     /*
266      * Attempt to get rid of any stray interrupts that occured during
267      * configuration.  On the i386 this isn't possible because one may
268      * already be queued.  However, a single stray interrupt is
269      * unimportant.
270      */
271     outw(BASE + VX_COMMAND, ACK_INTR | 0xff);
272 
273     vxsetfilter(sc);
274     vxsetlink(sc);
275 
276     outw(BASE + VX_COMMAND, RX_ENABLE);
277     outw(BASE + VX_COMMAND, TX_ENABLE);
278 
279     vxmbuffill((caddr_t) sc);
280 
281     /* Interface is now `running', with no output active. */
282     ifp->if_flags |= IFF_RUNNING;
283     ifp->if_flags &= ~IFF_OACTIVE;
284 
285     /* Attempt to start output, if any. */
286     vxstart(ifp);
287 }
288 
289 static void
290 vxsetfilter(sc)
291     struct vx_softc *sc;
292 {
293     register struct ifnet *ifp = &sc->arpcom.ac_if;
294 
295     GO_WINDOW(1);           /* Window 1 is operating window */
296     outw(BASE + VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST |
297 	 FIL_MULTICAST |
298 	 ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
299 }
300 
301 static void
302 vxgetlink(sc)
303     struct vx_softc *sc;
304 {
305     int n, k;
306 
307     GO_WINDOW(3);
308     sc->vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f;
309     for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
310       if (sc->vx_connectors & conn_tab[k].bit) {
311 	if (n > 0) {
312 	  printf("/");
313 	}
314 	printf(conn_tab[k].name);
315 	n++;
316       }
317     }
318     if (sc->vx_connectors == 0) {
319 	printf("no connectors!");
320 	return;
321     }
322     GO_WINDOW(3);
323     sc->vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG)
324 			& INTERNAL_CONNECTOR_MASK)
325 			>> INTERNAL_CONNECTOR_BITS;
326     if (sc->vx_connector & 0x10) {
327 	sc->vx_connector &= 0x0f;
328 	printf("[*%s*]", conn_tab[(int)sc->vx_connector].name);
329 	printf(": disable 'auto select' with DOS util!");
330     } else {
331 	printf("[*%s*]", conn_tab[(int)sc->vx_connector].name);
332     }
333 }
334 
335 static void
336 vxsetlink(sc)
337     struct vx_softc *sc;
338 {
339     register struct ifnet *ifp = &sc->arpcom.ac_if;
340     int i, j, k;
341     char *reason, *warning;
342     static short prev_flags;
343     static char prev_conn = -1;
344 
345     if (prev_conn == -1) {
346 	prev_conn = sc->vx_connector;
347     }
348 
349     /*
350      * S.B.
351      *
352      * Now behavior was slightly changed:
353      *
354      * if any of flags link[0-2] is used and its connector is
355      * physically present the following connectors are used:
356      *
357      *   link0 - AUI * highest precedence
358      *   link1 - BNC
359      *   link2 - UTP * lowest precedence
360      *
361      * If none of them is specified then
362      * connector specified in the EEPROM is used
363      * (if present on card or UTP if not).
364      */
365 
366     i = sc->vx_connector;	/* default in EEPROM */
367     reason = "default";
368     warning = 0;
369 
370     if (ifp->if_flags & IFF_LINK0) {
371 	if (sc->vx_connectors & conn_tab[CONNECTOR_AUI].bit) {
372 	    i = CONNECTOR_AUI;
373 	    reason = "link0";
374 	} else {
375 	    warning = "aui not present! (link0)";
376 	}
377     } else if (ifp->if_flags & IFF_LINK1) {
378 	if (sc->vx_connectors & conn_tab[CONNECTOR_BNC].bit) {
379 	    i = CONNECTOR_BNC;
380 	    reason = "link1";
381 	} else {
382 	    warning = "bnc not present! (link1)";
383 	}
384     } else if (ifp->if_flags & IFF_LINK2) {
385 	if (sc->vx_connectors & conn_tab[CONNECTOR_UTP].bit) {
386 	    i = CONNECTOR_UTP;
387 	    reason = "link2";
388 	} else {
389 	    warning = "utp not present! (link2)";
390 	}
391     } else if ((sc->vx_connectors & conn_tab[(int)sc->vx_connector].bit) == 0) {
392 	warning = "strange connector type in EEPROM.";
393 	reason = "forced";
394 	i = CONNECTOR_UTP;
395     }
396 
397     /* Avoid unnecessary message. */
398     k = (prev_flags ^ ifp->if_flags) & (IFF_LINK0 | IFF_LINK1 | IFF_LINK2);
399     if ((k != 0) || (prev_conn != i)) {
400 	if (warning != 0) {
401 	    printf("vx%d: warning: %s\n", sc->unit, warning);
402 	}
403 	printf("vx%d: selected %s. (%s)\n",
404 	       sc->unit, conn_tab[i].name, reason);
405     }
406 
407     /* Set the selected connector. */
408     GO_WINDOW(3);
409     j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
410     outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
411 
412     /* First, disable all. */
413     outw(BASE + VX_COMMAND, STOP_TRANSCEIVER);
414     DELAY(800);
415     GO_WINDOW(4);
416     outw(BASE + VX_W4_MEDIA_TYPE, 0);
417 
418     /* Second, enable the selected one. */
419     switch(i) {
420       case CONNECTOR_UTP:
421 	GO_WINDOW(4);
422 	outw(BASE + VX_W4_MEDIA_TYPE, ENABLE_UTP);
423 	break;
424       case CONNECTOR_BNC:
425 	outw(BASE + VX_COMMAND, START_TRANSCEIVER);
426 	DELAY(800);
427 	break;
428       case CONNECTOR_TX:
429       case CONNECTOR_FX:
430 	GO_WINDOW(4);
431 	outw(BASE + VX_W4_MEDIA_TYPE, LINKBEAT_ENABLE);
432 	break;
433       default:	/* AUI and MII fall here */
434 	break;
435     }
436     GO_WINDOW(1);
437 
438     prev_flags = ifp->if_flags;
439     prev_conn = i;
440 }
441 
442 static void
443 vxstart(ifp)
444     struct ifnet *ifp;
445 {
446     register struct vx_softc *sc = vx_softc[ifp->if_unit];
447     register struct mbuf *m, *m0;
448     int sh, len, pad;
449 
450     /* Don't transmit if interface is busy or not running */
451     if ((sc->arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
452 	return;
453 
454 startagain:
455     /* Sneak a peek at the next packet */
456     m0 = ifp->if_snd.ifq_head;
457     if (m0 == 0) {
458 	return;
459     }
460     /* We need to use m->m_pkthdr.len, so require the header */
461      if ((m0->m_flags & M_PKTHDR) == 0)
462 	panic("vxstart: no header mbuf");
463      len = m0->m_pkthdr.len;
464 
465      pad = (4 - len) & 3;
466 
467     /*
468      * The 3c509 automatically pads short packets to minimum ethernet length,
469      * but we drop packets that are too large. Perhaps we should truncate
470      * them instead?
471      */
472     if (len + pad > ETHER_MAX_LEN) {
473 	/* packet is obviously too large: toss it */
474 	++ifp->if_oerrors;
475 	IF_DEQUEUE(&ifp->if_snd, m0);
476 	m_freem(m0);
477 	goto readcheck;
478     }
479     VX_BUSY_WAIT;
480     if (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) {
481 	outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> 2));
482 	/* not enough room in FIFO */
483 	if (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) { /* make sure */
484 	    ifp->if_flags |= IFF_OACTIVE;
485 	    ifp->if_timer = 1;
486 	    return;
487 	}
488     }
489     outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2));
490     IF_DEQUEUE(&ifp->if_snd, m0);
491     if (m0 == 0) {		/* not really needed */
492 	return;
493     }
494 
495     VX_BUSY_WAIT;
496     outw(BASE + VX_COMMAND, SET_TX_START_THRESH |
497 	((len / 4 + sc->tx_start_thresh) >> 2));
498 
499 #if NBPF > 0
500     if (sc->arpcom.ac_if.if_bpf) {
501 	bpf_mtap(&sc->arpcom.ac_if, m0);
502     }
503 #endif
504 
505     /*
506      * Do the output at splhigh() so that an interrupt from another device
507      * won't cause a FIFO underrun.
508      */
509     sh = splhigh();
510 
511     outl(BASE + VX_W1_TX_PIO_WR_1, len | TX_INDICATE);
512 
513     for (m = m0; m != 0;) {
514         if (m->m_len > 3)
515 	    outsl(BASE + VX_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 4);
516         if (m->m_len & 3)
517 	    outsb(BASE + VX_W1_TX_PIO_WR_1,
518 	      mtod(m, caddr_t) + (m->m_len & ~3) , m->m_len & 3);
519         MFREE(m, m0);
520         m = m0;
521     }
522     while (pad--)
523 	outb(BASE + VX_W1_TX_PIO_WR_1, 0);	/* Padding */
524 
525     splx(sh);
526 
527     ++ifp->if_opackets;
528     ifp->if_timer = 1;
529 
530 readcheck:
531     if ((inw(BASE + VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
532 	/* We received a complete packet. */
533 
534 	if ((inw(BASE + VX_STATUS) & S_INTR_LATCH) == 0) {
535 	    /*
536 	     * No interrupt, read the packet and continue
537 	     * Is  this supposed to happen? Is my motherboard
538 	     * completely busted?
539 	     */
540 	    vxread(sc);
541 	} else
542 	    /* Got an interrupt, return so that it gets serviced. */
543 	    return;
544     } else {
545 	/* Check if we are stuck and reset [see XXX comment] */
546 	if (vxstatus(sc)) {
547 	    if (ifp->if_flags & IFF_DEBUG)
548 	       printf("vx%d: adapter reset\n", ifp->if_unit);
549 	    vxreset(sc);
550 	}
551     }
552 
553     goto startagain;
554 }
555 
556 /*
557  * XXX: The 3c509 card can get in a mode where both the fifo status bit
558  *      FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
559  *      We detect this situation and we reset the adapter.
560  *      It happens at times when there is a lot of broadcast traffic
561  *      on the cable (once in a blue moon).
562  */
563 static int
564 vxstatus(sc)
565     struct vx_softc *sc;
566 {
567     int fifost;
568 
569     /*
570      * Check the FIFO status and act accordingly
571      */
572     GO_WINDOW(4);
573     fifost = inw(BASE + VX_W4_FIFO_DIAG);
574     GO_WINDOW(1);
575 
576     if (fifost & FIFOS_RX_UNDERRUN) {
577 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
578 	    printf("vx%d: RX underrun\n", sc->unit);
579 	vxreset(sc);
580 	return 0;
581     }
582 
583     if (fifost & FIFOS_RX_STATUS_OVERRUN) {
584 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
585 	    printf("vx%d: RX Status overrun\n", sc->unit);
586 	return 1;
587     }
588 
589     if (fifost & FIFOS_RX_OVERRUN) {
590 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
591 	    printf("vx%d: RX overrun\n", sc->unit);
592 	return 1;
593     }
594 
595     if (fifost & FIFOS_TX_OVERRUN) {
596 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
597 	    printf("vx%d: TX overrun\n", sc->unit);
598 	vxreset(sc);
599 	return 0;
600     }
601 
602     return 0;
603 }
604 
605 static void
606 vxtxstat(sc)
607     struct vx_softc *sc;
608 {
609     int i;
610 
611     /*
612     * We need to read+write TX_STATUS until we get a 0 status
613     * in order to turn off the interrupt flag.
614     */
615     while ((i = inb(BASE + VX_W1_TX_STATUS)) & TXS_COMPLETE) {
616 	outb(BASE + VX_W1_TX_STATUS, 0x0);
617 
618     if (i & TXS_JABBER) {
619 	++sc->arpcom.ac_if.if_oerrors;
620 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
621 	    printf("vx%d: jabber (%x)\n", sc->unit, i);
622 	vxreset(sc);
623     } else if (i & TXS_UNDERRUN) {
624 	++sc->arpcom.ac_if.if_oerrors;
625 	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
626 	    printf("vx%d: fifo underrun (%x) @%d\n",
627 		sc->unit, i, sc->tx_start_thresh);
628 	if (sc->tx_succ_ok < 100)
629 	    sc->tx_start_thresh = min(ETHER_MAX_LEN, sc->tx_start_thresh + 20);
630 	sc->tx_succ_ok = 0;
631 	vxreset(sc);
632     } else if (i & TXS_MAX_COLLISION) {
633 	++sc->arpcom.ac_if.if_collisions;
634 	outw(BASE + VX_COMMAND, TX_ENABLE);
635 	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
636     } else
637 	sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
638     }
639 }
640 
641 void
642 vxintr(voidsc)
643     void *voidsc;
644 {
645     register short status;
646     struct vx_softc *sc = voidsc;
647     struct ifnet *ifp = &sc->arpcom.ac_if;
648 
649     for (;;) {
650 	outw(BASE + VX_COMMAND, C_INTR_LATCH);
651 
652 	status = inw(BASE + VX_STATUS);
653 
654 	if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
655 		S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
656 	    break;
657 
658 	/*
659 	 * Acknowledge any interrupts.  It's important that we do this
660 	 * first, since there would otherwise be a race condition.
661 	 * Due to the i386 interrupt queueing, we may get spurious
662 	 * interrupts occasionally.
663 	 */
664 	outw(BASE + VX_COMMAND, ACK_INTR | status);
665 
666 	if (status & S_RX_COMPLETE)
667 	    vxread(sc);
668 	if (status & S_TX_AVAIL) {
669 	    ifp->if_timer = 0;
670 	    sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
671 	    vxstart(&sc->arpcom.ac_if);
672 	}
673 	if (status & S_CARD_FAILURE) {
674 	    printf("vx%d: adapter failure (%x)\n", sc->unit, status);
675 	    ifp->if_timer = 0;
676 	    vxreset(sc);
677 	    return;
678 	}
679 	if (status & S_TX_COMPLETE) {
680 	    ifp->if_timer = 0;
681 	    vxtxstat(sc);
682 	    vxstart(ifp);
683 	}
684     }
685 
686     /* no more interrupts */
687     return;
688 }
689 
690 static void
691 vxread(sc)
692     struct vx_softc *sc;
693 {
694     struct ifnet *ifp = &sc->arpcom.ac_if;
695     struct mbuf *m;
696     struct ether_header *eh;
697     u_int len;
698 
699     len = inw(BASE + VX_W1_RX_STATUS);
700 
701 again:
702 
703     if (ifp->if_flags & IFF_DEBUG) {
704 	int err = len & ERR_MASK;
705 	char *s = NULL;
706 
707 	if (len & ERR_INCOMPLETE)
708 	    s = "incomplete packet";
709 	else if (err == ERR_OVERRUN)
710 	    s = "packet overrun";
711 	else if (err == ERR_RUNT)
712 	    s = "runt packet";
713 	else if (err == ERR_ALIGNMENT)
714 	    s = "bad alignment";
715 	else if (err == ERR_CRC)
716 	    s = "bad crc";
717 	else if (err == ERR_OVERSIZE)
718 	    s = "oversized packet";
719 	else if (err == ERR_DRIBBLE)
720 	    s = "dribble bits";
721 
722 	if (s)
723 	printf("vx%d: %s\n", sc->unit, s);
724     }
725 
726     if (len & ERR_INCOMPLETE)
727 	return;
728 
729     if (len & ERR_RX) {
730 	++ifp->if_ierrors;
731 	goto abort;
732     }
733 
734     len &= RX_BYTES_MASK;	/* Lower 11 bits = RX bytes. */
735 
736     /* Pull packet off interface. */
737     m = vxget(sc, len);
738     if (m == 0) {
739 	ifp->if_ierrors++;
740 	goto abort;
741     }
742 
743     ++ifp->if_ipackets;
744 
745     /* We assume the header fit entirely in one mbuf. */
746     eh = mtod(m, struct ether_header *);
747 
748 #if NBPF > 0
749     /*
750      * Check if there's a BPF listener on this interface.
751      * If so, hand off the raw packet to BPF.
752      */
753     if (sc->arpcom.ac_if.if_bpf) {
754 	bpf_mtap(&sc->arpcom.ac_if, m);
755     }
756 #endif
757 
758     /*
759      * XXX: Some cards seem to be in promiscous mode all the time.
760      * we need to make sure we only get our own stuff always.
761      * bleah!
762      */
763 
764     if ((eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
765 	bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
766 	sizeof(eh->ether_dhost)) != 0) {
767 	m_freem(m);
768 	    return;
769     }
770     /* We assume the header fit entirely in one mbuf. */
771     m_adj(m, sizeof(struct ether_header));
772     ether_input(ifp, eh, m);
773 
774     /*
775     * In periods of high traffic we can actually receive enough
776     * packets so that the fifo overrun bit will be set at this point,
777     * even though we just read a packet. In this case we
778     * are not going to receive any more interrupts. We check for
779     * this condition and read again until the fifo is not full.
780     * We could simplify this test by not using vxstatus(), but
781     * rechecking the RX_STATUS register directly. This test could
782     * result in unnecessary looping in cases where there is a new
783     * packet but the fifo is not full, but it will not fix the
784     * stuck behavior.
785     *
786     * Even with this improvement, we still get packet overrun errors
787     * which are hurting performance. Maybe when I get some more time
788     * I'll modify vxread() so that it can handle RX_EARLY interrupts.
789     */
790     if (vxstatus(sc)) {
791 	len = inw(BASE + VX_W1_RX_STATUS);
792 	/* Check if we are stuck and reset [see XXX comment] */
793 	if (len & ERR_INCOMPLETE) {
794 	    if (ifp->if_flags & IFF_DEBUG)
795 		printf("vx%d: adapter reset\n", sc->unit);
796 	    vxreset(sc);
797 	    return;
798 	}
799 	goto again;
800     }
801 
802     return;
803 
804 abort:
805     outw(BASE + VX_COMMAND, RX_DISCARD_TOP_PACK);
806 }
807 
808 static struct mbuf *
809 vxget(sc, totlen)
810     struct vx_softc *sc;
811     u_int totlen;
812 {
813     struct ifnet *ifp = &sc->arpcom.ac_if;
814     struct mbuf *top, **mp, *m;
815     int len;
816     int sh;
817 
818     m = sc->mb[sc->next_mb];
819     sc->mb[sc->next_mb] = 0;
820     if (m == 0) {
821         MGETHDR(m, M_DONTWAIT, MT_DATA);
822         if (m == 0)
823             return 0;
824     } else {
825         /* If the queue is no longer full, refill. */
826         if (sc->last_mb == sc->next_mb && sc->buffill_pending == 0) {
827 	    sc->ch = timeout(vxmbuffill, sc, 1);
828 	    sc->buffill_pending = 1;
829 	}
830         /* Convert one of our saved mbuf's. */
831         sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
832         m->m_data = m->m_pktdat;
833         m->m_flags = M_PKTHDR;
834     }
835     m->m_pkthdr.rcvif = ifp;
836     m->m_pkthdr.len = totlen;
837     len = MHLEN;
838     top = 0;
839     mp = &top;
840 
841     /*
842      * We read the packet at splhigh() so that an interrupt from another
843      * device doesn't cause the card's buffer to overflow while we're
844      * reading it.  We may still lose packets at other times.
845      */
846     sh = splhigh();
847 
848     /*
849      * Since we don't set allowLargePackets bit in MacControl register,
850      * we can assume that totlen <= 1500bytes.
851      * The while loop will be performed iff we have a packet with
852      * MLEN < m_len < MINCLSIZE.
853      */
854     while (totlen > 0) {
855         if (top) {
856             m = sc->mb[sc->next_mb];
857             sc->mb[sc->next_mb] = 0;
858             if (m == 0) {
859                 MGET(m, M_DONTWAIT, MT_DATA);
860                 if (m == 0) {
861                     splx(sh);
862                     m_freem(top);
863                     return 0;
864                 }
865             } else {
866                 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
867             }
868             len = MLEN;
869         }
870         if (totlen >= MINCLSIZE) {
871 	    MCLGET(m, M_DONTWAIT);
872 	    if (m->m_flags & M_EXT)
873 		len = MCLBYTES;
874         }
875         len = min(totlen, len);
876         if (len > 3)
877             insl(BASE + VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4);
878 	if (len & 3) {
879 	    insb(BASE + VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3),
880 		len & 3);
881 	}
882         m->m_len = len;
883         totlen -= len;
884         *mp = m;
885         mp = &m->m_next;
886     }
887 
888     outw(BASE +VX_COMMAND, RX_DISCARD_TOP_PACK);
889 
890     splx(sh);
891 
892     return top;
893 }
894 
895 
896 static int
897 vxioctl(ifp, cmd, data)
898     register struct ifnet *ifp;
899     u_long cmd;
900     caddr_t data;
901 {
902     struct vx_softc *sc = vx_softc[ifp->if_unit];
903     struct ifreq *ifr = (struct ifreq *) data;
904     int s, error = 0;
905 
906     s = splimp();
907 
908     switch (cmd) {
909     case SIOCSIFADDR:
910     case SIOCGIFADDR:
911 	ether_ioctl(ifp, cmd, data);
912 	break;
913 
914     case SIOCSIFFLAGS:
915 	if ((ifp->if_flags & IFF_UP) == 0 &&
916 	    (ifp->if_flags & IFF_RUNNING) != 0) {
917 	    /*
918              * If interface is marked up and it is stopped, then
919              * start it.
920              */
921 	    vxstop(sc);
922 	    ifp->if_flags &= ~IFF_RUNNING;
923         } else if ((ifp->if_flags & IFF_UP) != 0 &&
924                    (ifp->if_flags & IFF_RUNNING) == 0) {
925             /*
926              * If interface is marked up and it is stopped, then
927              * start it.
928              */
929             vxinit(sc);
930         } else {
931             /*
932              * deal with flags changes:
933              * IFF_MULTICAST, IFF_PROMISC,
934              * IFF_LINK0, IFF_LINK1,
935              */
936             vxsetfilter(sc);
937             vxsetlink(sc);
938         }
939         break;
940 
941     case SIOCSIFMTU:
942         /*
943          * Set the interface MTU.
944          */
945         if (ifr->ifr_mtu > ETHERMTU) {
946             error = EINVAL;
947         } else {
948             ifp->if_mtu = ifr->ifr_mtu;
949         }
950         break;
951 
952     case SIOCADDMULTI:
953     case SIOCDELMULTI:
954 	/*
955 	 * Multicast list has changed; set the hardware filter
956 	 * accordingly.
957 	 */
958 	vxreset(sc);
959 	error = 0;
960         break;
961 
962 
963     default:
964         error = EINVAL;
965     }
966 
967     splx(s);
968 
969     return (error);
970 }
971 
972 static void
973 vxreset(sc)
974     struct vx_softc *sc;
975 {
976     int s;
977     s = splimp();
978 
979     vxstop(sc);
980     vxinit(sc);
981     splx(s);
982 }
983 
984 static void
985 vxwatchdog(ifp)
986     struct ifnet *ifp;
987 {
988     struct vx_softc *sc = vx_softc[ifp->if_unit];
989 
990     if (ifp->if_flags & IFF_DEBUG)
991 	printf("vx%d: device timeout\n", ifp->if_unit);
992     ifp->if_flags &= ~IFF_OACTIVE;
993     vxstart(ifp);
994     vxintr(sc);
995 }
996 
997 void
998 vxstop(sc)
999     struct vx_softc *sc;
1000 {
1001     struct ifnet *ifp = &sc->arpcom.ac_if;
1002 
1003     ifp->if_timer = 0;
1004 
1005     outw(BASE + VX_COMMAND, RX_DISABLE);
1006     outw(BASE + VX_COMMAND, RX_DISCARD_TOP_PACK);
1007     VX_BUSY_WAIT;
1008     outw(BASE + VX_COMMAND, TX_DISABLE);
1009     outw(BASE + VX_COMMAND, STOP_TRANSCEIVER);
1010     DELAY(800);
1011     outw(BASE + VX_COMMAND, RX_RESET);
1012     VX_BUSY_WAIT;
1013     outw(BASE + VX_COMMAND, TX_RESET);
1014     VX_BUSY_WAIT;
1015     outw(BASE + VX_COMMAND, C_INTR_LATCH);
1016     outw(BASE + VX_COMMAND, SET_RD_0_MASK);
1017     outw(BASE + VX_COMMAND, SET_INTR_MASK);
1018     outw(BASE + VX_COMMAND, SET_RX_FILTER);
1019 
1020     vxmbufempty(sc);
1021 }
1022 
1023 int
1024 vxbusyeeprom(sc)
1025     struct vx_softc *sc;
1026 {
1027     int j, i = 100;
1028 
1029     while (i--) {
1030         j = inw(BASE + VX_W0_EEPROM_COMMAND);
1031         if (j & EEPROM_BUSY)
1032             DELAY(100);
1033         else
1034             break;
1035     }
1036     if (!i) {
1037         printf("vx%d: eeprom failed to come ready\n", sc->unit);
1038         return (1);
1039     }
1040     return (0);
1041 }
1042 
1043 static void
1044 vxmbuffill(sp)
1045     void *sp;
1046 {
1047     struct vx_softc *sc = (struct vx_softc *) sp;
1048     int s, i;
1049 
1050     s = splimp();
1051     i = sc->last_mb;
1052     do {
1053 	if (sc->mb[i] == NULL)
1054 	    MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1055 	if (sc->mb[i] == NULL)
1056 	    break;
1057 	i = (i + 1) % MAX_MBS;
1058     } while (i != sc->next_mb);
1059     sc->last_mb = i;
1060     /* If the queue was not filled, try again. */
1061     if (sc->last_mb != sc->next_mb) {
1062 	sc->ch = timeout(vxmbuffill, sc, 1);
1063 	sc->buffill_pending = 1;
1064     } else {
1065 	sc->buffill_pending = 0;
1066     }
1067     splx(s);
1068 }
1069 
1070 static void
1071 vxmbufempty(sc)
1072     struct vx_softc *sc;
1073 {
1074     int s, i;
1075 
1076     s = splimp();
1077     for (i = 0; i < MAX_MBS; i++) {
1078 	if (sc->mb[i]) {
1079 	    m_freem(sc->mb[i]);
1080 	    sc->mb[i] = NULL;
1081 	}
1082     }
1083     sc->last_mb = sc->next_mb = 0;
1084     if (sc->buffill_pending != 0)
1085 	untimeout(vxmbuffill, sc, sc->ch);
1086     splx(s);
1087 }
1088 
1089 #endif				/* NVX > 0 */
1090