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