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