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