if_ep.c revision 13638
1294491Sdelphij/*
2294491Sdelphij * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
3294491Sdelphij * All rights reserved.
4294491Sdelphij *
5294491Sdelphij * Redistribution and use in source and binary forms, with or without
6294491Sdelphij * modification, are permitted provided that the following conditions
7294491Sdelphij * are met:
8294491Sdelphij * 1. Redistributions of source code must retain the above copyright
9294491Sdelphij *    notice, this list of conditions and the following disclaimer.
10294491Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
11294491Sdelphij *    notice, this list of conditions and the following disclaimer in the
12294491Sdelphij *    documentation and/or other materials provided with the distribution.
13294491Sdelphij * 3. All advertising materials mentioning features or use of this software
14294491Sdelphij *    must display the following acknowledgement:
15294491Sdelphij *      This product includes software developed by Herb Peyerl.
16294491Sdelphij * 4. The name of Herb Peyerl may not be used to endorse or promote products
17294491Sdelphij *    derived from this software without specific prior written permission.
18294491Sdelphij *
19294491Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20294491Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21294491Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22294491Sdelphij * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23294491Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24294491Sdelphij * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25294491Sdelphij * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26294491Sdelphij * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27294491Sdelphij * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28294491Sdelphij * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29294491Sdelphij *
30294491Sdelphij *	if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp
31294491Sdelphij */
32294491Sdelphij
33294491Sdelphij/*
34294491Sdelphij *	Modified from the FreeBSD 1.1.5.1 version by:
35294491Sdelphij *		 	Andres Vega Garcia
36294491Sdelphij *			INRIA - Sophia Antipolis, France
37294491Sdelphij *			avega@sophia.inria.fr
38294491Sdelphij */
39294491Sdelphij
40294491Sdelphij/*
41294491Sdelphij *  $Id: if_ep.c,v 1.37 1995/12/15 00:54:11 bde Exp $
42294491Sdelphij *
43294491Sdelphij *  Promiscuous mode added and interrupt logic slightly changed
44294491Sdelphij *  to reduce the number of adapter failures. Transceiver select
45294491Sdelphij *  logic changed to use value from EEPROM. Autoconfiguration
46294491Sdelphij *  features added.
47294491Sdelphij *  Done by:
48294491Sdelphij *          Serge Babkin
49294491Sdelphij *          Chelindbank (Chelyabinsk, Russia)
50294491Sdelphij *          babkin@hq.icb.chel.su
51294491Sdelphij */
52294491Sdelphij
53294491Sdelphij#include "ep.h"
54294491Sdelphij#if NEP > 0
55294491Sdelphij
56294491Sdelphij#include "bpfilter.h"
57294491Sdelphij
58294491Sdelphij#include <sys/param.h>
59294491Sdelphij#if defined(__FreeBSD__)
60294491Sdelphij#include <sys/systm.h>
61294491Sdelphij#include <sys/kernel.h>
62294491Sdelphij#include <sys/conf.h>
63294491Sdelphij#include <sys/devconf.h>
64294491Sdelphij#endif
65294491Sdelphij#include <sys/mbuf.h>
66294491Sdelphij#include <sys/socket.h>
67294491Sdelphij#include <sys/ioctl.h>
68294491Sdelphij#include <sys/errno.h>
69294491Sdelphij#include <sys/syslog.h>
70294491Sdelphij#if defined(__NetBSD__)
71294491Sdelphij#include <sys/select.h>
72294491Sdelphij#endif
73294491Sdelphij
74294491Sdelphij#include <net/if.h>
75294491Sdelphij#include <net/if_dl.h>
76294491Sdelphij#include <net/if_types.h>
77294491Sdelphij
78294491Sdelphij#ifdef INET
79294491Sdelphij#include <netinet/in.h>
80294491Sdelphij#include <netinet/in_systm.h>
81294491Sdelphij#include <netinet/in_var.h>
82294491Sdelphij#include <netinet/ip.h>
83294491Sdelphij#include <netinet/if_ether.h>
84294491Sdelphij#endif
85294491Sdelphij
86294491Sdelphij#ifdef IPX
87294491Sdelphij#include <netipx/ipx.h>
88294491Sdelphij#include <netipx/ipx_if.h>
89294491Sdelphij#endif
90
91#ifdef NS
92#include <netns/ns.h>
93#include <netns/ns_if.h>
94#endif
95
96#if NBPFILTER > 0
97#include <net/bpf.h>
98#include <net/bpfdesc.h>
99#endif
100
101#if defined(__FreeBSD__)
102#include <machine/clock.h>
103#endif
104
105#include <i386/isa/isa.h>
106#include <i386/isa/isa_device.h>
107#include <i386/isa/icu.h>
108#include <i386/isa/if_epreg.h>
109
110static int eeprom_rdy __P((struct isa_device *is));
111static int ep_look_for_board_at __P((struct isa_device *is));
112static int get_e __P((struct isa_device *is, int offset));
113
114static int epprobe __P((struct isa_device *));
115static int epattach __P((struct isa_device *));
116static int epioctl __P((struct ifnet * ifp, int, caddr_t));
117static void epmbuffill __P((caddr_t, int));
118static void epmbufempty __P((struct ep_softc *));
119
120static void epinit __P((int));
121static void epread __P((struct ep_softc *));
122void epreset __P((int));
123static void epstart __P((struct ifnet *));
124static void epstop __P((int));
125static void epwatchdog __P((struct ifnet *));
126
127static int send_ID_sequence __P((int));
128static int get_eeprom_data __P((int, int));
129
130static struct ep_softc ep_softc[NEP];
131
132#define ep_ftst(f) (sc->stat&(f))
133#define ep_fset(f) (sc->stat|=(f))
134#define ep_frst(f) (sc->stat&=~(f))
135
136struct isa_driver epdriver = {
137    epprobe,
138    epattach,
139    "ep",
140	0
141};
142
143static struct kern_devconf kdc_ep[NEP] = { {
144      0, 0, 0,			/* filled in by dev_attach */
145      "ep", 0, { MDDT_ISA, 0, "net" },
146      isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
147      &kdc_isa0,		/* parent */
148      0,			/* parentdata */
149      DC_UNCONFIGURED,		/* state */
150      "3Com 3C509 Ethernet adapter",
151      DC_CLS_NETIF		/* class */
152} };
153
154static inline void
155ep_registerdev(struct isa_device *id)
156{
157      if(id->id_unit)
158              kdc_ep[id->id_unit] = kdc_ep[0];
159      kdc_ep[id->id_unit].kdc_unit = id->id_unit;
160      kdc_ep[id->id_unit].kdc_parentdata = id;
161      dev_attach(&kdc_ep[id->id_unit]);
162}
163
164static int ep_current_tag = EP_LAST_TAG + 1;
165
166static struct {
167	int epb_addr;	/* address of this board */
168	char epb_used;	/* was this entry already used for configuring ? */
169	}
170	ep_board[EP_MAX_BOARDS + 1];
171
172static int
173eeprom_rdy(is)
174    struct isa_device *is;
175{
176    int i;
177
178    for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
179    if (i >= MAX_EEPROMBUSY) {
180	printf("ep%d: eeprom failed to come ready.\n", is->id_unit);
181	return (0);
182    }
183    return (1);
184}
185
186static int
187ep_look_for_board_at(is)
188    struct isa_device *is;
189{
190    int data, i, j, io_base, id_port = EP_ID_PORT;
191    int nisa = 0, neisa = 0;
192
193    if (ep_current_tag == (EP_LAST_TAG + 1)) {
194	/* Come here just one time */
195
196	/* Look for the EISA boards, leave them activated */
197	for(j = 1; j < 16; j++) {
198	    io_base = (j * EP_EISA_START) | EP_EISA_W0;
199	    if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
200		continue;
201
202	    /* we must found 0x1f if the board is EISA configurated */
203	    if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
204		continue;
205
206	    /* Reset and Enable the card */
207	    outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
208	    DELAY(1000); /* we must wait at least 1 ms */
209	    outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
210
211	    /*
212	     * Once activated, all the registers are mapped in the range
213	     * x000 - x00F, where x is the slot number.
214             */
215	    ep_board[neisa].epb_used = 0;
216	    ep_board[neisa++].epb_addr = j * EP_EISA_START;
217	}
218	ep_current_tag--;
219
220        /* Look for the ISA boards. Init and leave them actived */
221	outb(id_port, 0xc0);	/* Global reset */
222	DELAY(10000);
223	for (i = 0; i < EP_MAX_BOARDS; i++) {
224	    outb(id_port, 0);
225	    outb(id_port, 0);
226	    send_ID_sequence(id_port);
227
228	    data = get_eeprom_data(id_port, EEPROM_MFG_ID);
229	    if (data != MFG_ID)
230		break;
231
232	    /* resolve contention using the Ethernet address */
233	    for (j = 0; j < 3; j++)
234		data = get_eeprom_data(id_port, j);
235
236	    ep_board[neisa+nisa].epb_used = 0;
237	    ep_board[neisa+nisa++].epb_addr =
238		(get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
239	    outb(id_port, ep_current_tag);	/* tags board */
240	    outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
241	    ep_current_tag--;
242	}
243
244	ep_board[neisa+nisa].epb_addr = 0;
245	if (neisa) {
246	    printf("%d 3C5x9 board(s) on EISA found at", neisa);
247	    for (j = 0; ep_board[j].epb_addr; j++)
248		if (ep_board[j].epb_addr >= EP_EISA_START)
249		    printf(" 0x%x", ep_board[j].epb_addr);
250	    printf("\n");
251	}
252	if (nisa) {
253	    printf("%d 3C5x9 board(s) on ISA found at", nisa);
254	    for (j = 0; ep_board[j].epb_addr; j++)
255		if (ep_board[j].epb_addr < EP_EISA_START)
256		    printf(" 0x%x", ep_board[j].epb_addr);
257	    printf("\n");
258	}
259    }
260
261    /* we have two cases:
262     *
263     *  1. Device was configured with 'port ?'
264     *      In this case we search for the first unused card in list
265     *
266     *  2. Device was configured with 'port xxx'
267     *      In this case we search for the unused card with that address
268     *
269     */
270
271    if(IS_BASE==-1) { /* port? */
272	for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++);
273	if(ep_board[i].epb_addr==0)
274	    return 0;
275
276	IS_BASE=ep_board[i].epb_addr;
277	ep_board[i].epb_used=1;
278	return 1;
279    } else {
280	for (i=0; ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE; i++);
281
282	if( ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
283	    return 0;
284
285	if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE)
286	    printf("ep%d: 3c5x9 at 0x%x in test mode. Erase pencil mark!\n",
287		   is->id_unit, IS_BASE);
288	ep_board[i].epb_used=1;
289	return 1;
290    }
291}
292
293/*
294 * get_e: gets a 16 bits word from the EEPROM. we must have set the window
295 * before
296 */
297static int
298get_e(is, offset)
299    struct isa_device *is;
300    int offset;
301{
302    if (!eeprom_rdy(is))
303	return (0xffff);
304    outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
305    if (!eeprom_rdy(is))
306	return (0xffff);
307    return (inw(IS_BASE + EP_W0_EEPROM_DATA));
308}
309
310int
311epprobe(is)
312    struct isa_device *is;
313{
314    struct ep_softc *sc = &ep_softc[is->id_unit];
315    u_short k;
316
317    ep_registerdev(is);
318
319    if (!ep_look_for_board_at(is))
320	return (0);
321    /*
322     * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
323     * 0x9[0-f]50
324     */
325    GO_WINDOW(0);
326    k = get_e(is, EEPROM_PROD_ID);
327    if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
328	printf("epprobe: ignoring model %04x\n", k);
329	return (0);
330    }
331
332    k = get_e(is, EEPROM_RESOURCE_CFG);
333    k >>= 12;
334
335    /* Now we have two cases again:
336     *
337     *  1. Device was configured with 'irq?'
338     *      In this case we use irq read from the board
339     *
340     *  2. Device was configured with 'irq xxx'
341     *      In this case we set up the board to use specified interrupt
342     *
343     */
344
345    if(is->id_irq==0) { /* irq? */
346	is->id_irq= 1 << ( (k==2) ? 9 : k );
347    }
348
349    if (BASE >= EP_EISA_START) /* we have an EISA board, we allow 32 bits access */
350	sc->stat = F_ACCESS_32_BITS;
351    else
352	sc->stat = 0;
353
354    /* By now, the adapter is already activated */
355
356    return (0x10);		/* 16 bytes of I/O space used. */
357}
358
359static char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
360
361static int
362epattach(is)
363    struct isa_device *is;
364{
365    struct ep_softc *sc = &ep_softc[is->id_unit];
366    struct ifnet *ifp = &sc->arpcom.ac_if;
367    u_short i, j, *p;
368    struct ifaddr *ifa;
369    struct sockaddr_dl *sdl;
370    int irq;
371
372    /* BASE = IS_BASE; */
373    sc->ep_io_addr = is->id_iobase;
374
375    printf("ep%d: ", is->id_unit);
376
377    sc->ep_connectors = 0;
378    i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
379    j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
380    if (i & IS_AUI) {
381	printf("aui");
382	sc->ep_connectors |= AUI;
383    }
384    if (i & IS_BNC) {
385	if (sc->ep_connectors)
386	    printf("/");
387	printf("bnc");
388	sc->ep_connectors |= BNC;
389    }
390    if (i & IS_UTP) {
391	if (sc->ep_connectors)
392	    printf("/");
393	printf("utp");
394	sc->ep_connectors |= UTP;
395    }
396    if (!(sc->ep_connectors & 7))
397	printf("no connectors!");
398    else
399	printf("[*%s*]", ep_conn_type[j]);
400
401    /*
402     * Read the station address from the eeprom
403     */
404    p = (u_short *) & sc->arpcom.ac_enaddr;
405    for (i = 0; i < 3; i++) {
406	GO_WINDOW(0);
407	p[i] = htons(get_e(is, i));
408	GO_WINDOW(2);
409	outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
410    }
411    printf(" address %6D", sc->arpcom.ac_enaddr, ":");
412
413    /*
414     * Write IRQ value to board
415     */
416
417    i=is->id_irq;
418    if(i==0) {
419	printf(" irq STRANGE\n");
420	return 0;
421	}
422
423    for(irq=0; !(i & 1) && irq<16 ; i>>=1, irq++);
424
425    if(irq==9)
426	irq=2;
427    printf(" irq %d\n",irq);
428    GO_WINDOW(0);
429    outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(irq));
430
431    ifp->if_unit = is->id_unit;
432    ifp->if_name = "ep";
433    ifp->if_mtu = ETHERMTU;
434    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
435    ifp->if_output = ether_output;
436    ifp->if_start = epstart;
437    ifp->if_ioctl = epioctl;
438    ifp->if_watchdog = epwatchdog;
439
440    if_attach(ifp);
441    kdc_ep[is->id_unit].kdc_state = DC_BUSY;
442
443    /*
444     * Fill the hardware address into ifa_addr if we find an AF_LINK entry.
445     * We need to do this so bpf's can get the hardware addr of this card.
446     * netstat likes this too!
447     */
448    ifa = ifp->if_addrlist;
449    while ((ifa != 0) && (ifa->ifa_addr != 0) &&
450	   (ifa->ifa_addr->sa_family != AF_LINK))
451	ifa = ifa->ifa_next;
452
453    if ((ifa != 0) && (ifa->ifa_addr != 0)) {
454	sdl = (struct sockaddr_dl *) ifa->ifa_addr;
455	sdl->sdl_type = IFT_ETHER;
456	sdl->sdl_alen = ETHER_ADDR_LEN;
457	sdl->sdl_slen = 0;
458	bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
459    }
460    /* we give some initial parameters */
461    sc->rx_avg_pkt = 128;
462
463    /*
464     * NOTE: In all this I multiply everything by 64.
465     * W_s = the speed the CPU is able to write to the TX FIFO.
466     * T_s = the speed the board sends the info to the Ether.
467     * W_s/T_s = 16   (represents 16/64) =>    W_s = 25 % of T_s.
468     * This will give us for a packet of 1500 bytes
469     * tx_start_thresh=1125 and for a pkt of 64 bytes tx_start_threshold=48.
470     * We prefer to start thinking the CPU is much slower than the Ethernet
471     * transmission.
472     */
473    sc->tx_rate = TX_INIT_RATE;
474    sc->tx_counter = 0;
475    sc->rx_latency = RX_INIT_LATENCY;
476    sc->rx_early_thresh = RX_INIT_EARLY_THRESH;
477#ifdef EP_LOCAL_STATS
478    sc->rx_no_first = sc->rx_no_mbuf =
479	sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
480	sc->tx_underrun = 0;
481#endif
482    ep_fset(F_RX_FIRST);
483    sc->top = sc->mcur = 0;
484
485#if NBPFILTER > 0
486    bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
487#endif
488    return 1;
489}
490
491
492/*
493 * The order in here seems important. Otherwise we may not receive
494 * interrupts. ?!
495 */
496static void
497epinit(unit)
498    int unit;
499{
500    register struct ep_softc *sc = &ep_softc[unit];
501    register struct ifnet *ifp = &sc->arpcom.ac_if;
502    int s, i, j;
503
504	/*
505    if (ifp->if_addrlist == (struct ifaddr *) 0)
506	return;
507	*/
508
509    s = splimp();
510    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
511
512    GO_WINDOW(0);
513    outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
514    GO_WINDOW(4);
515    outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
516    GO_WINDOW(0);
517
518    /* Disable the card */
519    outw(BASE + EP_W0_CONFIG_CTRL, 0);
520
521    /* Enable the card */
522    outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
523
524    GO_WINDOW(2);
525
526    /* Reload the ether_addr. */
527    for (i = 0; i < 6; i++)
528	outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
529
530    outw(BASE + EP_COMMAND, RX_RESET);
531    outw(BASE + EP_COMMAND, TX_RESET);
532
533    /* Window 1 is operating window */
534    GO_WINDOW(1);
535    for (i = 0; i < 31; i++)
536	inb(BASE + EP_W1_TX_STATUS);
537
538    /* get rid of stray intr's */
539    outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
540
541    outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
542
543    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
544
545	if(ifp->if_flags & IFF_PROMISC)
546		outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
547		 FIL_GROUP | FIL_BRDCST | FIL_ALL);
548	else
549		outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
550		 FIL_GROUP | FIL_BRDCST);
551
552	 /*
553	  * S.B.
554	  *
555	  * Now behavior was slightly changed:
556	  *
557	  * if any of flags link[0-2] is used and its connector is
558	  * physically present the following connectors are used:
559	  *
560	  *   link0 - AUI * highest precedence
561	  *   link1 - BNC
562	  *   link2 - UTP * lowest precedence
563	  *
564	  * If none of them is specified then
565	  * connector specified in the EEPROM is used
566	  * (if present on card or AUI if not).
567	  *
568	  */
569
570    if(ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) {
571	/* nothing */
572    } else if(ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) {
573	outw(BASE + EP_COMMAND, START_TRANSCEIVER);
574	DELAY(1000);
575    } else if(ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) {
576	GO_WINDOW(4);
577	outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
578	GO_WINDOW(1);
579    } else {
580	GO_WINDOW(0);
581	j = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
582	GO_WINDOW(1);
583	switch(j) {
584	    case ACF_CONNECTOR_UTP:
585		if(sc->ep_connectors & UTP) {
586		    GO_WINDOW(4);
587		    outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
588		    GO_WINDOW(1);
589		}
590		break;
591	    case ACF_CONNECTOR_BNC:
592		if(sc->ep_connectors & BNC) {
593		    outw(BASE + EP_COMMAND, START_TRANSCEIVER);
594		    DELAY(1000);
595		}
596		break;
597	    case ACF_CONNECTOR_AUI:
598		/* nothing to do */
599		break;
600	    default:
601		printf("ep%d: strange connector type in EEPROM: assuming AUI\n",
602		    unit);
603		break;
604	}
605    }
606
607    outw(BASE + EP_COMMAND, RX_ENABLE);
608    outw(BASE + EP_COMMAND, TX_ENABLE);
609
610    ifp->if_flags |= IFF_RUNNING;
611    ifp->if_flags &= ~IFF_OACTIVE;	/* just in case */
612
613    sc->tx_rate = TX_INIT_RATE;
614    sc->tx_counter = 0;
615    sc->rx_latency = RX_INIT_LATENCY;
616    sc->rx_early_thresh = RX_INIT_EARLY_THRESH;
617#ifdef EP_LOCAL_STATS
618    sc->rx_no_first = sc->rx_no_mbuf =
619	sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
620	sc->tx_underrun = 0;
621#endif
622    ep_fset(F_RX_FIRST);
623    ep_frst(F_RX_TRAILER);
624    if (sc->top) {
625	m_freem(sc->top);
626	sc->top = sc->mcur = 0;
627    }
628    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | sc->rx_early_thresh);
629
630    /*
631     * These clever computations look very interesting
632     * but the fixed threshold gives near no output errors
633     * and if it as low as 16 bytes it gives the max. throughput.
634     * We think that processor is anyway quicker than Ethernet
635	 * (and this should be true for any 386 and higher)
636     */
637
638    outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
639
640    /*
641     * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up
642     * any that we had in case we're being called from intr or somewhere
643     * else.
644     */
645    sc->last_mb = 0;
646    sc->next_mb = 0;
647    epmbuffill((caddr_t) sc, 0);
648
649    epstart(ifp);
650
651    splx(s);
652}
653
654static const char padmap[] = {0, 3, 2, 1};
655
656static void
657epstart(ifp)
658    struct ifnet *ifp;
659{
660    register struct ep_softc *sc = &ep_softc[ifp->if_unit];
661    register u_int len;
662    register struct mbuf *m;
663    struct mbuf *top;
664    int s, pad;
665
666    s = splimp();
667    if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
668	splx(s);
669	return;
670    }
671startagain:
672    /* Sneak a peek at the next packet */
673    m = sc->arpcom.ac_if.if_snd.ifq_head;
674    if (m == 0) {
675	splx(s);
676	return;
677    }
678#if 0
679    len = m->m_pkthdr.len;
680#else
681    for (len = 0, top = m; m; m = m->m_next)
682	len += m->m_len;
683#endif
684
685    pad = padmap[len & 3];
686
687    /*
688     * The 3c509 automatically pads short packets to minimum ethernet length,
689     * but we drop packets that are too large. Perhaps we should truncate
690     * them instead?
691     */
692    if (len + pad > ETHER_MAX_LEN) {
693	/* packet is obviously too large: toss it */
694	++sc->arpcom.ac_if.if_oerrors;
695	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
696	m_freem(m);
697	goto readcheck;
698    }
699    if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
700	/* no room in FIFO */
701	outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
702	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
703	splx(s);
704	return;
705    }
706    IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
707
708    outw(BASE + EP_W1_TX_PIO_WR_1, len);
709    outw(BASE + EP_W1_TX_PIO_WR_1, 0x0);	/* Second dword meaningless */
710
711    /* compute the Tx start threshold for this packet */
712    sc->tx_start_thresh = len =
713	(((len * (64 - sc->tx_rate)) >> 6) & ~3) + 16;
714#if 0
715    /*
716     * The following string does something strange with the card and
717     * we get a lot of output errors due to it so it's commented out
718     * and we use fixed threshold (see above)
719     */
720
721    outw(BASE + EP_COMMAND, SET_TX_START_THRESH | len);
722#endif
723
724    for (top = m; m != 0; m = m->m_next)
725	if(ep_ftst(F_ACCESS_32_BITS)) {
726	    outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
727		  m->m_len / 4);
728	    if (m->m_len & 3)
729		outsb(BASE + EP_W1_TX_PIO_WR_1,
730		      mtod(m, caddr_t) + m->m_len / 4,
731		      m->m_len & 3);
732	} else {
733	    outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
734	    if (m->m_len & 1)
735		outb(BASE + EP_W1_TX_PIO_WR_1,
736		     *(mtod(m, caddr_t) + m->m_len - 1));
737	}
738
739    while (pad--)
740	outb(BASE + EP_W1_TX_PIO_WR_1, 0);	/* Padding */
741
742#if NBPFILTER > 0
743    if (sc->bpf) {
744	bpf_mtap(sc->bpf, top);
745    }
746#endif
747
748    sc->arpcom.ac_if.if_opackets++;
749    m_freem(top);
750    /*
751     * Every 1024*4 packets we increment the tx_rate if we haven't had
752     * errors, that in the case it has abnormaly goten too low
753     */
754    if (!(++sc->tx_counter & (1024 * 4 - 1)) &&
755	sc->tx_rate < TX_INIT_MAX_RATE)
756	sc->tx_rate++;
757
758    /*
759     * Is another packet coming in? We don't want to overflow the tiny RX
760     * fifo.
761     */
762readcheck:
763    if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
764	/*
765	 * we check if we have packets left, in that case we prepare to come
766	 * back later
767	 */
768	if (sc->arpcom.ac_if.if_snd.ifq_head) {
769	    outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH |
770		 sc->tx_start_thresh);
771	}
772	splx(s);
773	return;
774    }
775    goto startagain;
776}
777
778void
779epintr(unit)
780    int unit;
781{
782    register int status;
783    register struct ep_softc *sc = &ep_softc[unit];
784    int x;
785
786    x=splbio();
787
788    outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */
789
790rescan:
791
792    while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {
793
794	/* first acknowledge all interrupt sources */
795	outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));
796
797	if (status & (S_RX_COMPLETE | S_RX_EARLY)) {
798	    epread(sc);
799	    continue;
800	}
801	if (status & S_TX_AVAIL) {
802	    /* we need ACK */
803	    sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
804	    GO_WINDOW(1);
805	    inw(BASE + EP_W1_FREE_TX);
806	    epstart(&sc->arpcom.ac_if);
807	}
808	if (status & S_CARD_FAILURE) {
809#ifdef EP_LOCAL_STATS
810	    printf("\nep%d:\n\tStatus: %x\n", unit, status);
811	    GO_WINDOW(4);
812	    printf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
813	    printf("\tStat: %x\n", sc->stat);
814	    printf("\tIpackets=%d, Opackets=%d\n",
815		sc->arpcom.ac_if.if_ipackets, sc->arpcom.ac_if.if_opackets);
816	    printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
817		   sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf,
818		   sc->rx_overrunl, sc->tx_underrun);
819#else
820	    printf("ep%d: Status: %x\n", unit, status);
821#endif
822	    epinit(unit);
823	    splx(x);
824	    return;
825	}
826	if (status & S_TX_COMPLETE) {
827	    /* we  need ACK. we do it at the end */
828	    /*
829	     * We need to read TX_STATUS until we get a 0 status in order to
830	     * turn off the interrupt flag.
831	     */
832	    while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
833		if (status & TXS_SUCCES_INTR_REQ);
834		else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
835		    outw(BASE + EP_COMMAND, TX_RESET);
836		    if (status & TXS_UNDERRUN) {
837			if (sc->tx_rate > 1) {
838			    sc->tx_rate--;	/* Actually in steps of 1/64 */
839			    sc->tx_counter = 0;	/* We reset it */
840			}
841#ifdef EP_LOCAL_STATS
842			sc->tx_underrun++;
843#endif
844		    } else {
845			if (status & TXS_JABBER);
846			else	/* TXS_MAX_COLLISION - we shouldn't get here */
847			    ++sc->arpcom.ac_if.if_collisions;
848		    }
849		    ++sc->arpcom.ac_if.if_oerrors;
850		    outw(BASE + EP_COMMAND, TX_ENABLE);
851		    /*
852		     * To have a tx_avail_int but giving the chance to the
853		     * Reception
854		     */
855		    if (sc->arpcom.ac_if.if_snd.ifq_head) {
856			outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
857		    }
858		}
859		outb(BASE + EP_W1_TX_STATUS, 0x0);	/* pops up the next
860							 * status */
861	    }			/* while */
862	    sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
863	    GO_WINDOW(1);
864	    inw(BASE + EP_W1_FREE_TX);
865	    epstart(&sc->arpcom.ac_if);
866	}			/* end TX_COMPLETE */
867    }
868
869    outw(BASE + EP_COMMAND, C_INTR_LATCH);	/* ACK int Latch */
870
871    if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
872	goto rescan;
873
874    /* re-enable Ints */
875    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
876
877    splx(x);
878}
879
880static void
881epread(sc)
882    register struct ep_softc *sc;
883{
884    struct ether_header *eh;
885    struct mbuf *top, *mcur, *m;
886    int lenthisone;
887
888    short rx_fifo2, status;
889    register short delta;
890    register short rx_fifo;
891
892    status = inw(BASE + EP_W1_RX_STATUS);
893
894read_again:
895
896    if (status & ERR_RX) {
897	++sc->arpcom.ac_if.if_ierrors;
898	if (status & ERR_RX_OVERRUN) {
899	    /*
900	     * we can think the rx latency is actually greather than we
901	     * expect
902	     */
903#ifdef EP_LOCAL_STATS
904	    if (ep_ftst(F_RX_FIRST))
905		sc->rx_overrunf++;
906	    else
907		sc->rx_overrunl++;
908#endif
909	    if (sc->rx_latency < ETHERMTU)
910		sc->rx_latency += 16;
911	}
912	goto out;
913    }
914    rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;
915
916    if (ep_ftst(F_RX_FIRST)) {
917	if (m = sc->mb[sc->next_mb]) {
918	    sc->mb[sc->next_mb] = 0;
919	    sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
920	    m->m_data = m->m_pktdat;
921	    m->m_flags = M_PKTHDR;
922	} else {
923	    MGETHDR(m, M_DONTWAIT, MT_DATA);
924	    if (!m)
925		goto out;
926	}
927	sc->top = sc->mcur = top = m;
928#define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
929#define EOFF    (EROUND - sizeof(struct ether_header))
930	top->m_data += EOFF;
931
932	/* Read what should be the header. */
933	insw(BASE + EP_W1_RX_PIO_RD_1,
934	     mtod(top, caddr_t), sizeof(struct ether_header) / 2);
935	top->m_len = sizeof(struct ether_header);
936	rx_fifo -= sizeof(struct ether_header);
937	sc->cur_len = rx_fifo2;
938    } else {
939	/* come here if we didn't have a complete packet last time */
940	top = sc->top;
941	m = sc->mcur;
942	sc->cur_len += rx_fifo2;
943	if (ep_ftst(F_RX_TRAILER))
944	    /* We don't read the trailer */
945	    rx_fifo -= sizeof(struct ether_header);
946    }
947
948    /* Reads what is left in the RX FIFO */
949    while (rx_fifo > 0) {
950	lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
951	if (lenthisone == 0) {	/* no room in this one */
952	    mcur = m;
953	    if (m = sc->mb[sc->next_mb]) {
954		sc->mb[sc->next_mb] = 0;
955		sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
956	    } else {
957		MGET(m, M_DONTWAIT, MT_DATA);
958		if (!m)
959		    goto out;
960	    }
961
962	    if (rx_fifo >= MINCLSIZE)
963		MCLGET(m, M_DONTWAIT);
964	    m->m_len = 0;
965	    mcur->m_next = m;
966	    lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
967	}
968	if (ep_ftst(F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
969	    insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
970		 lenthisone / 4);
971	    m->m_len += (lenthisone & ~3);
972	    if (lenthisone & 3)
973		insb(BASE + EP_W1_RX_PIO_RD_1,
974		     mtod(m, caddr_t) + m->m_len,
975		     lenthisone & 3);
976	    m->m_len += (lenthisone & 3);
977	} else {
978	    insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
979		 lenthisone / 2);
980	    m->m_len += lenthisone;
981	    if (lenthisone & 1)
982		*(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
983	}
984	rx_fifo -= lenthisone;
985    }
986
987    if (ep_ftst(F_RX_TRAILER)) {/* reads the trailer */
988	if (m = sc->mb[sc->next_mb]) {
989	    sc->mb[sc->next_mb] = 0;
990	    sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
991	    m->m_data = m->m_pktdat;
992	    m->m_flags = M_PKTHDR;
993	} else {
994	    MGETHDR(m, M_DONTWAIT, MT_DATA);
995	    if (!m)
996		goto out;
997	}
998	insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t),
999	     sizeof(struct ether_header));
1000	m->m_len = sizeof(struct ether_header);
1001	m->m_next = top;
1002	sc->top = top = m;
1003	/* XXX Accomodate for type and len from beginning of trailer */
1004	sc->cur_len -= (2 * sizeof(u_short));
1005	ep_frst(F_RX_TRAILER);
1006	goto all_pkt;
1007    }
1008
1009    if (status & ERR_RX_INCOMPLETE) {	/* we haven't received the complete
1010					 * packet */
1011	sc->mcur = m;
1012#ifdef EP_LOCAL_STATS
1013	sc->rx_no_first++;	/* to know how often we come here */
1014#endif
1015	/*
1016	 * Re-compute rx_latency, the factor used is 1/4 to go up and 1/32 to
1017	 * go down
1018	 */
1019	delta = rx_fifo2 - sc->rx_early_thresh;	/* last latency seen LLS */
1020	delta -= sc->rx_latency;/* LLS - estimated_latency */
1021	if (delta >= 0)
1022	    sc->rx_latency += (delta / 4);
1023	else
1024	    sc->rx_latency += (delta / 32);
1025	ep_frst(F_RX_FIRST);
1026	if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
1027	    /* we see if by now, the packet has completly arrived */
1028	    goto read_again;
1029	}
1030	/* compute rx_early_threshold */
1031	delta = (sc->rx_avg_pkt - sc->cur_len - sc->rx_latency - 16) & ~3;
1032	if (delta < MIN_RX_EARLY_THRESHL)
1033	    delta = MIN_RX_EARLY_THRESHL;
1034
1035	outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH |
1036	     (sc->rx_early_thresh = delta));
1037	return;
1038    }
1039all_pkt:
1040    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1041    /*
1042     * recompute average packet's length, the factor used is 1/8 to go down
1043     * and 1/32 to go up
1044     */
1045    delta = sc->cur_len - sc->rx_avg_pkt;
1046    if (delta > 0)
1047	sc->rx_avg_pkt += (delta / 32);
1048    else
1049	sc->rx_avg_pkt += (delta / 8);
1050    delta = (sc->rx_avg_pkt - sc->rx_latency - 16) & ~3;
1051    if (delta < MIN_RX_EARLY_THRESHF)
1052	delta = MIN_RX_EARLY_THRESHF;
1053    sc->rx_early_thresh = delta;
1054    ++sc->arpcom.ac_if.if_ipackets;
1055    ep_fset(F_RX_FIRST);
1056    ep_frst(F_RX_TRAILER);
1057    top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1058    top->m_pkthdr.len = sc->cur_len;
1059
1060#if NBPFILTER > 0
1061    if (sc->bpf) {
1062	bpf_mtap(sc->bpf, top);
1063
1064	/*
1065	 * Note that the interface cannot be in promiscuous mode if there are
1066	 * no BPF listeners.  And if we are in promiscuous mode, we have to
1067	 * check if this packet is really ours.
1068	 */
1069	eh = mtod(top, struct ether_header *);
1070	if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
1071	    (eh->ether_dhost[0] & 1) == 0 &&
1072	    bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
1073		 sizeof(eh->ether_dhost)) != 0 &&
1074	    bcmp(eh->ether_dhost, etherbroadcastaddr,
1075		 sizeof(eh->ether_dhost)) != 0) {
1076	    if (sc->top) {
1077		m_freem(sc->top);
1078		sc->top = 0;
1079	    }
1080	    ep_fset(F_RX_FIRST);
1081	    ep_frst(F_RX_TRAILER);
1082#ifdef EP_LOCAL_STATS
1083	    sc->rx_bpf_disc++;
1084#endif
1085	    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1086	    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | delta);
1087	    return;
1088	}
1089    }
1090#endif
1091
1092    eh = mtod(top, struct ether_header *);
1093    m_adj(top, sizeof(struct ether_header));
1094    ether_input(&sc->arpcom.ac_if, eh, top);
1095    if (!sc->mb[sc->next_mb])
1096	epmbuffill((caddr_t) sc, 0);
1097    sc->top = 0;
1098    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1099    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | delta);
1100    return;
1101
1102out:
1103    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1104    if (sc->top) {
1105	m_freem(sc->top);
1106	sc->top = 0;
1107#ifdef EP_LOCAL_STATS
1108	sc->rx_no_mbuf++;
1109#endif
1110    }
1111    delta = (sc->rx_avg_pkt - sc->rx_latency - 16) & ~3;
1112    if (delta < MIN_RX_EARLY_THRESHF)
1113	delta = MIN_RX_EARLY_THRESHF;
1114    ep_fset(F_RX_FIRST);
1115    ep_frst(F_RX_TRAILER);
1116    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1117    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH |
1118	 (sc->rx_early_thresh = delta));
1119}
1120
1121/*
1122 * Look familiar?
1123 */
1124static int
1125epioctl(ifp, cmd, data)
1126    register struct ifnet *ifp;
1127    int cmd;
1128    caddr_t data;
1129{
1130    register struct ifaddr *ifa = (struct ifaddr *) data;
1131    struct ep_softc *sc = &ep_softc[ifp->if_unit];
1132    struct ifreq *ifr = (struct ifreq *) data;
1133    int s, error = 0;
1134
1135    s = splimp();
1136
1137    switch (cmd) {
1138      case SIOCSIFADDR:
1139	ifp->if_flags |= IFF_UP;
1140	switch (ifa->ifa_addr->sa_family) {
1141#ifdef INET
1142	  case AF_INET:
1143	    epinit(ifp->if_unit);	/* before arpwhohas */
1144	    arp_ifinit((struct arpcom *)ifp, ifa);
1145	    break;
1146#endif
1147#ifdef IPX
1148	  case AF_IPX:
1149	    {
1150		register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
1151
1152		if (ipx_nullhost(*ina))
1153		    ina->x_host =
1154			*(union ipx_host *) (sc->arpcom.ac_enaddr);
1155		else {
1156		    ifp->if_flags &= ~IFF_RUNNING;
1157		    bcopy((caddr_t) ina->x_host.c_host,
1158			  (caddr_t) sc->arpcom.ac_enaddr,
1159			  sizeof(sc->arpcom.ac_enaddr));
1160		}
1161		epinit(ifp->if_unit);
1162		break;
1163	    }
1164#endif
1165#ifdef NS
1166	  case AF_NS:
1167	    {
1168		register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1169
1170		if (ns_nullhost(*ina))
1171		    ina->x_host =
1172			*(union ns_host *) (sc->arpcom.ac_enaddr);
1173		else {
1174		    ifp->if_flags &= ~IFF_RUNNING;
1175		    bcopy((caddr_t) ina->x_host.c_host,
1176			  (caddr_t) sc->arpcom.ac_enaddr,
1177			  sizeof(sc->arpcom.ac_enaddr));
1178		}
1179		epinit(ifp->if_unit);
1180		break;
1181	    }
1182#endif
1183	  default:
1184	    epinit(ifp->if_unit);
1185	    break;
1186	}
1187	break;
1188      case SIOCGIFADDR:
1189	{
1190	  struct sockaddr *sa;
1191
1192	  sa = (struct sockaddr *) & ifr->ifr_data;
1193	  bcopy((caddr_t) sc->arpcom.ac_enaddr,
1194		(caddr_t) sa->sa_data, ETHER_ADDR_LEN);
1195	}
1196	break;
1197      case SIOCSIFFLAGS:
1198	if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1199	    ifp->if_flags &= ~IFF_RUNNING;
1200	    epstop(ifp->if_unit);
1201	    epmbufempty(sc);
1202	    break;
1203	} else {
1204	    /* reinitialize card on any parameter change */
1205	    epinit(ifp->if_unit);
1206	    break;
1207	}
1208
1209	/* NOTREACHED */
1210
1211	if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0)
1212	    epinit(ifp->if_unit);
1213
1214	if ( (ifp->if_flags & IFF_PROMISC) &&  !ep_ftst(F_PROMISC) ) {
1215	    ep_fset(F_PROMISC);
1216	    epinit(ifp->if_unit);
1217	    }
1218	else if( !(ifp->if_flags & IFF_PROMISC) && ep_ftst(F_PROMISC) ) {
1219	    ep_frst(F_PROMISC);
1220	    epinit(ifp->if_unit);
1221	    }
1222
1223	break;
1224#ifdef notdef
1225      case SIOCGHWADDR:
1226	bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
1227	      sizeof(sc->sc_addr));
1228	break;
1229#endif
1230	case SIOCSIFMTU:
1231
1232		/*
1233		 * Set the interface MTU.
1234		 */
1235		if (ifr->ifr_mtu > ETHERMTU) {
1236			error = EINVAL;
1237		} else {
1238			ifp->if_mtu = ifr->ifr_mtu;
1239		}
1240		break;
1241
1242      default:
1243		error = EINVAL;
1244    }
1245
1246    splx(s);
1247
1248    return (error);
1249}
1250
1251static void
1252epwatchdog(ifp)
1253    struct ifnet *ifp;
1254{
1255    /*
1256    printf("ep: watchdog\n");
1257
1258    log(LOG_ERR, "ep%d: watchdog\n", ifp->if_unit);
1259    ifp->if_oerrors++;
1260    */
1261
1262    ifp->if_flags &= ~IFF_OACTIVE;
1263    epstart(ifp);
1264    epintr(ifp->if_unit);
1265}
1266
1267static void
1268epstop(unit)
1269    int unit;
1270{
1271    struct ep_softc *sc = &ep_softc[unit];
1272
1273    outw(BASE + EP_COMMAND, RX_DISABLE);
1274    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1275    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1276    outw(BASE + EP_COMMAND, TX_DISABLE);
1277    outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
1278    outw(BASE + EP_COMMAND, RX_RESET);
1279    outw(BASE + EP_COMMAND, TX_RESET);
1280    outw(BASE + EP_COMMAND, C_INTR_LATCH);
1281    outw(BASE + EP_COMMAND, SET_RD_0_MASK);
1282    outw(BASE + EP_COMMAND, SET_INTR_MASK);
1283    outw(BASE + EP_COMMAND, SET_RX_FILTER);
1284}
1285
1286
1287static int
1288send_ID_sequence(port)
1289    int port;
1290{
1291    int cx, al;
1292
1293    for (al = 0xff, cx = 0; cx < 255; cx++) {
1294	outb(port, al);
1295	al <<= 1;
1296	if (al & 0x100)
1297	    al ^= 0xcf;
1298    }
1299    return (1);
1300}
1301
1302
1303/*
1304 * We get eeprom data from the id_port given an offset into the eeprom.
1305 * Basically; after the ID_sequence is sent to all of the cards; they enter
1306 * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
1307 * the eeprom data.  We then read the port 16 times and with every read; the
1308 * cards check for contention (ie: if one card writes a 0 bit and another
1309 * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
1310 * compares the data on the bus; if there is a difference then that card goes
1311 * into ID_WAIT state again). In the meantime; one bit of data is returned in
1312 * the AX register which is conveniently returned to us by inb().  Hence; we
1313 * read 16 times getting one bit of data with each read.
1314 */
1315static int
1316get_eeprom_data(id_port, offset)
1317    int id_port;
1318    int offset;
1319{
1320    int i, data = 0;
1321    outb(id_port, 0x80 + offset);
1322    DELAY(1000);
1323    for (i = 0; i < 16; i++)
1324	data = (data << 1) | (inw(id_port) & 1);
1325    return (data);
1326}
1327
1328/*
1329 * We suppose this is always called inside a splimp(){...}splx() region
1330 */
1331static void
1332epmbuffill(sp, dummy_arg)
1333    caddr_t sp;
1334    int dummy_arg;
1335{
1336    struct ep_softc *sc = (struct ep_softc *) sp;
1337    int i;
1338
1339    i = sc->last_mb;
1340    do {
1341	if (sc->mb[i] == NULL)
1342	    MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1343	if (sc->mb[i] == NULL)
1344	    break;
1345	i = (i + 1) % MAX_MBS;
1346    } while (i != sc->next_mb);
1347    sc->last_mb = i;
1348}
1349
1350static void
1351epmbufempty(sc)
1352    struct ep_softc *sc;
1353{
1354    int s, i;
1355
1356    s = splimp();
1357    for (i = 0; i < MAX_MBS; i++) {
1358	if (sc->mb[i]) {
1359	    m_freem(sc->mb[i]);
1360	    sc->mb[i] = NULL;
1361	}
1362    }
1363    sc->last_mb = sc->next_mb = 0;
1364    splx(s);
1365}
1366
1367#endif				/* NEP > 0 */
1368