if_ep.c revision 1020
1/*
2 * Copyright (c) 1993 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. The name of the author may not be used to endorse or promote products
11 *    derived from this software withough specific prior written permission
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 *	From: if_ep.c,v 1.9 1994/01/25 10:46:29 deraadt Exp $
25 *	$Id: if_ep.c,v 1.5 1994/01/26 09:13:56 nate Exp $
26 */
27/*
28 * TODO:
29 *	Multi-509 configs.
30 *	don't pass unit into epstop.
31 *	epintr returns an int for magnum. 0=not for me. 1=for me. -1=whoknows?
32 *	deallocate mbufs when ifconfig'd down.
33 */
34#include "ep.h"
35#if NEP > 0
36
37#include "bpfilter.h"
38
39#include <sys/param.h>
40#if defined(__FreeBSD__)
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#endif
44#include <sys/mbuf.h>
45#include <sys/socket.h>
46#include <sys/ioctl.h>
47#include <sys/errno.h>
48#include <sys/syslog.h>
49#if defined(__NetBSD__)
50#include <sys/select.h>
51#endif
52
53#include <net/if.h>
54#include <net/netisr.h>
55#include <net/if_dl.h>
56#include <net/if_types.h>
57#include <net/netisr.h>
58
59#ifdef INET
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/in_var.h>
63#include <netinet/ip.h>
64#include <netinet/if_ether.h>
65#endif
66
67#ifdef NS
68#include <netns/ns.h>
69#include <netns/ns_if.h>
70#endif
71
72#if NBPFILTER > 0
73#include <net/bpf.h>
74#include <net/bpfdesc.h>
75#endif
76
77#include <machine/pio.h>
78
79#include <i386/isa/isa.h>
80#include <i386/isa/isa_device.h>
81#include <i386/isa/icu.h>
82#include <i386/isa/if_epreg.h>
83
84#define ETHER_MIN_LEN	64
85#define ETHER_MAX_LEN	1518
86#define ETHER_ADDR_LEN	6
87
88/*
89 * Ethernet software status per interface.
90 */
91struct ep_softc {
92	struct arpcom arpcom;		/* Ethernet common part		*/
93	short   ep_io_addr;		/* i/o bus address		*/
94	char    ep_connectors;		/* Connectors on this card.	*/
95#define MAX_MBS  4			/* # of mbufs we keep around	*/
96	struct mbuf *mb[MAX_MBS];	/* spare mbuf storage.		*/
97	int     next_mb;		/* Which mbuf to use next. 	*/
98	int     last_mb;		/* Last mbuf.			*/
99	int     tx_start_thresh;	/* Current TX_start_thresh.	*/
100	caddr_t bpf;			/* BPF  "magic cookie"		*/
101}       ep_softc[NEP];
102
103static int epprobe __P((struct isa_device *));
104static int epattach __P((struct isa_device *));
105static int epioctl __P((struct ifnet * ifp, int, caddr_t));
106
107void epinit __P((int));
108void epintr __P((int));
109void epmbufqueue __P((caddr_t, int));
110void epread __P((struct ep_softc *));
111void epreset __P((int));
112void epstart __P((struct ifnet *));
113void epstop __P((int));
114void epwatchdog __P((int));
115
116struct isa_driver epdriver = {
117	epprobe,
118	epattach,
119	"ep"
120};
121
122static int send_ID_sequence __P((u_short));
123static u_short get_eeprom_data __P((int, int));
124static int is_eeprom_busy __P((struct isa_device *));
125
126/*
127 * Rudimentary support for multiple cards is here but is not
128 * currently handled.  In the future we will have to add code
129 * for tagging the cards for later activation.  We wanna do something
130 * about the id_port.  We're limited due to current config procedure.
131 * Magnum config holds promise of a fix but we'll have to wait a bit.
132 */
133int
134epprobe(is)
135	struct isa_device *is;
136{
137	struct ep_softc *sc = &ep_softc[is->id_unit];
138	u_short k;
139	int     id_port = 0x100;	/* XXX */
140
141	outw(BASE + EP_COMMAND, GLOBAL_RESET);
142	DELAY(1000);
143	outb(id_port, 0xc0);	/* Global reset to id_port. */
144	DELAY(1000);
145	send_ID_sequence(id_port);
146	DELAY(1000);
147
148	/*
149	 * MFG_ID should have 0x6d50.
150	 * PROD_ID should be 0x9[0-f]50
151	 */
152	k = get_eeprom_data(id_port, EEPROM_MFG_ID);
153	if (k != MFG_ID)
154		return (0);
155	k = get_eeprom_data(id_port, EEPROM_PROD_ID);
156	if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
157		return (0);
158
159	k = get_eeprom_data(id_port, EEPROM_ADDR_CFG);	/* get addr cfg */
160	k = (k & 0x1f) * 0x10 + 0x200;			/* decode base addr. */
161	if (k != (u_short)is->id_iobase)
162		return (0);
163
164	k = get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
165	k >>= 12;
166	if (is->id_irq != (1 << ((k == 2) ? 9 : k)))
167		return (0);
168
169	outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
170
171	return (0x10);		/* 16 bytes of I/O space used. */
172}
173
174static int
175epattach(is)
176	struct isa_device *is;
177{
178	struct ep_softc *sc = &ep_softc[is->id_unit];
179	struct ifnet *ifp = &sc->arpcom.ac_if;
180	u_short i;
181	struct ifaddr *ifa;
182	struct sockaddr_dl *sdl;
183
184	sc->ep_io_addr = is->id_iobase;
185
186	printf("ep%d: ", is->id_unit);
187
188	sc->ep_connectors = 0;
189	i = inw(is->id_iobase + EP_W0_CONFIG_CTRL);
190	if (i & IS_AUI) {
191		printf("aui");
192		sc->ep_connectors |= AUI;
193	}
194	if (i & IS_BNC) {
195		if (sc->ep_connectors)
196			printf("/");
197		printf("bnc");
198		sc->ep_connectors |= BNC;
199	}
200	if (i & IS_UTP) {
201		if (sc->ep_connectors)
202			printf("/");
203		printf("utp");
204		sc->ep_connectors |= UTP;
205	}
206	if (!sc->ep_connectors)
207		printf("no connectors!");
208
209	/*
210	 * Read the station address from the eeprom
211	 */
212	for (i = 0; i < 3; i++) {
213		u_short *p;
214		GO_WINDOW(0);
215		if (is_eeprom_busy(is))
216			return(0);
217		outw(BASE + EP_W0_EEPROM_COMMAND, READ_EEPROM | i);
218		if (is_eeprom_busy(is))
219			return(0);
220		p =(u_short *)&sc->arpcom.ac_enaddr[i*2];
221		*p = htons(inw(BASE + EP_W0_EEPROM_DATA));
222		GO_WINDOW(2);
223		outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(*p));
224	}
225	printf(" address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
226
227	ifp->if_unit = is->id_unit;
228	ifp->if_name = "ep";
229	ifp->if_mtu = ETHERMTU;
230	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
231	ifp->if_init = epinit;
232	ifp->if_output = ether_output;
233	ifp->if_start = epstart;
234	ifp->if_ioctl = epioctl;
235	ifp->if_watchdog = epwatchdog;
236
237	if_attach(ifp);
238
239	/*
240	 * Fill the hardware address into ifa_addr if we find an
241	 * AF_LINK entry. We need to do this so bpf's can get the hardware
242	 * addr of this card. netstat likes this too!
243	 */
244	ifa = ifp->if_addrlist;
245	while ((ifa != 0) && (ifa->ifa_addr != 0) &&
246	    (ifa->ifa_addr->sa_family != AF_LINK))
247		ifa = ifa->ifa_next;
248
249	if ((ifa != 0) && (ifa->ifa_addr != 0)) {
250		sdl = (struct sockaddr_dl *) ifa->ifa_addr;
251		sdl->sdl_type = IFT_ETHER;
252		sdl->sdl_alen = ETHER_ADDR_LEN;
253		sdl->sdl_slen = 0;
254		bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
255	}
256#if NBPFILTER > 0
257	bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
258#endif
259	return 1;
260}
261
262
263/*
264 * The order in here seems important. Otherwise we may not receive
265 * interrupts. ?!
266 */
267void
268epinit(unit)
269	int     unit;
270{
271	register struct ep_softc *sc = &ep_softc[unit];
272	register struct ifnet *ifp = &sc->arpcom.ac_if;
273	int     s, i;
274
275	if (ifp->if_addrlist == (struct ifaddr *) 0)
276		return;
277
278	s = splimp();
279	while (inb(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
280		;
281
282	GO_WINDOW(0);
283
284	/* Disable the card */
285	outw(BASE + EP_W0_CONFIG_CTRL, 0);
286
287	/* Enable the card */
288	outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
289
290	GO_WINDOW(2);
291
292	/* Reload the ether_addr. */
293	for (i = 0; i < 6; i++)
294		outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
295
296	outw(BASE + EP_COMMAND, RX_RESET);
297	outw(BASE + EP_COMMAND, TX_RESET);
298
299	/* Window 1 is operating window */
300	GO_WINDOW(1);
301	for (i = 0; i < 31; i++)
302		inb(BASE + EP_W1_TX_STATUS);
303
304 	/* get rid of stray intr's */
305	outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
306
307	outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
308	    S_TX_COMPLETE | S_TX_AVAIL);
309	outw(BASE + EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
310	    S_TX_COMPLETE | S_TX_AVAIL);
311
312	outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
313	    FIL_GROUP | FIL_BRDCST);
314
315	/*
316	 * you can `ifconfig (link0|-link0) ep0' to get the following
317	 * behaviour:
318	 *	-link0	disable AUI/UTP. enable BNC.
319	 *	link0	disable BNC. enable AUI. if the card has a UTP
320	 *		connector, that is enabled too. not sure, but it
321	 * 		seems you have to be careful to not plug things
322	 *		into both AUI & UTP.
323	 */
324#if defined(__NetBSD__)
325	if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
326#else
327	if (!(ifp->if_flags & IFF_ALTPHYS) && (sc->ep_connectors & BNC)) {
328#endif
329		outw(BASE + EP_COMMAND, START_TRANSCEIVER);
330		DELAY(1000);
331	}
332#if defined(__NetBSD__)
333	if ((ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & UTP)) {
334#else
335	if ((ifp->if_flags & IFF_ALTPHYS) && (sc->ep_connectors & UTP)) {
336#endif
337		GO_WINDOW(4);
338		outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
339		GO_WINDOW(1);
340	}
341
342	outw(BASE + EP_COMMAND, RX_ENABLE);
343	outw(BASE + EP_COMMAND, TX_ENABLE);
344
345	ifp->if_flags |= IFF_RUNNING;
346	ifp->if_flags &= ~IFF_OACTIVE;	/* just in case */
347	sc->tx_start_thresh = 20;	/* probably a good starting point. */
348	/*
349	 * Store up a bunch of mbuf's for use later. (MAX_MBS). First we
350	 * free up any that we had in case we're being called from intr or
351	 * somewhere else.
352	 */
353	sc->last_mb = 0;
354	sc->next_mb = 0;
355	epmbufqueue((caddr_t)sc, 0);
356
357	epstart(ifp);
358
359	splx(s);
360}
361
362static const char padmap[] = {0, 3, 2, 1};
363
364void
365epstart(ifp)
366	struct ifnet *ifp;
367{
368	register struct ep_softc *sc = &ep_softc[ifp->if_unit];
369	struct mbuf *m, *top;
370	int     s, len, pad;
371
372	s = splimp();
373	if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
374		splx(s);
375		return;
376	}
377
378startagain:
379	/* Sneak a peek at the next packet */
380	m = sc->arpcom.ac_if.if_snd.ifq_head;
381	if (m == 0) {
382		splx(s);
383		return;
384	}
385#if 0
386	len = m->m_pkthdr.len;
387#else
388	for (len = 0, top = m; m; m = m->m_next)
389		len += m->m_len;
390#endif
391
392	pad = padmap[len & 3];
393
394	/*
395	 * The 3c509 automatically pads short packets to minimum ethernet
396	 * length, but we drop packets that are too large. Perhaps we should
397	 * truncate them instead?
398	 */
399	if (len + pad > ETHER_MAX_LEN) {
400		/* packet is obviously too large: toss it */
401		++sc->arpcom.ac_if.if_oerrors;
402		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
403		m_freem(m);
404		goto readcheck;
405	}
406
407	if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
408		/* no room in FIFO */
409		outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
410		sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
411		splx(s);
412		return;
413	}
414	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
415	if (m == 0) {		/* not really needed */
416		splx(s);
417		return;
418	}
419	outw(BASE + EP_COMMAND, SET_TX_START_THRESH |
420	    (len / 4 + sc->tx_start_thresh));
421
422	outw(BASE + EP_W1_TX_PIO_WR_1, len);
423	outw(BASE + EP_W1_TX_PIO_WR_1, 0xffff);	/* Second dword meaningless */
424
425	for (top = m; m != 0; m = m->m_next) {
426		outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len/2);
427		if (m->m_len & 1)
428			outb(BASE + EP_W1_TX_PIO_WR_1,
429			    *(mtod(m, caddr_t) + m->m_len - 1));
430	}
431	while (pad--)
432		outb(BASE + EP_W1_TX_PIO_WR_1, 0);	/* Padding */
433
434#if NBPFILTER > 0
435	if (sc->bpf) {
436		u_short etype;
437		int     off, datasize, resid;
438		struct ether_header *eh;
439		struct trailer_header {
440			u_short ether_type;
441			u_short ether_residual;
442		}       trailer_header;
443		char    ether_packet[ETHER_MAX_LEN];
444		char   *ep;
445
446		ep = ether_packet;
447
448		/*
449		 * We handle trailers below:
450		 * Copy ether header first, then residual data,
451		 * then data. Put all this in a temporary buffer
452		 * 'ether_packet' and send off to bpf. Since the
453		 * system has generated this packet, we assume
454		 * that all of the offsets in the packet are
455		 * correct; if they're not, the system will almost
456		 * certainly crash in m_copydata.
457		 * We make no assumptions about how the data is
458		 * arranged in the mbuf chain (i.e. how much
459		 * data is in each mbuf, if mbuf clusters are
460		 * used, etc.), which is why we use m_copydata
461		 * to get the ether header rather than assume
462		 * that this is located in the first mbuf.
463		 */
464		/* copy ether header */
465		m_copydata(top, 0, sizeof(struct ether_header), ep);
466		eh = (struct ether_header *) ep;
467		ep += sizeof(struct ether_header);
468		eh->ether_type = etype = ntohs(eh->ether_type);
469		if (etype >= ETHERTYPE_TRAIL &&
470		    etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
471			datasize = ((etype - ETHERTYPE_TRAIL) << 9);
472			off = datasize + sizeof(struct ether_header);
473
474			/* copy trailer_header into a data structure */
475			m_copydata(top, off, sizeof(struct trailer_header),
476			    &trailer_header.ether_type);
477
478			/* copy residual data */
479			resid = trailer_header.ether_residual -
480			    sizeof(struct trailer_header);
481			resid = ntohs(resid);
482			m_copydata(top, off + sizeof(struct trailer_header),
483			    resid, ep);
484			ep += resid;
485
486			/* copy data */
487			m_copydata(top, sizeof(struct ether_header),
488			    datasize, ep);
489			ep += datasize;
490
491			/* restore original ether packet type */
492			eh->ether_type = trailer_header.ether_type;
493
494			bpf_tap(sc->bpf, ether_packet, ep - ether_packet);
495		} else
496			bpf_mtap(sc->bpf, top);
497	}
498#endif
499
500	m_freem(top);
501	++sc->arpcom.ac_if.if_opackets;
502
503	/*
504	 * Is another packet coming in? We don't want to overflow the
505	 * tiny RX fifo.
506	 */
507readcheck:
508	if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
509		splx(s);
510		return;
511	}
512	goto startagain;
513}
514
515void
516epintr(unit)
517	int     unit;
518{
519	int     status, i;
520	register struct ep_softc *sc = &ep_softc[unit];
521	struct ifnet *ifp = &sc->arpcom.ac_if;
522	struct mbuf *m;
523
524	status = 0;
525checkintr:
526	status = inw(BASE + EP_STATUS) &
527	    (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE);
528	if (status == 0) {
529		/* No interrupts. */
530		outw(BASE + EP_COMMAND, C_INTR_LATCH);
531		return;
532	}
533	/* important that we do this first. */
534	outw(BASE + EP_COMMAND, ACK_INTR | status);
535
536	if (status & S_TX_AVAIL) {
537		status &= ~S_TX_AVAIL;
538		inw(BASE + EP_W1_FREE_TX);
539		sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
540		epstart(&sc->arpcom.ac_if);
541	}
542	if (status & S_RX_COMPLETE) {
543		status &= ~S_RX_COMPLETE;
544		epread(sc);
545	}
546	if (status & S_CARD_FAILURE) {
547		printf("ep%d: reset (status: %x)\n", unit, status);
548		outw(BASE + EP_COMMAND, C_INTR_LATCH);
549		epinit(unit);
550		return;
551	}
552	if (status & S_TX_COMPLETE) {
553		status &= ~S_TX_COMPLETE;
554		/*
555		 * We need to read TX_STATUS until we get a 0 status in
556		 * order to turn off the interrupt flag.
557		 */
558		while ((i = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
559			outw(BASE + EP_W1_TX_STATUS, 0x0);
560			if (i & (TXS_MAX_COLLISION | TXS_JABBER | TXS_UNDERRUN)) {
561				if (i & TXS_MAX_COLLISION)
562					++sc->arpcom.ac_if.if_collisions;
563				if (i & (TXS_JABBER | TXS_UNDERRUN)) {
564					outw(BASE + EP_COMMAND, TX_RESET);
565					if (i & TXS_UNDERRUN) {
566						if (sc->tx_start_thresh < ETHER_MAX_LEN) {
567							sc->tx_start_thresh += 20;
568							outw(BASE + EP_COMMAND,
569							    SET_TX_START_THRESH |
570							    sc->tx_start_thresh);
571						}
572					}
573				}
574				outw(BASE + EP_COMMAND, TX_ENABLE);
575				++sc->arpcom.ac_if.if_oerrors;
576			}
577		}
578		epstart(ifp);
579	}
580	goto checkintr;
581}
582
583void
584epread(sc)
585	register struct ep_softc *sc;
586{
587	struct ether_header *eh;
588	struct mbuf *mcur, *m, *m0, *top;
589	int     totlen, lenthisone;
590	int     save_totlen;
591	u_short etype;
592	int     off, resid;
593	int     count, spinwait;
594	int     i;
595
596	totlen = inw(BASE + EP_W1_RX_STATUS);
597	off = 0;
598	top = 0;
599
600	if (totlen & ERR_RX) {
601		++sc->arpcom.ac_if.if_ierrors;
602		goto out;
603	}
604	save_totlen = totlen &= RX_BYTES_MASK;	/* Lower 11 bits = RX bytes. */
605
606	m = sc->mb[sc->next_mb];
607	sc->mb[sc->next_mb] = 0;
608
609	if (m == 0) {
610		MGETHDR(m, M_DONTWAIT, MT_DATA);
611		if (m == 0)
612			goto out;
613	} else {
614		/* Convert one of our saved mbuf's */
615		sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
616		m->m_data = m->m_pktdat;
617		m->m_flags = M_PKTHDR;
618	}
619
620	top = m0 = m;		/* We assign top so we can "goto out" */
621#define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
622#define EOFF    (EROUND - sizeof(struct ether_header))
623	m0->m_data += EOFF;
624	/* Read what should be the header. */
625	insw(BASE + EP_W1_RX_PIO_RD_1,
626	    mtod(m0, caddr_t), sizeof(struct ether_header) / 2);
627	m->m_len = sizeof(struct ether_header);
628	totlen -= sizeof(struct ether_header);
629	/*
630 	 * mostly deal with trailer here.  (untested)
631	 * We do this in a couple of parts.  First we check for a trailer, if
632	 * we have one we convert the mbuf back to a regular mbuf and set the offset and
633	 * subtract sizeof(struct ether_header) from the pktlen.
634	 * After we've read the packet off the interface (all except for the trailer
635	 * header, we then get a header mbuf, read the trailer into it, and fix up
636	 * the mbuf pointer chain.
637	 */
638	eh = mtod(m, struct ether_header *);
639	eh->ether_type = etype = ntohs((u_short) eh->ether_type);
640	if (etype >= ETHERTYPE_TRAIL &&
641	    etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
642		m->m_data = m->m_dat;	/* Convert back to regular mbuf.  */
643		m->m_flags = 0;		/* This sucks but non-trailers are the norm */
644		off = (etype - ETHERTYPE_TRAIL) * 512;
645		if (off >= ETHERMTU) {
646			m_freem(m);
647			return;		/* sanity */
648		}
649		totlen -= sizeof(struct ether_header);	/* We don't read the trailer */
650		m->m_data += 2 * sizeof(u_short);	/* Get rid of type & len */
651	}
652	while (totlen > 0) {
653		lenthisone = min(totlen, M_TRAILINGSPACE(m));
654		if (lenthisone == 0) {	/* no room in this one */
655			mcur = m;
656			m = sc->mb[sc->next_mb];
657			sc->mb[sc->next_mb] = 0;
658			if (!m) {
659				MGET(m, M_DONTWAIT, MT_DATA);
660				if (m == 0)
661					goto out;
662			} else {
663				timeout(epmbufqueue, (caddr_t)sc, 0);
664				sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
665			}
666			if (totlen >= MINCLSIZE)
667				MCLGET(m, M_DONTWAIT);
668			m->m_len = 0;
669			mcur->m_next = m;
670			lenthisone = min(totlen, M_TRAILINGSPACE(m));
671		}
672		insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
673		    lenthisone / 2);
674		m->m_len += lenthisone;
675		if (lenthisone & 1)
676			*(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
677		totlen -= lenthisone;
678	}
679	if (off) {
680		top = sc->mb[sc->next_mb];
681		sc->mb[sc->next_mb] = 0;
682		if (top == 0) {
683			MGETHDR(m, M_DONTWAIT, MT_DATA);
684			if (top == 0)
685				goto out;
686		} else {
687			/* Convert one of our saved mbuf's */
688			sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
689			top->m_data = top->m_pktdat;
690			top->m_flags = M_PKTHDR;
691		}
692		insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
693		    sizeof(struct ether_header));
694		top->m_next = m0;
695		top->m_len = sizeof(struct ether_header);
696		/* XXX Accomodate for type and len from beginning of trailer */
697		top->m_pkthdr.len = save_totlen - (2 * sizeof(u_short));
698	} else {
699		top = m0;
700		top->m_pkthdr.len = save_totlen;
701	}
702
703	top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
704	outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
705	while (inb(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
706		;
707	++sc->arpcom.ac_if.if_ipackets;
708#if NBPFILTER > 0
709	if (sc->bpf) {
710		bpf_mtap(sc->bpf, top);
711
712		/*
713		 * Note that the interface cannot be in promiscuous mode if
714		 * there are no BPF listeners.  And if we are in promiscuous
715		 * mode, we have to check if this packet is really ours.
716		 */
717		if ((sc->ep_ac.ac_if.if_flags & IFF_PROMISC) &&
718		    (eh->ether_dhost[0] & 1) == 0 &&
719		    bcmp(eh->ether_dhost, sc->ep_ac.ac_enaddr,
720			 sizeof(eh->ether_dhost)) != 0 &&
721		    bcmp(eh->ether_dhost, etherbroadcastaddr,
722			 sizeof(eh->ether_dhost)) != 0) {
723			m_freem(top);
724			return;
725		}
726	}
727#endif
728	m_adj(top, sizeof(struct ether_header));
729	ether_input(&sc->arpcom.ac_if, eh, top);
730	return;
731
732out:	outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
733	while (inb(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
734		;
735	if (top)
736		m_freem(top);
737
738	return;
739}
740
741
742/*
743 * Look familiar?
744 */
745static int
746epioctl(ifp, cmd, data)
747	register struct ifnet *ifp;
748	int     cmd;
749	caddr_t data;
750{
751	register struct ifaddr *ifa = (struct ifaddr *) data;
752	struct ep_softc *sc = &ep_softc[ifp->if_unit];
753	struct ifreq *ifr = (struct ifreq *) data;
754	int s, error = 0;
755
756	switch (cmd) {
757	case SIOCSIFADDR:
758		ifp->if_flags |= IFF_UP;
759		switch (ifa->ifa_addr->sa_family) {
760#ifdef INET
761		case AF_INET:
762			epinit(ifp->if_unit);	/* before arpwhohas */
763			((struct arpcom *) ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
764			arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr);
765			break;
766#endif
767#ifdef NS
768		case AF_NS:
769		{
770			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
771
772			if (ns_nullhost(*ina))
773				ina->x_host =
774					*(union ns_host *)(sc->arpcom.ac_enaddr);
775			else {
776				ifp->if_flags &= ~IFF_RUNNING;
777				bcopy((caddr_t) ina->x_host.c_host,
778					(caddr_t)sc->arpcom.ns_addr
779					sizeof(sc->arpcom.ac_enaddr));
780			}
781			epinit(ifp->if_unit);
782			break;
783		}
784#endif
785		default:
786			epinit(ifp->if_unit);
787			break;
788		}
789		break;
790	case SIOCSIFFLAGS:
791		if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
792			ifp->if_flags &= ~IFF_RUNNING;
793			epstop(ifp->if_unit);
794			break;
795		}
796		if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0)
797			epinit(ifp->if_unit);
798		break;
799#ifdef notdef
800	case SIOCGHWADDR:
801		bcopy((caddr_t) sc->sc_addr, (caddr_t) &ifr->ifr_data,
802		    sizeof(sc->sc_addr));
803		break;
804#endif
805	default:
806		error = EINVAL;
807	}
808	return (error);
809}
810
811void
812epreset(unit)
813	int     unit;
814{
815	int s = splimp();
816
817	epstop(unit);
818	epinit(unit);
819	splx(s);
820	return;
821}
822
823void
824epwatchdog(unit)
825	int     unit;
826{
827	struct ep_softc *sc = &ep_softc[unit];
828
829	log(LOG_ERR, "ep%d: watchdog\n", unit);
830	++sc->arpcom.ac_if.if_oerrors;
831
832	epreset(unit);
833}
834
835void
836epstop(unit)
837	int     unit;
838{
839	struct ep_softc *sc = &ep_softc[unit];
840
841	outw(BASE + EP_COMMAND, RX_DISABLE);
842	outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
843	while (inb(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
844		;
845	outw(BASE + EP_COMMAND, TX_DISABLE);
846	outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
847	outw(BASE + EP_COMMAND, RX_RESET);
848	outw(BASE + EP_COMMAND, TX_RESET);
849	outw(BASE + EP_COMMAND, C_INTR_LATCH);
850	outw(BASE + EP_COMMAND, SET_RD_0_MASK);
851	outw(BASE + EP_COMMAND, SET_INTR_MASK);
852	outw(BASE + EP_COMMAND, SET_RX_FILTER);
853	return;
854}
855
856
857/*
858 * This is adapted straight from the book. There's probably a better way.
859 */
860static int
861send_ID_sequence(port)
862	u_short port;
863{
864	char    cx, al;
865
866	cx = 0x0ff;
867	al = 0x0ff;
868
869	outb(port, 0x0);
870	DELAY(1000);
871	outb(port, 0x0);
872	DELAY(1000);
873
874loop1:	cx--;
875	outb(port, al);
876	if (!(al & 0x80)) {
877		al = al << 1;
878		goto loop1;
879	}
880	al = al << 1;
881	al ^= 0xcf;
882	if (cx)
883		goto loop1;
884
885	return(1);
886}
887
888
889/*
890 * We get eeprom data from the id_port given an offset into the
891 * eeprom.  Basically; after the ID_sequence is sent to all of
892 * the cards; they enter the ID_CMD state where they will accept
893 * command requests. 0x80-0xbf loads the eeprom data.  We then
894 * read the port 16 times and with every read; the cards check
895 * for contention (ie: if one card writes a 0 bit and another
896 * writes a 1 bit then the host sees a 0. At the end of the cycle;
897 * each card compares the data on the bus; if there is a difference
898 * then that card goes into ID_WAIT state again). In the meantime;
899 * one bit of data is returned in the AX register which is conveniently
900 * returned to us by inb().  Hence; we read 16 times getting one
901 * bit of data with each read.
902 */
903static u_short
904get_eeprom_data(id_port, offset)
905	int     id_port;
906	int     offset;
907{
908	int     i, data = 0;
909	outb(id_port, 0x80 + offset);
910	DELAY(1000);
911	for (i = 0; i < 16; i++)
912		data = (data << 1) | (inw(id_port) & 1);
913	return (data);
914}
915
916static int
917is_eeprom_busy(is)
918	struct isa_device *is;
919{
920	int     i = 0, j;
921	register struct ep_softc *sc = &ep_softc[is->id_unit];
922
923	while (i++ < 100) {
924		j = inw(BASE + EP_W0_EEPROM_COMMAND);
925		if (j & EEPROM_BUSY)
926			DELAY(100);
927		else
928			break;
929	}
930	if (i >= 100) {
931		printf("\nep%d: eeprom failed to come ready.\n", is->id_unit);
932		return (1);
933	}
934	if (j & EEPROM_TST_MODE) {
935		printf("\nep%d: 3c509 in test mode. Erase pencil mark!\n", is->id_unit);
936		return (1);
937	}
938	return (0);
939}
940
941void
942epmbufqueue(sp, dummy_arg)
943	caddr_t sp;
944	int dummy_arg;
945{
946	struct ep_softc *sc = (struct ep_softc *)sp;
947	int     i;
948
949	if (sc->mb[sc->last_mb])
950		return;
951	i = sc->last_mb;
952	do {
953		MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
954		if (!sc->mb[i])
955			break;
956		i = (i + 1) % MAX_MBS;
957	} while (i != sc->next_mb);
958	sc->last_mb = i;
959	return;
960}
961
962#endif /* NEP > 0 */
963