if_ep.c revision 11872
1258945Sroberto/*
2258945Sroberto * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
3258945Sroberto * All rights reserved.
4280849Scy *
5280849Scy * Redistribution and use in source and binary forms, with or without
6280849Scy * modification, are permitted provided that the following conditions
7280849Scy * are met:
8280849Scy * 1. Redistributions of source code must retain the above copyright
9280849Scy *    notice, this list of conditions and the following disclaimer.
10280849Scy * 2. Redistributions in binary form must reproduce the above copyright
11280849Scy *    notice, this list of conditions and the following disclaimer in the
12280849Scy *    documentation and/or other materials provided with the distribution.
13280849Scy * 3. All advertising materials mentioning features or use of this software
14280849Scy *    must display the following acknowledgement:
15280849Scy *      This product includes software developed by Herb Peyerl.
16280849Scy * 4. The name of Herb Peyerl may not be used to endorse or promote products
17280849Scy *    derived from this software without specific prior written permission.
18258945Sroberto *
19258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20258945Sroberto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21258945Sroberto * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22258945Sroberto * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23258945Sroberto * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24258945Sroberto * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25258945Sroberto * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26258945Sroberto * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27258945Sroberto * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28258945Sroberto * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29258945Sroberto *
30258945Sroberto *	if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp
31258945Sroberto */
32258945Sroberto
33258945Sroberto/*
34280849Scy *	Modified from the FreeBSD 1.1.5.1 version by:
35258945Sroberto *		 	Andres Vega Garcia
36258945Sroberto *			INRIA - Sophia Antipolis, France
37258945Sroberto *			avega@sophia.inria.fr
38258945Sroberto */
39258945Sroberto
40258945Sroberto/*
41280849Scy *  $Id: if_ep.c,v 1.32 1995/10/26 20:29:37 julian Exp $
42258945Sroberto *
43258945Sroberto *  Promiscuous mode added and interrupt logic slightly changed
44258945Sroberto *  to reduce the number of adapter failures. Transceiver select
45258945Sroberto *  logic changed to use value from EEPROM. Autoconfiguration
46280849Scy *  features added.
47258945Sroberto *  Done by:
48258945Sroberto *          Serge Babkin
49258945Sroberto *          Chelindbank (Chelyabinsk, Russia)
50258945Sroberto *          babkin@hq.icb.chel.su
51258945Sroberto */
52258945Sroberto
53280849Scy#include "ep.h"
54258945Sroberto#if NEP > 0
55258945Sroberto
56258945Sroberto#include "bpfilter.h"
57258945Sroberto
58258945Sroberto#include <sys/param.h>
59258945Sroberto#if defined(__FreeBSD__)
60280849Scy#include <sys/systm.h>
61258945Sroberto#include <sys/kernel.h>
62258945Sroberto#include <sys/devconf.h>
63258945Sroberto#endif
64258945Sroberto#include <sys/mbuf.h>
65258945Sroberto#include <sys/socket.h>
66258945Sroberto#include <sys/ioctl.h>
67280849Scy#include <sys/errno.h>
68258945Sroberto#include <sys/syslog.h>
69280849Scy#if defined(__NetBSD__)
70258945Sroberto#include <sys/select.h>
71258945Sroberto#endif
72258945Sroberto
73258945Sroberto#include <net/if.h>
74280849Scy#include <net/if_dl.h>
75258945Sroberto#include <net/if_types.h>
76280849Scy
77258945Sroberto#ifdef INET
78258945Sroberto#include <netinet/in.h>
79258945Sroberto#include <netinet/in_systm.h>
80258945Sroberto#include <netinet/in_var.h>
81258945Sroberto#include <netinet/ip.h>
82258945Sroberto#include <netinet/if_ether.h>
83258945Sroberto#endif
84258945Sroberto
85258945Sroberto#ifdef IPX
86258945Sroberto#include <netipx/ipx.h>
87258945Sroberto#include <netipx/ipx_if.h>
88258945Sroberto#endif
89258945Sroberto
90258945Sroberto#ifdef NS
91258945Sroberto#include <netns/ns.h>
92258945Sroberto#include <netns/ns_if.h>
93258945Sroberto#endif
94258945Sroberto
95258945Sroberto#if NBPFILTER > 0
96258945Sroberto#include <net/bpf.h>
97258945Sroberto#include <net/bpfdesc.h>
98258945Sroberto#endif
99258945Sroberto
100280849Scy#if defined(__FreeBSD__)
101258945Sroberto#include <machine/clock.h>
102258945Sroberto#endif
103258945Sroberto
104258945Sroberto#include <i386/isa/isa.h>
105258945Sroberto#include <i386/isa/isa_device.h>
106258945Sroberto#include <i386/isa/icu.h>
107258945Sroberto#include <i386/isa/if_epreg.h>
108258945Sroberto
109258945Srobertostatic int epprobe __P((struct isa_device *));
110258945Srobertostatic int epattach __P((struct isa_device *));
111258945Srobertostatic int epioctl __P((struct ifnet * ifp, int, caddr_t));
112258945Srobertostatic void epmbuffill __P((caddr_t, int));
113258945Srobertostatic void epmbufempty __P((struct ep_softc *));
114258945Sroberto
115258945Srobertovoid epinit __P((int));
116258945Srobertovoid epintr __P((int));
117258945Srobertovoid epread __P((struct ep_softc *));
118258945Srobertovoid epreset __P((int));
119258945Srobertovoid epstart __P((struct ifnet *));
120258945Srobertovoid epstop __P((int));
121258945Srobertovoid epwatchdog __P((int));
122258945Sroberto
123258945Srobertostatic int send_ID_sequence __P((int));
124258945Srobertostatic int get_eeprom_data __P((int, int));
125258945Sroberto
126258945Srobertostruct ep_softc ep_softc[NEP];
127258945Sroberto
128258945Sroberto#define ep_ftst(f) (sc->stat&(f))
129258945Sroberto#define ep_fset(f) (sc->stat|=(f))
130258945Sroberto#define ep_frst(f) (sc->stat&=~(f))
131258945Sroberto
132258945Srobertostruct isa_driver epdriver = {
133258945Sroberto    epprobe,
134258945Sroberto    epattach,
135258945Sroberto    "ep",
136258945Sroberto	0
137258945Sroberto};
138258945Sroberto
139258945Srobertostatic struct kern_devconf kdc_ep[NEP] = { {
140258945Sroberto      0, 0, 0,			/* filled in by dev_attach */
141258945Sroberto      "ep", 0, { MDDT_ISA, 0, "net" },
142258945Sroberto      isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
143258945Sroberto      &kdc_isa0,		/* parent */
144258945Sroberto      0,			/* parentdata */
145258945Sroberto      DC_UNCONFIGURED,		/* state */
146258945Sroberto      "3Com 3C509 Ethernet adapter",
147258945Sroberto      DC_CLS_NETIF		/* class */
148258945Sroberto} };
149258945Sroberto
150258945Srobertostatic inline void
151280849Scyep_registerdev(struct isa_device *id)
152280849Scy{
153258945Sroberto      if(id->id_unit)
154258945Sroberto              kdc_ep[id->id_unit] = kdc_ep[0];
155280849Scy      kdc_ep[id->id_unit].kdc_unit = id->id_unit;
156258945Sroberto      kdc_ep[id->id_unit].kdc_parentdata = id;
157258945Sroberto      dev_attach(&kdc_ep[id->id_unit]);
158258945Sroberto}
159258945Sroberto
160258945Srobertoint ep_current_tag = EP_LAST_TAG + 1;
161258945Sroberto
162258945Srobertostruct {
163258945Sroberto	int epb_addr;	/* address of this board */
164280849Scy	char epb_used;	/* was this entry already used for configuring ? */
165258945Sroberto	}
166258945Sroberto	ep_board[EP_MAX_BOARDS + 1];
167258945Sroberto
168258945Srobertostatic int
169258945Srobertoeeprom_rdy(is)
170258945Sroberto    struct isa_device *is;
171258945Sroberto{
172258945Sroberto    int i;
173258945Sroberto
174258945Sroberto    for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
175280849Scy    if (i >= MAX_EEPROMBUSY) {
176280849Scy	printf("ep%d: eeprom failed to come ready.\n", is->id_unit);
177280849Scy	return (0);
178280849Scy    }
179280849Scy    return (1);
180280849Scy}
181280849Scy
182280849Scystatic int
183280849Scyep_look_for_board_at(is)
184280849Scy    struct isa_device *is;
185258945Sroberto{
186280849Scy    int data, i, j, io_base, id_port = EP_ID_PORT;
187258945Sroberto    int nisa = 0, neisa = 0;
188258945Sroberto
189258945Sroberto    if (ep_current_tag == (EP_LAST_TAG + 1)) {
190258945Sroberto	/* Come here just one time */
191258945Sroberto
192258945Sroberto	/* Look for the EISA boards, leave them activated */
193258945Sroberto	for(j = 1; j < 16; j++) {
194258945Sroberto	    io_base = (j * EP_EISA_START) | EP_EISA_W0;
195258945Sroberto	    if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
196258945Sroberto		continue;
197258945Sroberto
198258945Sroberto	    /* we must found 0x1f if the board is EISA configurated */
199258945Sroberto	    if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
200258945Sroberto		continue;
201280849Scy
202258945Sroberto	    /* Reset and Enable the card */
203280849Scy	    outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
204280849Scy	    DELAY(1000); /* we must wait at least 1 ms */
205280849Scy	    outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
206280849Scy
207258945Sroberto	    /*
208258945Sroberto	     * Once activated, all the registers are mapped in the range
209258945Sroberto	     * x000 - x00F, where x is the slot number.
210258945Sroberto             */
211258945Sroberto	    ep_board[neisa].epb_used = 0;
212258945Sroberto	    ep_board[neisa++].epb_addr = j * EP_EISA_START;
213258945Sroberto	}
214258945Sroberto	ep_current_tag--;
215258945Sroberto
216258945Sroberto        /* Look for the ISA boards. Init and leave them actived */
217258945Sroberto	outb(id_port, 0xc0);	/* Global reset */
218258945Sroberto	DELAY(10000);
219258945Sroberto	for (i = 0; i < EP_MAX_BOARDS; i++) {
220258945Sroberto	    outb(id_port, 0);
221258945Sroberto	    outb(id_port, 0);
222258945Sroberto	    send_ID_sequence(id_port);
223258945Sroberto
224258945Sroberto	    data = get_eeprom_data(id_port, EEPROM_MFG_ID);
225258945Sroberto	    if (data != MFG_ID)
226258945Sroberto		break;
227258945Sroberto
228258945Sroberto	    /* resolve contention using the Ethernet address */
229258945Sroberto	    for (j = 0; j < 3; j++)
230258945Sroberto		data = get_eeprom_data(id_port, j);
231258945Sroberto
232258945Sroberto	    ep_board[neisa+nisa].epb_used = 0;
233258945Sroberto	    ep_board[neisa+nisa++].epb_addr =
234258945Sroberto		(get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
235258945Sroberto	    outb(id_port, ep_current_tag);	/* tags board */
236258945Sroberto	    outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
237258945Sroberto	    ep_current_tag--;
238258945Sroberto	}
239258945Sroberto
240258945Sroberto	ep_board[neisa+nisa].epb_addr = 0;
241258945Sroberto	if (neisa) {
242258945Sroberto	    printf("%d 3C5x9 board(s) on EISA found at", neisa);
243258945Sroberto	    for (j = 0; ep_board[j].epb_addr; j++)
244258945Sroberto		if (ep_board[j].epb_addr >= EP_EISA_START)
245258945Sroberto		    printf(" 0x%x", ep_board[j].epb_addr);
246258945Sroberto	    printf("\n");
247258945Sroberto	}
248258945Sroberto	if (nisa) {
249258945Sroberto	    printf("%d 3C5x9 board(s) on ISA found at", nisa);
250258945Sroberto	    for (j = 0; ep_board[j].epb_addr; j++)
251258945Sroberto		if (ep_board[j].epb_addr < EP_EISA_START)
252258945Sroberto		    printf(" 0x%x", ep_board[j].epb_addr);
253258945Sroberto	    printf("\n");
254258945Sroberto	}
255258945Sroberto    }
256280849Scy
257280849Scy    /* we have two cases:
258258945Sroberto     *
259258945Sroberto     *  1. Device was configured with 'port ?'
260258945Sroberto     *      In this case we search for the first unused card in list
261280849Scy     *
262258945Sroberto     *  2. Device was configured with 'port xxx'
263258945Sroberto     *      In this case we search for the unused card with that address
264258945Sroberto     *
265258945Sroberto     */
266258945Sroberto
267258945Sroberto    if(IS_BASE==-1) { /* port? */
268258945Sroberto	for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++);
269258945Sroberto	if(ep_board[i].epb_addr==0)
270258945Sroberto	    return 0;
271280849Scy
272280849Scy	IS_BASE=ep_board[i].epb_addr;
273280849Scy	ep_board[i].epb_used=1;
274280849Scy	return 1;
275258945Sroberto    } else {
276280849Scy	for (i=0; ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE; i++);
277258945Sroberto
278258945Sroberto	if( ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
279258945Sroberto	    return 0;
280258945Sroberto
281258945Sroberto	if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE)
282258945Sroberto	    printf("ep%d: 3c5x9 at 0x%x in test mode. Erase pencil mark!\n",
283258945Sroberto		   is->id_unit, IS_BASE);
284258945Sroberto	ep_board[i].epb_used=1;
285280849Scy	return 1;
286280849Scy    }
287258945Sroberto}
288258945Sroberto
289258945Sroberto/*
290258945Sroberto * get_e: gets a 16 bits word from the EEPROM. we must have set the window
291258945Sroberto * before
292258945Sroberto */
293258945Srobertostatic int
294258945Srobertoget_e(is, offset)
295258945Sroberto    struct isa_device *is;
296258945Sroberto    int offset;
297258945Sroberto{
298258945Sroberto    if (!eeprom_rdy(is))
299258945Sroberto	return (0xffff);
300258945Sroberto    outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
301258945Sroberto    if (!eeprom_rdy(is))
302258945Sroberto	return (0xffff);
303258945Sroberto    return (inw(IS_BASE + EP_W0_EEPROM_DATA));
304258945Sroberto}
305258945Sroberto
306258945Srobertoint
307258945Srobertoepprobe(is)
308258945Sroberto    struct isa_device *is;
309258945Sroberto{
310258945Sroberto    struct ep_softc *sc = &ep_softc[is->id_unit];
311258945Sroberto    u_short k;
312258945Sroberto
313258945Sroberto    ep_registerdev(is);
314258945Sroberto
315258945Sroberto    if (!ep_look_for_board_at(is))
316258945Sroberto	return (0);
317258945Sroberto    /*
318258945Sroberto     * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
319258945Sroberto     * 0x9[0-f]50
320258945Sroberto     */
321258945Sroberto    GO_WINDOW(0);
322258945Sroberto    k = get_e(is, EEPROM_PROD_ID);
323258945Sroberto    if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
324258945Sroberto	printf("epprobe: ignoring model %04x\n", k);
325258945Sroberto	return (0);
326280849Scy    }
327280849Scy
328280849Scy    k = get_e(is, EEPROM_RESOURCE_CFG);
329280849Scy    k >>= 12;
330280849Scy
331280849Scy    /* Now we have two cases again:
332280849Scy     *
333280849Scy     *  1. Device was configured with 'irq?'
334280849Scy     *      In this case we use irq read from the board
335280849Scy     *
336280849Scy     *  2. Device was configured with 'irq xxx'
337280849Scy     *      In this case we set up the board to use specified interrupt
338258945Sroberto     *
339258945Sroberto     */
340258945Sroberto
341258945Sroberto    if(is->id_irq==0) { /* irq? */
342258945Sroberto	is->id_irq= 1 << ( (k==2) ? 9 : k );
343258945Sroberto    }
344258945Sroberto
345258945Sroberto    if (BASE >= EP_EISA_START) /* we have an EISA board, we allow 32 bits access */
346258945Sroberto	sc->stat = F_ACCESS_32_BITS;
347258945Sroberto    else
348258945Sroberto	sc->stat = 0;
349258945Sroberto
350258945Sroberto    /* By now, the adapter is already activated */
351258945Sroberto
352258945Sroberto    return (0x10);		/* 16 bytes of I/O space used. */
353258945Sroberto}
354258945Sroberto
355258945Srobertostatic char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
356258945Sroberto
357258945Srobertostatic int
358258945Srobertoepattach(is)
359258945Sroberto    struct isa_device *is;
360258945Sroberto{
361280849Scy    struct ep_softc *sc = &ep_softc[is->id_unit];
362258945Sroberto    struct ifnet *ifp = &sc->arpcom.ac_if;
363258945Sroberto    u_short i, j, *p;
364258945Sroberto    struct ifaddr *ifa;
365258945Sroberto    struct sockaddr_dl *sdl;
366258945Sroberto    int irq;
367258945Sroberto
368258945Sroberto    /* BASE = IS_BASE; */
369258945Sroberto    sc->ep_io_addr = is->id_iobase;
370258945Sroberto
371258945Sroberto    printf("ep%d: ", is->id_unit);
372258945Sroberto
373258945Sroberto    sc->ep_connectors = 0;
374258945Sroberto    i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
375258945Sroberto    j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
376258945Sroberto    if (i & IS_AUI) {
377258945Sroberto	printf("aui");
378258945Sroberto	sc->ep_connectors |= AUI;
379258945Sroberto    }
380258945Sroberto    if (i & IS_BNC) {
381258945Sroberto	if (sc->ep_connectors)
382258945Sroberto	    printf("/");
383258945Sroberto	printf("bnc");
384258945Sroberto	sc->ep_connectors |= BNC;
385258945Sroberto    }
386258945Sroberto    if (i & IS_UTP) {
387258945Sroberto	if (sc->ep_connectors)
388258945Sroberto	    printf("/");
389258945Sroberto	printf("utp");
390258945Sroberto	sc->ep_connectors |= UTP;
391258945Sroberto    }
392258945Sroberto    if (!(sc->ep_connectors & 7))
393258945Sroberto	printf("no connectors!");
394258945Sroberto    else
395258945Sroberto	printf("[*%s*]", ep_conn_type[j]);
396258945Sroberto
397258945Sroberto    /*
398258945Sroberto     * Read the station address from the eeprom
399258945Sroberto     */
400258945Sroberto    p = (u_short *) & sc->arpcom.ac_enaddr;
401258945Sroberto    for (i = 0; i < 3; i++) {
402258945Sroberto	GO_WINDOW(0);
403258945Sroberto	p[i] = htons(get_e(is, i));
404258945Sroberto	GO_WINDOW(2);
405258945Sroberto	outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
406258945Sroberto    }
407258945Sroberto    printf(" address %s", ether_sprintf(sc->arpcom.ac_enaddr));
408258945Sroberto
409258945Sroberto    /*
410258945Sroberto     * Write IRQ value to board
411258945Sroberto     */
412258945Sroberto
413258945Sroberto    i=is->id_irq;
414280849Scy    if(i==0) {
415258945Sroberto	printf(" irq STRANGE\n");
416258945Sroberto	return 0;
417258945Sroberto	}
418258945Sroberto
419258945Sroberto    for(irq=0; !(i & 1) && irq<16 ; i>>=1, irq++);
420258945Sroberto
421258945Sroberto    if(irq==9)
422258945Sroberto	irq=2;
423258945Sroberto    printf(" irq %d\n",irq);
424258945Sroberto    GO_WINDOW(0);
425280849Scy    outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(irq));
426280849Scy
427280849Scy    ifp->if_unit = is->id_unit;
428280849Scy    ifp->if_name = "ep";
429280849Scy    ifp->if_mtu = ETHERMTU;
430280849Scy    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
431280849Scy    ifp->if_init = epinit;
432280849Scy    ifp->if_output = ether_output;
433280849Scy    ifp->if_start = epstart;
434280849Scy    ifp->if_ioctl = epioctl;
435280849Scy    ifp->if_watchdog = epwatchdog;
436280849Scy	ifp->if_timer=1;
437280849Scy
438280849Scy    if_attach(ifp);
439280849Scy    kdc_ep[is->id_unit].kdc_state = DC_BUSY;
440280849Scy
441280849Scy    /*
442280849Scy     * Fill the hardware address into ifa_addr if we find an AF_LINK entry.
443280849Scy     * We need to do this so bpf's can get the hardware addr of this card.
444280849Scy     * netstat likes this too!
445280849Scy     */
446280849Scy    ifa = ifp->if_addrlist;
447280849Scy    while ((ifa != 0) && (ifa->ifa_addr != 0) &&
448280849Scy	   (ifa->ifa_addr->sa_family != AF_LINK))
449280849Scy	ifa = ifa->ifa_next;
450280849Scy
451280849Scy    if ((ifa != 0) && (ifa->ifa_addr != 0)) {
452280849Scy	sdl = (struct sockaddr_dl *) ifa->ifa_addr;
453280849Scy	sdl->sdl_type = IFT_ETHER;
454280849Scy	sdl->sdl_alen = ETHER_ADDR_LEN;
455280849Scy	sdl->sdl_slen = 0;
456280849Scy	bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
457280849Scy    }
458280849Scy    /* we give some initial parameters */
459280849Scy    sc->rx_avg_pkt = 128;
460280849Scy
461280849Scy    /*
462280849Scy     * NOTE: In all this I multiply everything by 64.
463280849Scy     * W_s = the speed the CPU is able to write to the TX FIFO.
464280849Scy     * T_s = the speed the board sends the info to the Ether.
465280849Scy     * W_s/T_s = 16   (represents 16/64) =>    W_s = 25 % of T_s.
466280849Scy     * This will give us for a packet of 1500 bytes
467280849Scy     * tx_start_thresh=1125 and for a pkt of 64 bytes tx_start_threshold=48.
468280849Scy     * We prefer to start thinking the CPU is much slower than the Ethernet
469280849Scy     * transmission.
470280849Scy     */
471280849Scy    sc->tx_rate = TX_INIT_RATE;
472258945Sroberto    sc->tx_counter = 0;
473258945Sroberto    sc->rx_latency = RX_INIT_LATENCY;
474258945Sroberto    sc->rx_early_thresh = RX_INIT_EARLY_THRESH;
475258945Sroberto#ifdef EP_LOCAL_STATS
476258945Sroberto    sc->rx_no_first = sc->rx_no_mbuf =
477258945Sroberto	sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
478258945Sroberto	sc->tx_underrun = 0;
479258945Sroberto#endif
480258945Sroberto    ep_fset(F_RX_FIRST);
481258945Sroberto    sc->top = sc->mcur = 0;
482258945Sroberto
483258945Sroberto#if NBPFILTER > 0
484258945Sroberto    bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
485258945Sroberto#endif
486258945Sroberto    return 1;
487258945Sroberto}
488258945Sroberto
489258945Sroberto
490258945Sroberto/*
491258945Sroberto * The order in here seems important. Otherwise we may not receive
492258945Sroberto * interrupts. ?!
493258945Sroberto */
494258945Srobertovoid
495258945Srobertoepinit(unit)
496280849Scy    int unit;
497258945Sroberto{
498258945Sroberto    register struct ep_softc *sc = &ep_softc[unit];
499280849Scy    register struct ifnet *ifp = &sc->arpcom.ac_if;
500258945Sroberto    int s, i, j;
501280849Scy
502258945Sroberto	/*
503258945Sroberto    if (ifp->if_addrlist == (struct ifaddr *) 0)
504280849Scy	return;
505280849Scy	*/
506280849Scy
507280849Scy    s = splimp();
508258945Sroberto    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
509258945Sroberto
510258945Sroberto    GO_WINDOW(0);
511258945Sroberto    outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
512258945Sroberto    GO_WINDOW(4);
513258945Sroberto    outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
514258945Sroberto    GO_WINDOW(0);
515258945Sroberto
516258945Sroberto    /* Disable the card */
517258945Sroberto    outw(BASE + EP_W0_CONFIG_CTRL, 0);
518258945Sroberto
519258945Sroberto    /* Enable the card */
520258945Sroberto    outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
521258945Sroberto
522258945Sroberto    GO_WINDOW(2);
523258945Sroberto
524258945Sroberto    /* Reload the ether_addr. */
525258945Sroberto    for (i = 0; i < 6; i++)
526258945Sroberto	outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
527258945Sroberto
528258945Sroberto    outw(BASE + EP_COMMAND, RX_RESET);
529258945Sroberto    outw(BASE + EP_COMMAND, TX_RESET);
530258945Sroberto
531258945Sroberto    /* Window 1 is operating window */
532258945Sroberto    GO_WINDOW(1);
533258945Sroberto    for (i = 0; i < 31; i++)
534258945Sroberto	inb(BASE + EP_W1_TX_STATUS);
535258945Sroberto
536258945Sroberto    /* get rid of stray intr's */
537258945Sroberto    outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
538258945Sroberto
539258945Sroberto    outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
540258945Sroberto
541258945Sroberto    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
542258945Sroberto
543258945Sroberto	if(ifp->if_flags & IFF_PROMISC)
544258945Sroberto		outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
545258945Sroberto		 FIL_GROUP | FIL_BRDCST | FIL_ALL);
546258945Sroberto	else
547258945Sroberto		outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
548258945Sroberto		 FIL_GROUP | FIL_BRDCST);
549258945Sroberto
550258945Sroberto	 /*
551258945Sroberto	  * S.B.
552258945Sroberto	  *
553258945Sroberto	  * Now behavior was slightly changed:
554258945Sroberto	  *
555258945Sroberto	  * if any of flags link[0-2] is used and its connector is
556258945Sroberto	  * physically present the following connectors are used:
557258945Sroberto	  *
558258945Sroberto	  *   link0 - AUI * highest precedence
559258945Sroberto	  *   link1 - BNC
560258945Sroberto	  *   link2 - UTP * lowest precedence
561258945Sroberto	  *
562258945Sroberto	  * If none of them is specified then
563258945Sroberto	  * connector specified in the EEPROM is used
564258945Sroberto	  * (if present on card or AUI if not).
565258945Sroberto	  *
566258945Sroberto	  */
567258945Sroberto
568258945Sroberto    if(ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) {
569258945Sroberto	/* nothing */
570258945Sroberto    } else if(ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) {
571258945Sroberto	outw(BASE + EP_COMMAND, START_TRANSCEIVER);
572258945Sroberto	DELAY(1000);
573258945Sroberto    } else if(ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) {
574258945Sroberto	GO_WINDOW(4);
575258945Sroberto	outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
576258945Sroberto	GO_WINDOW(1);
577280849Scy    } else {
578258945Sroberto	GO_WINDOW(0);
579258945Sroberto	j = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
580258945Sroberto	GO_WINDOW(1);
581258945Sroberto	switch(j) {
582258945Sroberto	    case ACF_CONNECTOR_UTP:
583258945Sroberto		if(sc->ep_connectors & UTP) {
584258945Sroberto		    GO_WINDOW(4);
585258945Sroberto		    outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
586258945Sroberto		    GO_WINDOW(1);
587258945Sroberto		}
588258945Sroberto		break;
589258945Sroberto	    case ACF_CONNECTOR_BNC:
590258945Sroberto		if(sc->ep_connectors & BNC) {
591258945Sroberto		    outw(BASE + EP_COMMAND, START_TRANSCEIVER);
592258945Sroberto		    DELAY(1000);
593258945Sroberto		}
594258945Sroberto		break;
595258945Sroberto	    case ACF_CONNECTOR_AUI:
596258945Sroberto		/* nothing to do */
597258945Sroberto		break;
598258945Sroberto	    default:
599258945Sroberto		printf("ep%d: strange connector type in EEPROM: assuming AUI\n",
600258945Sroberto		    unit);
601258945Sroberto		break;
602258945Sroberto	}
603280849Scy    }
604258945Sroberto
605258945Sroberto    outw(BASE + EP_COMMAND, RX_ENABLE);
606280849Scy    outw(BASE + EP_COMMAND, TX_ENABLE);
607280849Scy
608258945Sroberto    ifp->if_flags |= IFF_RUNNING;
609258945Sroberto    ifp->if_flags &= ~IFF_OACTIVE;	/* just in case */
610258945Sroberto
611258945Sroberto    sc->tx_rate = TX_INIT_RATE;
612258945Sroberto    sc->tx_counter = 0;
613258945Sroberto    sc->rx_latency = RX_INIT_LATENCY;
614258945Sroberto    sc->rx_early_thresh = RX_INIT_EARLY_THRESH;
615258945Sroberto#ifdef EP_LOCAL_STATS
616258945Sroberto    sc->rx_no_first = sc->rx_no_mbuf =
617258945Sroberto	sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
618258945Sroberto	sc->tx_underrun = 0;
619258945Sroberto#endif
620258945Sroberto    ep_fset(F_RX_FIRST);
621258945Sroberto    ep_frst(F_RX_TRAILER);
622258945Sroberto    if (sc->top) {
623258945Sroberto	m_freem(sc->top);
624258945Sroberto	sc->top = sc->mcur = 0;
625258945Sroberto    }
626258945Sroberto    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | sc->rx_early_thresh);
627258945Sroberto
628258945Sroberto    /*
629280849Scy     * These clever computations look very interesting
630280849Scy     * but the fixed threshold gives near no output errors
631280849Scy     * and if it as low as 16 bytes it gives the max. throughput.
632280849Scy     * We think that processor is anyway quicker than Ethernet
633280849Scy	 * (and this should be true for any 386 and higher)
634258945Sroberto     */
635258945Sroberto
636258945Sroberto    outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
637258945Sroberto
638258945Sroberto    /*
639258945Sroberto     * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up
640258945Sroberto     * any that we had in case we're being called from intr or somewhere
641258945Sroberto     * else.
642258945Sroberto     */
643258945Sroberto    sc->last_mb = 0;
644258945Sroberto    sc->next_mb = 0;
645258945Sroberto    epmbuffill((caddr_t) sc, 0);
646258945Sroberto
647258945Sroberto    epstart(ifp);
648258945Sroberto
649258945Sroberto    splx(s);
650258945Sroberto}
651258945Sroberto
652258945Srobertostatic const char padmap[] = {0, 3, 2, 1};
653258945Sroberto
654258945Srobertovoid
655258945Srobertoepstart(ifp)
656258945Sroberto    struct ifnet *ifp;
657258945Sroberto{
658258945Sroberto    register struct ep_softc *sc = &ep_softc[ifp->if_unit];
659258945Sroberto    register u_int len;
660258945Sroberto    register struct mbuf *m;
661258945Sroberto    struct mbuf *top;
662258945Sroberto    int s, pad;
663258945Sroberto
664258945Sroberto    s = splimp();
665258945Sroberto    if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
666258945Sroberto	splx(s);
667258945Sroberto	return;
668258945Sroberto    }
669258945Srobertostartagain:
670280849Scy    /* Sneak a peek at the next packet */
671280849Scy    m = sc->arpcom.ac_if.if_snd.ifq_head;
672258945Sroberto    if (m == 0) {
673258945Sroberto	splx(s);
674280849Scy	return;
675280849Scy    }
676258945Sroberto#if 0
677258945Sroberto    len = m->m_pkthdr.len;
678258945Sroberto#else
679258945Sroberto    for (len = 0, top = m; m; m = m->m_next)
680258945Sroberto	len += m->m_len;
681258945Sroberto#endif
682258945Sroberto
683258945Sroberto    pad = padmap[len & 3];
684258945Sroberto
685258945Sroberto    /*
686258945Sroberto     * The 3c509 automatically pads short packets to minimum ethernet length,
687258945Sroberto     * but we drop packets that are too large. Perhaps we should truncate
688258945Sroberto     * them instead?
689280849Scy     */
690280849Scy    if (len + pad > ETHER_MAX_LEN) {
691258945Sroberto	/* packet is obviously too large: toss it */
692258945Sroberto	++sc->arpcom.ac_if.if_oerrors;
693280849Scy	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
694280849Scy	m_freem(m);
695258945Sroberto	goto readcheck;
696258945Sroberto    }
697258945Sroberto    if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
698258945Sroberto	/* no room in FIFO */
699258945Sroberto	outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
700258945Sroberto	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
701258945Sroberto	splx(s);
702258945Sroberto	return;
703258945Sroberto    }
704258945Sroberto    IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
705258945Sroberto
706258945Sroberto    outw(BASE + EP_W1_TX_PIO_WR_1, len);
707258945Sroberto    outw(BASE + EP_W1_TX_PIO_WR_1, 0x0);	/* Second dword meaningless */
708258945Sroberto
709258945Sroberto    /* compute the Tx start threshold for this packet */
710280849Scy    sc->tx_start_thresh = len =
711280849Scy	(((len * (64 - sc->tx_rate)) >> 6) & ~3) + 16;
712258945Sroberto#if 0
713258945Sroberto    /*
714258945Sroberto     * The following string does something strange with the card and
715258945Sroberto     * we get a lot of output errors due to it so it's commented out
716258945Sroberto     * and we use fixed threshold (see above)
717258945Sroberto     */
718258945Sroberto
719258945Sroberto    outw(BASE + EP_COMMAND, SET_TX_START_THRESH | len);
720258945Sroberto#endif
721258945Sroberto
722258945Sroberto    for (top = m; m != 0; m = m->m_next)
723280849Scy	if(ep_ftst(F_ACCESS_32_BITS)) {
724258945Sroberto	    outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
725258945Sroberto		  m->m_len / 4);
726280849Scy	    if (m->m_len & 3)
727280849Scy		outsb(BASE + EP_W1_TX_PIO_WR_1,
728280849Scy		      mtod(m, caddr_t) + m->m_len / 4,
729280849Scy		      m->m_len & 3);
730280849Scy	} else {
731280849Scy	    outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
732280849Scy	    if (m->m_len & 1)
733280849Scy		outb(BASE + EP_W1_TX_PIO_WR_1,
734258945Sroberto		     *(mtod(m, caddr_t) + m->m_len - 1));
735258945Sroberto	}
736258945Sroberto
737258945Sroberto    while (pad--)
738258945Sroberto	outb(BASE + EP_W1_TX_PIO_WR_1, 0);	/* Padding */
739258945Sroberto
740280849Scy#if NBPFILTER > 0
741258945Sroberto    if (sc->bpf) {
742258945Sroberto	bpf_mtap(sc->bpf, top);
743258945Sroberto    }
744258945Sroberto#endif
745280849Scy
746280849Scy    sc->arpcom.ac_if.if_opackets++;
747280849Scy    m_freem(top);
748280849Scy    /*
749280849Scy     * Every 1024*4 packets we increment the tx_rate if we haven't had
750280849Scy     * errors, that in the case it has abnormaly goten too low
751258945Sroberto     */
752258945Sroberto    if (!(++sc->tx_counter & (1024 * 4 - 1)) &&
753258945Sroberto	sc->tx_rate < TX_INIT_MAX_RATE)
754	sc->tx_rate++;
755
756    /*
757     * Is another packet coming in? We don't want to overflow the tiny RX
758     * fifo.
759     */
760readcheck:
761    if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
762	/*
763	 * we check if we have packets left, in that case we prepare to come
764	 * back later
765	 */
766	if (sc->arpcom.ac_if.if_snd.ifq_head) {
767	    outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH |
768		 sc->tx_start_thresh);
769	}
770	splx(s);
771	return;
772    }
773    goto startagain;
774}
775
776void
777epintr(unit)
778    int unit;
779{
780    register int status;
781    register struct ep_softc *sc = &ep_softc[unit];
782    int x;
783
784    x=splbio();
785
786    outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */
787
788rescan:
789
790    while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {
791
792	/* first acknowledge all interrupt sources */
793	outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));
794
795	if (status & (S_RX_COMPLETE | S_RX_EARLY)) {
796	    epread(sc);
797	    continue;
798	}
799	if (status & S_TX_AVAIL) {
800	    /* we need ACK */
801	    sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
802	    GO_WINDOW(1);
803	    inw(BASE + EP_W1_FREE_TX);
804	    epstart(&sc->arpcom.ac_if);
805	}
806	if (status & S_CARD_FAILURE) {
807#ifdef EP_LOCAL_STATS
808	    printf("\nep%d:\n\tStatus: %x\n", unit, status);
809	    GO_WINDOW(4);
810	    printf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
811	    printf("\tStat: %x\n", sc->stat);
812	    printf("\tIpackets=%d, Opackets=%d\n",
813		sc->arpcom.ac_if.if_ipackets, sc->arpcom.ac_if.if_opackets);
814	    printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
815		   sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf,
816		   sc->rx_overrunl, sc->tx_underrun);
817#else
818	    printf("ep%d: Status: %x\n", unit, status);
819#endif
820	    epinit(unit);
821	    splx(x);
822	    return;
823	}
824	if (status & S_TX_COMPLETE) {
825	    /* we  need ACK. we do it at the end */
826	    /*
827	     * We need to read TX_STATUS until we get a 0 status in order to
828	     * turn off the interrupt flag.
829	     */
830	    while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
831		if (status & TXS_SUCCES_INTR_REQ);
832		else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
833		    outw(BASE + EP_COMMAND, TX_RESET);
834		    if (status & TXS_UNDERRUN) {
835			if (sc->tx_rate > 1) {
836			    sc->tx_rate--;	/* Actually in steps of 1/64 */
837			    sc->tx_counter = 0;	/* We reset it */
838			}
839#ifdef EP_LOCAL_STATS
840			sc->tx_underrun++;
841#endif
842		    } else {
843			if (status & TXS_JABBER);
844			else	/* TXS_MAX_COLLISION - we shouldn't get here */
845			    ++sc->arpcom.ac_if.if_collisions;
846		    }
847		    ++sc->arpcom.ac_if.if_oerrors;
848		    outw(BASE + EP_COMMAND, TX_ENABLE);
849		    /*
850		     * To have a tx_avail_int but giving the chance to the
851		     * Reception
852		     */
853		    if (sc->arpcom.ac_if.if_snd.ifq_head) {
854			outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
855		    }
856		}
857		outb(BASE + EP_W1_TX_STATUS, 0x0);	/* pops up the next
858							 * status */
859	    }			/* while */
860	    sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
861	    GO_WINDOW(1);
862	    inw(BASE + EP_W1_FREE_TX);
863	    epstart(&sc->arpcom.ac_if);
864	}			/* end TX_COMPLETE */
865    }
866
867    outw(BASE + EP_COMMAND, C_INTR_LATCH);	/* ACK int Latch */
868
869    if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
870	goto rescan;
871
872    /* re-enable Ints */
873    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
874
875    splx(x);
876}
877
878void
879epread(sc)
880    register struct ep_softc *sc;
881{
882    struct ether_header *eh;
883    struct mbuf *top, *mcur, *m;
884    int lenthisone;
885
886    short rx_fifo2, status;
887    register short delta;
888    register short rx_fifo;
889
890    status = inw(BASE + EP_W1_RX_STATUS);
891
892read_again:
893
894    if (status & ERR_RX) {
895	++sc->arpcom.ac_if.if_ierrors;
896	if (status & ERR_RX_OVERRUN) {
897	    /*
898	     * we can think the rx latency is actually greather than we
899	     * expect
900	     */
901#ifdef EP_LOCAL_STATS
902	    if (ep_ftst(F_RX_FIRST))
903		sc->rx_overrunf++;
904	    else
905		sc->rx_overrunl++;
906#endif
907	    if (sc->rx_latency < ETHERMTU)
908		sc->rx_latency += 16;
909	}
910	goto out;
911    }
912    rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;
913
914    if (ep_ftst(F_RX_FIRST)) {
915	if (m = sc->mb[sc->next_mb]) {
916	    sc->mb[sc->next_mb] = 0;
917	    sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
918	    m->m_data = m->m_pktdat;
919	    m->m_flags = M_PKTHDR;
920	} else {
921	    MGETHDR(m, M_DONTWAIT, MT_DATA);
922	    if (!m)
923		goto out;
924	}
925	sc->top = sc->mcur = top = m;
926#define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
927#define EOFF    (EROUND - sizeof(struct ether_header))
928	top->m_data += EOFF;
929
930	/* Read what should be the header. */
931	insw(BASE + EP_W1_RX_PIO_RD_1,
932	     mtod(top, caddr_t), sizeof(struct ether_header) / 2);
933	top->m_len = sizeof(struct ether_header);
934	rx_fifo -= sizeof(struct ether_header);
935	sc->cur_len = rx_fifo2;
936    } else {
937	/* come here if we didn't have a complete packet last time */
938	top = sc->top;
939	m = sc->mcur;
940	sc->cur_len += rx_fifo2;
941	if (ep_ftst(F_RX_TRAILER))
942	    /* We don't read the trailer */
943	    rx_fifo -= sizeof(struct ether_header);
944    }
945
946    /* Reads what is left in the RX FIFO */
947    while (rx_fifo > 0) {
948	lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
949	if (lenthisone == 0) {	/* no room in this one */
950	    mcur = m;
951	    if (m = sc->mb[sc->next_mb]) {
952		sc->mb[sc->next_mb] = 0;
953		sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
954	    } else {
955		MGET(m, M_DONTWAIT, MT_DATA);
956		if (!m)
957		    goto out;
958	    }
959
960	    if (rx_fifo >= MINCLSIZE)
961		MCLGET(m, M_DONTWAIT);
962	    m->m_len = 0;
963	    mcur->m_next = m;
964	    lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
965	}
966	if (ep_ftst(F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
967	    insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
968		 lenthisone / 4);
969	    m->m_len += (lenthisone & ~3);
970	    if (lenthisone & 3)
971		insb(BASE + EP_W1_RX_PIO_RD_1,
972		     mtod(m, caddr_t) + m->m_len,
973		     lenthisone & 3);
974	    m->m_len += (lenthisone & 3);
975	} else {
976	    insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
977		 lenthisone / 2);
978	    m->m_len += lenthisone;
979	    if (lenthisone & 1)
980		*(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
981	}
982	rx_fifo -= lenthisone;
983    }
984
985    if (ep_ftst(F_RX_TRAILER)) {/* reads the trailer */
986	if (m = sc->mb[sc->next_mb]) {
987	    sc->mb[sc->next_mb] = 0;
988	    sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
989	    m->m_data = m->m_pktdat;
990	    m->m_flags = M_PKTHDR;
991	} else {
992	    MGETHDR(m, M_DONTWAIT, MT_DATA);
993	    if (!m)
994		goto out;
995	}
996	insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t),
997	     sizeof(struct ether_header));
998	m->m_len = sizeof(struct ether_header);
999	m->m_next = top;
1000	sc->top = top = m;
1001	/* XXX Accomodate for type and len from beginning of trailer */
1002	sc->cur_len -= (2 * sizeof(u_short));
1003	ep_frst(F_RX_TRAILER);
1004	goto all_pkt;
1005    }
1006
1007    if (status & ERR_RX_INCOMPLETE) {	/* we haven't received the complete
1008					 * packet */
1009	sc->mcur = m;
1010#ifdef EP_LOCAL_STATS
1011	sc->rx_no_first++;	/* to know how often we come here */
1012#endif
1013	/*
1014	 * Re-compute rx_latency, the factor used is 1/4 to go up and 1/32 to
1015	 * go down
1016	 */
1017	delta = rx_fifo2 - sc->rx_early_thresh;	/* last latency seen LLS */
1018	delta -= sc->rx_latency;/* LLS - estimated_latency */
1019	if (delta >= 0)
1020	    sc->rx_latency += (delta / 4);
1021	else
1022	    sc->rx_latency += (delta / 32);
1023	ep_frst(F_RX_FIRST);
1024	if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
1025	    /* we see if by now, the packet has completly arrived */
1026	    goto read_again;
1027	}
1028	/* compute rx_early_threshold */
1029	delta = (sc->rx_avg_pkt - sc->cur_len - sc->rx_latency - 16) & ~3;
1030	if (delta < MIN_RX_EARLY_THRESHL)
1031	    delta = MIN_RX_EARLY_THRESHL;
1032
1033	outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH |
1034	     (sc->rx_early_thresh = delta));
1035	return;
1036    }
1037all_pkt:
1038    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1039    /*
1040     * recompute average packet's length, the factor used is 1/8 to go down
1041     * and 1/32 to go up
1042     */
1043    delta = sc->cur_len - sc->rx_avg_pkt;
1044    if (delta > 0)
1045	sc->rx_avg_pkt += (delta / 32);
1046    else
1047	sc->rx_avg_pkt += (delta / 8);
1048    delta = (sc->rx_avg_pkt - sc->rx_latency - 16) & ~3;
1049    if (delta < MIN_RX_EARLY_THRESHF)
1050	delta = MIN_RX_EARLY_THRESHF;
1051    sc->rx_early_thresh = delta;
1052    ++sc->arpcom.ac_if.if_ipackets;
1053    ep_fset(F_RX_FIRST);
1054    ep_frst(F_RX_TRAILER);
1055    top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1056    top->m_pkthdr.len = sc->cur_len;
1057
1058#if NBPFILTER > 0
1059    if (sc->bpf) {
1060	bpf_mtap(sc->bpf, top);
1061
1062	/*
1063	 * Note that the interface cannot be in promiscuous mode if there are
1064	 * no BPF listeners.  And if we are in promiscuous mode, we have to
1065	 * check if this packet is really ours.
1066	 */
1067	eh = mtod(top, struct ether_header *);
1068	if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
1069	    (eh->ether_dhost[0] & 1) == 0 &&
1070	    bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
1071		 sizeof(eh->ether_dhost)) != 0 &&
1072	    bcmp(eh->ether_dhost, etherbroadcastaddr,
1073		 sizeof(eh->ether_dhost)) != 0) {
1074	    if (sc->top) {
1075		m_freem(sc->top);
1076		sc->top = 0;
1077	    }
1078	    ep_fset(F_RX_FIRST);
1079	    ep_frst(F_RX_TRAILER);
1080#ifdef EP_LOCAL_STATS
1081	    sc->rx_bpf_disc++;
1082#endif
1083	    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1084	    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | delta);
1085	    return;
1086	}
1087    }
1088#endif
1089
1090    eh = mtod(top, struct ether_header *);
1091    m_adj(top, sizeof(struct ether_header));
1092    ether_input(&sc->arpcom.ac_if, eh, top);
1093    if (!sc->mb[sc->next_mb])
1094	epmbuffill((caddr_t) sc, 0);
1095    sc->top = 0;
1096    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1097    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | delta);
1098    return;
1099
1100out:
1101    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1102    if (sc->top) {
1103	m_freem(sc->top);
1104	sc->top = 0;
1105#ifdef EP_LOCAL_STATS
1106	sc->rx_no_mbuf++;
1107#endif
1108    }
1109    delta = (sc->rx_avg_pkt - sc->rx_latency - 16) & ~3;
1110    if (delta < MIN_RX_EARLY_THRESHF)
1111	delta = MIN_RX_EARLY_THRESHF;
1112    ep_fset(F_RX_FIRST);
1113    ep_frst(F_RX_TRAILER);
1114    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1115    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH |
1116	 (sc->rx_early_thresh = delta));
1117}
1118
1119/*
1120 * Look familiar?
1121 */
1122static int
1123epioctl(ifp, cmd, data)
1124    register struct ifnet *ifp;
1125    int cmd;
1126    caddr_t data;
1127{
1128    register struct ifaddr *ifa = (struct ifaddr *) data;
1129    struct ep_softc *sc = &ep_softc[ifp->if_unit];
1130    struct ifreq *ifr = (struct ifreq *) data;
1131    int s, error = 0;
1132
1133    s = splimp();
1134
1135    switch (cmd) {
1136      case SIOCSIFADDR:
1137	ifp->if_flags |= IFF_UP;
1138	switch (ifa->ifa_addr->sa_family) {
1139#ifdef INET
1140	  case AF_INET:
1141	    epinit(ifp->if_unit);	/* before arpwhohas */
1142	    arp_ifinit((struct arpcom *)ifp, ifa);
1143	    break;
1144#endif
1145#ifdef IPX
1146	  case AF_IPX:
1147	    {
1148		register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
1149
1150		if (ipx_nullhost(*ina))
1151		    ina->x_host =
1152			*(union ipx_host *) (sc->arpcom.ac_enaddr);
1153		else {
1154		    ifp->if_flags &= ~IFF_RUNNING;
1155		    bcopy((caddr_t) ina->x_host.c_host,
1156			  (caddr_t) sc->arpcom.ac_enaddr,
1157			  sizeof(sc->arpcom.ac_enaddr));
1158		}
1159		epinit(ifp->if_unit);
1160		break;
1161	    }
1162#endif
1163#ifdef NS
1164	  case AF_NS:
1165	    {
1166		register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1167
1168		if (ns_nullhost(*ina))
1169		    ina->x_host =
1170			*(union ns_host *) (sc->arpcom.ac_enaddr);
1171		else {
1172		    ifp->if_flags &= ~IFF_RUNNING;
1173		    bcopy((caddr_t) ina->x_host.c_host,
1174			  (caddr_t) sc->arpcom.ac_enaddr,
1175			  sizeof(sc->arpcom.ac_enaddr));
1176		}
1177		epinit(ifp->if_unit);
1178		break;
1179	    }
1180#endif
1181	  default:
1182	    epinit(ifp->if_unit);
1183	    break;
1184	}
1185	break;
1186      case SIOCGIFADDR:
1187	{
1188	  struct sockaddr *sa;
1189
1190	  sa = (struct sockaddr *) & ifr->ifr_data;
1191	  bcopy((caddr_t) sc->arpcom.ac_enaddr,
1192		(caddr_t) sa->sa_data, ETHER_ADDR_LEN);
1193	}
1194	break;
1195      case SIOCSIFFLAGS:
1196	if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1197	    ifp->if_flags &= ~IFF_RUNNING;
1198	    epstop(ifp->if_unit);
1199	    epmbufempty(sc);
1200	    break;
1201	} else {
1202	    /* reinitialize card on any parameter change */
1203	    epinit(ifp->if_unit);
1204	    break;
1205	}
1206
1207	/* NOTREACHED */
1208
1209	if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0)
1210	    epinit(ifp->if_unit);
1211
1212	if ( (ifp->if_flags & IFF_PROMISC) &&  !ep_ftst(F_PROMISC) ) {
1213	    ep_fset(F_PROMISC);
1214	    epinit(ifp->if_unit);
1215	    }
1216	else if( !(ifp->if_flags & IFF_PROMISC) && ep_ftst(F_PROMISC) ) {
1217	    ep_frst(F_PROMISC);
1218	    epinit(ifp->if_unit);
1219	    }
1220
1221	break;
1222#ifdef notdef
1223      case SIOCGHWADDR:
1224	bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
1225	      sizeof(sc->sc_addr));
1226	break;
1227#endif
1228	case SIOCSIFMTU:
1229
1230		/*
1231		 * Set the interface MTU.
1232		 */
1233		if (ifr->ifr_mtu > ETHERMTU) {
1234			error = EINVAL;
1235		} else {
1236			ifp->if_mtu = ifr->ifr_mtu;
1237		}
1238		break;
1239
1240      default:
1241		error = EINVAL;
1242    }
1243
1244    splx(s);
1245
1246    return (error);
1247}
1248
1249void
1250epreset(unit)
1251    int unit;
1252{
1253    int s = splimp();
1254
1255    epstop(unit);
1256    epinit(unit);
1257    splx(s);
1258}
1259
1260void
1261epwatchdog(unit)
1262    int unit;
1263{
1264    struct ep_softc *sc = &ep_softc[unit];
1265    struct ifnet *ifp=&sc->arpcom.ac_if;
1266
1267    /*
1268    printf("ep: watchdog\n");
1269
1270    log(LOG_ERR, "ep%d: watchdog\n", unit);
1271    ++sc->arpcom.ac_if.if_oerrors;
1272    */
1273
1274    /* epreset(unit); */
1275    ifp->if_flags &= ~IFF_OACTIVE;
1276    epstart(ifp);
1277    epintr(unit);
1278
1279    ifp->if_timer=1;
1280}
1281
1282void
1283epstop(unit)
1284    int unit;
1285{
1286    struct ep_softc *sc = &ep_softc[unit];
1287
1288    outw(BASE + EP_COMMAND, RX_DISABLE);
1289    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1290    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1291    outw(BASE + EP_COMMAND, TX_DISABLE);
1292    outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
1293    outw(BASE + EP_COMMAND, RX_RESET);
1294    outw(BASE + EP_COMMAND, TX_RESET);
1295    outw(BASE + EP_COMMAND, C_INTR_LATCH);
1296    outw(BASE + EP_COMMAND, SET_RD_0_MASK);
1297    outw(BASE + EP_COMMAND, SET_INTR_MASK);
1298    outw(BASE + EP_COMMAND, SET_RX_FILTER);
1299}
1300
1301
1302static int
1303send_ID_sequence(port)
1304    int port;
1305{
1306    int cx, al;
1307
1308    for (al = 0xff, cx = 0; cx < 255; cx++) {
1309	outb(port, al);
1310	al <<= 1;
1311	if (al & 0x100)
1312	    al ^= 0xcf;
1313    }
1314    return (1);
1315}
1316
1317
1318/*
1319 * We get eeprom data from the id_port given an offset into the eeprom.
1320 * Basically; after the ID_sequence is sent to all of the cards; they enter
1321 * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
1322 * the eeprom data.  We then read the port 16 times and with every read; the
1323 * cards check for contention (ie: if one card writes a 0 bit and another
1324 * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
1325 * compares the data on the bus; if there is a difference then that card goes
1326 * into ID_WAIT state again). In the meantime; one bit of data is returned in
1327 * the AX register which is conveniently returned to us by inb().  Hence; we
1328 * read 16 times getting one bit of data with each read.
1329 */
1330static int
1331get_eeprom_data(id_port, offset)
1332    int id_port;
1333    int offset;
1334{
1335    int i, data = 0;
1336    outb(id_port, 0x80 + offset);
1337    DELAY(1000);
1338    for (i = 0; i < 16; i++)
1339	data = (data << 1) | (inw(id_port) & 1);
1340    return (data);
1341}
1342
1343/*
1344 * We suppose this is always called inside a splimp(){...}splx() region
1345 */
1346static void
1347epmbuffill(sp, dummy_arg)
1348    caddr_t sp;
1349    int dummy_arg;
1350{
1351    struct ep_softc *sc = (struct ep_softc *) sp;
1352    int i;
1353
1354    i = sc->last_mb;
1355    do {
1356	if (sc->mb[i] == NULL)
1357	    MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1358	if (sc->mb[i] == NULL)
1359	    break;
1360	i = (i + 1) % MAX_MBS;
1361    } while (i != sc->next_mb);
1362    sc->last_mb = i;
1363}
1364
1365static void
1366epmbufempty(sc)
1367    struct ep_softc *sc;
1368{
1369    int s, i;
1370
1371    s = splimp();
1372    for (i = 0; i < MAX_MBS; i++) {
1373	if (sc->mb[i]) {
1374	    m_freem(sc->mb[i]);
1375	    sc->mb[i] = NULL;
1376	}
1377    }
1378    sc->last_mb = sc->next_mb = 0;
1379    splx(s);
1380}
1381
1382#endif				/* NEP > 0 */
1383