xref: /openbsd-src/sys/dev/isa/if_ex.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: if_ex.c,v 1.7 2001/06/27 06:34:46 kjc Exp $	*/
2 /*
3  * Copyright (c) 1997, Donald A. Schmidt
4  * Copyright (c) 1996, Javier Mart�n Rueda (jmrueda@diatel.upm.es)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * Intel EtherExpress Pro/10 Ethernet driver
32  *
33  * Revision history:
34  *
35  * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
36  */
37 
38 #include "ex.h"
39 #if NEX > 0
40 #include "bpfilter.h"
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/conf.h>
45 #include <sys/sockio.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/device.h>
49 
50 #include <net/if.h>
51 
52 #ifdef INET
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
55 #endif
56 
57 #ifdef IPX
58 #include <netipx/ipx.h>
59 #include <netipx/ipx_if.h>
60 #endif
61 
62 #ifdef NS
63 #include <netns/ns.h>
64 #include <netns/ns_if.h>
65 #endif
66 
67 #if NBPFILTER > 0
68 #include <net/bpf.h>
69 #endif
70 
71 #include <machine/cpu.h>
72 #include <machine/bus.h>
73 
74 #include <dev/isa/isavar.h>
75 #include <dev/isa/if_exreg.h>
76 
77 
78 #ifdef EXDEBUG
79 #define Start_End 1
80 #define Rcvd_Pkts 2
81 #define Sent_Pkts 4
82 #define Status    8
83 static int debug_mask = 0;
84 static int exintr_count = 0;
85 #define DODEBUG(level, action) if (level & debug_mask) action
86 #else
87 #define DODEBUG(level, action)
88 #endif
89 
90 
91 #define Conn_BNC 1
92 #define Conn_TPE 2
93 #define Conn_AUI 3
94 
95 struct ex_softc {
96   	struct arpcom arpcom;	/* Ethernet common data */
97 	int iobase;		/* I/O base address. */
98 	u_short connector;	/* Connector type. */
99 	u_short irq_no; 	/* IRQ number. */
100 	u_int mem_size;		/* Total memory size, in bytes. */
101 	u_int rx_mem_size;	/* Rx memory size (by default, first 3/4 of
102 				   total memory). */
103   	u_int rx_lower_limit,
104 	      rx_upper_limit; 	/* Lower and upper limits of receive buffer. */
105   	u_int rx_head; 		/* Head of receive ring buffer. */
106 	u_int tx_mem_size;	/* Tx memory size (by default, last quarter of
107 				   total memory). */
108   	u_int tx_lower_limit,
109 	      tx_upper_limit;	/* Lower and upper limits of transmit buffer. */
110   	u_int tx_head, tx_tail; /* Head and tail of transmit ring buffer. */
111   	u_int tx_last; 		/* Pointer to beginning of last frame in the
112 				   chain. */
113 	bus_space_tag_t sc_iot;	/* ISA i/o space tag */
114 	bus_space_handle_t sc_ioh; /* ISA i/o space handle */
115 	void *sc_ih;		/* Device interrupt handler */
116 };
117 
118 /* static struct ex_softc ex_sc[NEX]; XXX would it be better to malloc(3)
119 					the memory? */
120 
121 static char irq2eemap[] = { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1,
122 			    -1, -1 };
123 static u_char ee2irqmap[] = { 9, 3, 5, 10, 11, 0, 0, 0 };
124 
125 static int ex_probe __P((struct device *, void *, void *));
126 static void ex_attach __P((struct device *, struct device *, void *));
127 static void ex_init __P((struct ex_softc *));
128 static void ex_start __P((struct ifnet *));
129 static void ex_stop __P((struct ex_softc *));
130 static int ex_ioctl __P((struct ifnet *, u_long, caddr_t));
131 static void ex_reset __P((struct ex_softc *));
132 static void ex_watchdog __P((struct ifnet *));
133 
134 static u_short eeprom_read __P((struct ex_softc *, int));
135 static int look_for_card __P((struct isa_attach_args *, struct ex_softc *sc));
136 static int exintr __P((void *));
137 static void ex_tx_intr __P((struct ex_softc *));
138 static void ex_rx_intr __P((struct ex_softc *));
139 
140 
141 struct cfattach ex_ca = {
142 	sizeof(struct ex_softc), ex_probe, ex_attach
143 };
144 
145 struct cfdriver ex_cd = {
146 	NULL, "ex", DV_IFNET
147 };
148 
149 #define BANK_SEL(X) bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMD_REG, \
150 	(X))
151 #define ISA_GET(offset) bus_space_read_1(sc->sc_iot, sc->sc_ioh, (offset))
152 #define ISA_PUT(offset, value) bus_space_write_1(sc->sc_iot, sc->sc_ioh, \
153  	(offset), (value))
154 #define ISA_GET_2(offset) bus_space_read_2(sc->sc_iot, sc->sc_ioh, \
155 	(offset))
156 #define ISA_PUT_2(offset, value) bus_space_write_2(sc->sc_iot, sc->sc_ioh, \
157 	(offset), (value))
158 #define ISA_GET_2_MULTI(offset, addr, count) bus_space_read_multi_2( \
159 	sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
160 #define ISA_PUT_2_MULTI(offset, addr, count) bus_space_write_multi_2( \
161 	sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
162 
163 
164 static int
165 look_for_card(ia, sc)
166 	struct isa_attach_args *ia;
167 	struct ex_softc *sc;
168 {
169 	int count1, count2;
170 
171 	/*
172 	 * Check for the i82595 signature, and check that the round robin
173 	 * counter actually advances.
174 	 */
175 	if (((count1 = ISA_GET(ID_REG)) & Id_Mask) != Id_Sig)
176 		return(0);
177 	count2 = ISA_GET(ID_REG);
178 	count2 = ISA_GET(ID_REG);
179 	count2 = ISA_GET(ID_REG);
180 	if ((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits))
181 		return(1);
182 	else
183 		return(0);
184 }
185 
186 
187 int
188 ex_probe(parent, match, aux)
189 	struct device *parent;
190 	void *match, *aux;
191 {
192 	struct ex_softc *sc = match;
193 	struct isa_attach_args *ia = aux;
194 	u_short eaddr_tmp;
195 	int tmp;
196 
197 	DODEBUG(Start_End, printf("ex_probe: start\n"););
198 
199 	if ((ia->ia_iobase >= 0x200) && (ia->ia_iobase <= 0x3a0)) {
200 		sc->sc_iot = ia->ia_iot;
201 		if(bus_space_map(sc->sc_iot, ia->ia_iobase, EX_IOSIZE, 0,
202 		    &sc->sc_ioh))
203 			return(0);
204 
205 		if (!look_for_card(ia, sc)) {
206 			bus_space_unmap(sc->sc_iot, sc->sc_ioh, EX_IOSIZE);
207 			return(0);
208 		}
209 	} else
210 		return(0);
211 
212 	ia->ia_iosize = EX_IOSIZE;
213 
214 	/*
215 	 * Reset the card.
216 	 */
217 	ISA_PUT(CMD_REG, Reset_CMD);
218 	delay(200);
219 
220 	/*
221 	 * Fill in several fields of the softc structure:
222 	 *	- I/O base address.
223 	 *	- Hardware Ethernet address.
224 	 *	- IRQ number (if not supplied in config file, read it from
225 	 *	  EEPROM).
226 	 *	- Connector type.
227 	 */
228 	sc->iobase = ia->ia_iobase;
229 	eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Lo);
230 	sc->arpcom.ac_enaddr[5] = eaddr_tmp & 0xff;
231 	sc->arpcom.ac_enaddr[4] = eaddr_tmp >> 8;
232 	eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Mid);
233 	sc->arpcom.ac_enaddr[3] = eaddr_tmp & 0xff;
234 	sc->arpcom.ac_enaddr[2] = eaddr_tmp >> 8;
235 	eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Hi);
236 	sc->arpcom.ac_enaddr[1] = eaddr_tmp & 0xff;
237 	sc->arpcom.ac_enaddr[0] = eaddr_tmp >> 8;
238 	tmp = eeprom_read(sc, EE_IRQ_No) & IRQ_No_Mask;
239 	if (ia->ia_irq > 0) {
240 		if (ee2irqmap[tmp] != ia->ia_irq)
241 			printf("ex: WARING: board's EEPROM is configured for IRQ %d, using %d\n", ee2irqmap[tmp], ia->ia_irq);
242 		sc->irq_no = ia->ia_irq;
243 	}
244 	else {
245 		sc->irq_no = ee2irqmap[tmp];
246 		ia->ia_irq = sc->irq_no;
247 	}
248 	if (sc->irq_no == 0) {
249 		printf("ex: invalid IRQ.\n");
250 		return(0);
251 	}
252 	BANK_SEL(Bank2_Sel);
253 	tmp = ISA_GET(REG3);
254 	if (tmp & TPE_bit)
255 		sc->connector = Conn_TPE;
256 	else if (tmp & BNC_bit)
257 		sc->connector = Conn_BNC;
258 	else
259 		sc->connector = Conn_AUI;
260 	sc->mem_size = CARD_RAM_SIZE;	/* XXX This should be read from the card
261 					       itself. */
262 
263 	BANK_SEL(Bank0_Sel);
264 
265 	DODEBUG(Start_End, printf("ex_probe: finish\n"););
266 	return(1);
267 }
268 
269 
270 void
271 ex_attach(parent, self, aux)
272 	struct device *parent, *self;
273 	void *aux;
274 {
275 	struct ex_softc *sc = (void *)self;
276 	struct isa_attach_args *ia = aux;
277 	struct ifnet *ifp = &sc->arpcom.ac_if;
278 
279 	/* struct ifaddr *ifa; 	XXX what are these for? */
280 	/* struct sockaddr_dl *sdl; */
281 
282 	DODEBUG(Start_End, printf("ex_attach: start\n"););
283 
284 	/*
285 	 * Initialize the ifnet structure.
286 
287 	 */
288 	ifp->if_softc = sc;
289 	bcopy(self->dv_xname, ifp->if_xname, IFNAMSIZ);
290 	ifp->if_output = ether_output;
291 	ifp->if_start = ex_start;
292 	ifp->if_ioctl = ex_ioctl;
293 	ifp->if_watchdog = ex_watchdog;
294 	ifp->if_mtu = ETHERMTU;
295 	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; /* XXX not done yet.
296 						       | IFF_MULTICAST */
297 	IFQ_SET_READY(&ifp->if_snd);
298 
299 	/*
300 	 * Attach the interface.
301 	 */
302 	if_attach(ifp);
303 	ether_ifattach(ifp);
304 	printf(": address %s, connecter ",
305 	    ether_sprintf(sc->arpcom.ac_enaddr));
306 	switch(sc->connector) {
307 		case Conn_TPE: printf("TPE\n"); break;
308 		case Conn_BNC: printf("BNC\n"); break;
309 		case Conn_AUI: printf("AUI\n"); break;
310 		default: printf("???\n");
311 	}
312 
313 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
314 	    IPL_NET, exintr, sc, self->dv_xname);
315 	ex_init(sc);
316 
317 	DODEBUG(Start_End, printf("ex_attach: finish\n"););
318 }
319 
320 
321 void
322 ex_init(sc)
323 	struct ex_softc *sc;
324 {
325 	struct ifnet *ifp = &sc->arpcom.ac_if;
326 	int s, i;
327 	unsigned short temp_reg;
328 
329 	DODEBUG(Start_End, printf("ex_init: start\n"););
330 
331 	if (ifp->if_addrlist.tqh_first == NULL)
332 		return;
333 	s = splimp();
334 	sc->arpcom.ac_if.if_timer = 0;
335 
336 	/*
337 	 * Load the ethernet address into the card.
338 	 */
339 	BANK_SEL(Bank2_Sel);
340 	temp_reg = ISA_GET(EEPROM_REG);
341 	if (temp_reg & Trnoff_Enable)
342 		ISA_PUT(EEPROM_REG, temp_reg & ~Trnoff_Enable);
343 	for (i = 0; i < ETHER_ADDR_LEN; i++)
344 		ISA_PUT(I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
345 	/*
346 	 * - Setup transmit chaining and discard bad received frames.
347 	 * - Match broadcast.
348 	 * - Clear test mode.
349 	 * - Set receiving mode.
350 	 * - Set IRQ number.
351 	 */
352 	ISA_PUT(REG1, ISA_GET(REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp |
353 	    Disc_Bad_Fr);
354 	ISA_PUT(REG2, ISA_GET(REG2) | No_SA_Ins | RX_CRC_InMem);
355 	ISA_PUT(REG3, (ISA_GET(REG3) & 0x3f));
356 	BANK_SEL(Bank1_Sel);
357 	ISA_PUT(INT_NO_REG, (ISA_GET(INT_NO_REG) & 0xf8) |
358 	    irq2eemap[sc->irq_no]);
359 
360 	/*
361 	 * Divide the available memory in the card into rcv and xmt buffers.
362 	 * By default, I use the first 3/4 of the memory for the rcv buffer,
363 	 * and the remaining 1/4 of the memory for the xmt buffer.
364 	 */
365 	sc->rx_mem_size = sc->mem_size * 3 / 4;
366 	sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
367 	sc->rx_lower_limit = 0x0000;
368 	sc->rx_upper_limit = sc->rx_mem_size - 2;
369 	sc->tx_lower_limit = sc->rx_mem_size;
370 	sc->tx_upper_limit = sc->mem_size - 2;
371  	ISA_PUT(RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
372         ISA_PUT(RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
373         ISA_PUT(XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
374 	ISA_PUT(XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
375 
376 	/*
377 	 * Enable receive and transmit interrupts, and clear any pending int.
378 	 */
379 	ISA_PUT(REG1, ISA_GET(REG1) | TriST_INT);
380 	BANK_SEL(Bank0_Sel);
381 	ISA_PUT(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
382 	ISA_PUT(STATUS_REG, All_Int);
383 
384 	/*
385 	 * Initialize receive and transmit ring buffers.
386 	 */
387 	ISA_PUT_2(RCV_BAR, sc->rx_lower_limit);
388 	sc->rx_head = sc->rx_lower_limit;
389 	ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
390 	ISA_PUT_2(XMT_BAR, sc->tx_lower_limit);
391 	sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
392 
393 	ifp->if_flags |= IFF_RUNNING;
394 	ifp->if_flags &= ~IFF_OACTIVE;
395 	DODEBUG(Status, printf("OIDLE init\n"););
396 
397 	/*
398 	 * Final reset of the board, and enable operation.
399 	 */
400 	ISA_PUT(CMD_REG, Sel_Reset_CMD);
401 	delay(2);
402 	ISA_PUT(CMD_REG, Rcv_Enable_CMD);
403 
404 	ex_start(ifp);
405 	splx(s);
406 
407 	DODEBUG(Start_End, printf("ex_init: finish\n"););
408 }
409 
410 
411 void
412 ex_start(ifp)
413 	struct ifnet *ifp;
414 {
415 	register struct ex_softc *sc = ifp->if_softc;
416 	int i, s, len, data_len, avail, dest, next;
417 	unsigned char tmp16[2];
418 	struct mbuf *opkt;
419 	register struct mbuf *m;
420 
421 	DODEBUG(Start_End, printf("ex_start: start\n"););
422 
423 	s = splimp();
424 
425 	/*
426  	 * Main loop: send outgoing packets to network card until there are no
427  	 * more packets left, or the card cannot accept any more yet.
428  	 */
429 	while (!(ifp->if_flags & IFF_OACTIVE)) {
430 		IFQ_POLL(&ifp->if_snd, opkt);
431 		if (opkt == NULL)
432 			break;
433 
434 		/*
435 		 * Ensure there is enough free transmit buffer space for this
436 		 * packet, including its header. Note: the header cannot wrap
437 		 * around the end of the transmit buffer and must be kept
438 		 * together, so we allow space for twice the length of the
439 		 * header, just in case.
440 		 */
441 		for (len = 0, m = opkt; m != NULL; m = m->m_next)
442  			len += m->m_len;
443     		data_len = len;
444    		DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
445 		if (len & 1)
446    			len += XMT_HEADER_LEN + 1;
447 		else
448 			len += XMT_HEADER_LEN;
449 		if ((i = sc->tx_tail - sc->tx_head) >= 0)
450 			avail = sc->tx_mem_size - i;
451 		else
452 			avail = -i;
453 		DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
454     		if (avail >= len + XMT_HEADER_LEN) {
455       			IFQ_DEQUEUE(&ifp->if_snd, opkt);
456 
457 #ifdef EX_PSA_INTR
458 			/*
459  			 * Disable rx and tx interrupts, to avoid corruption of
460 			 * the host address register by interrupt service
461 			 * routines. XXX Is this necessary with splimp()
462 			 * enabled?
463 			 */
464 			ISA_WRITE(MASK_REG, All_Int);
465 #endif
466 
467       			/*
468 			 * Compute the start and end addresses of this frame
469 			 * in the tx buffer.
470 			 */
471       			dest = sc->tx_tail;
472 			next = dest + len;
473 			if (next > sc->tx_upper_limit) {
474 				if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
475 				    XMT_HEADER_LEN) {
476 	  				dest = sc->tx_lower_limit;
477 	  				next = dest + len;
478 				} else
479 	  				next = sc->tx_lower_limit + next -
480 					    sc->tx_upper_limit - 2;
481       			}
482 
483 			/* Build the packet frame in the card's ring buffer. */
484 			DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
485 			ISA_PUT_2(HOST_ADDR_REG, dest);
486 			ISA_PUT_2(IO_PORT_REG, Transmit_CMD);
487 			ISA_PUT_2(IO_PORT_REG, 0);
488 			ISA_PUT_2(IO_PORT_REG, next);
489 			ISA_PUT_2(IO_PORT_REG, data_len);
490 
491 			/*
492  			 * Output the packet data to the card. Ensure all
493 			 * transfers are 16-bit wide, even if individual mbufs
494 			 * have odd length.
495 			 */
496 
497 			for (m = opkt, i = 0; m != NULL; m = m->m_next) {
498 				DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
499 				if (i) {
500 					tmp16[1] = *(mtod(m, caddr_t));
501 					ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
502 				}
503 				ISA_PUT_2_MULTI(IO_PORT_REG, mtod(m, caddr_t)
504 				    + i, (m->m_len - i) / 2);
505 				if ((i = (m->m_len - i) & 1))
506 					tmp16[0] = *(mtod(m, caddr_t) +
507 					    m->m_len - 1);
508 			}
509 			if (i)
510 				ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
511 
512       			/*
513 			 * If there were other frames chained, update the
514 			 * chain in the last one.
515 			 */
516 			if (sc->tx_head != sc->tx_tail) {
517 				if (sc->tx_tail != dest) {
518 					ISA_PUT_2(HOST_ADDR_REG,
519 					    sc->tx_last + XMT_Chain_Point);
520 					ISA_PUT_2(IO_PORT_REG, dest);
521 				}
522 				ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
523 				    XMT_Byte_Count);
524 				i = ISA_GET_2(IO_PORT_REG);
525 				ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
526 				    XMT_Byte_Count);
527 				ISA_PUT_2(IO_PORT_REG, i | Ch_bit);
528       			}
529 
530       			/*
531 			 * Resume normal operation of the card:
532 			 * -Make a dummy read to flush the DRAM write pipeline.
533 			 * -Enable receive and transmit interrupts.
534 			 * -Send Transmit or Resume_XMT command, as appropriate.
535 			 */
536 			ISA_GET_2(IO_PORT_REG);
537 #ifdef EX_PSA_INTR
538 			ISA_PUT_2(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
539 #endif
540 			if (sc->tx_head == sc->tx_tail) {
541 				ISA_PUT_2(XMT_BAR, dest);
542 				ISA_PUT(CMD_REG, Transmit_CMD);
543 				sc->tx_head = dest;
544 				DODEBUG(Sent_Pkts, printf("Transmit\n"););
545 			} else {
546 				ISA_PUT(CMD_REG, Resume_XMT_List_CMD);
547 				DODEBUG(Sent_Pkts, printf("Resume\n"););
548 			}
549 			sc->tx_last = dest;
550 			sc->tx_tail = next;
551 #if NBPFILTER > 0
552 			if (ifp->if_bpf != NULL)
553 				bpf_mtap(ifp->if_bpf, opkt);
554 #endif
555 			ifp->if_timer = 2;
556 			ifp->if_opackets++;
557 			m_freem(opkt);
558 		} else {
559 			ifp->if_flags |= IFF_OACTIVE;
560 			DODEBUG(Status, printf("OACTIVE start\n"););
561 		}
562 	}
563 
564 	splx(s);
565 
566 	DODEBUG(Start_End, printf("ex_start: finish\n"););
567 }
568 
569 
570 void
571 ex_stop(sc)
572 	struct ex_softc *sc;
573 {
574 	DODEBUG(Start_End, printf("ex_stop: start\n"););
575 
576 	/*
577 	 * Disable card operation:
578  	 * - Disable the interrupt line.
579 	 * - Flush transmission and disable reception.
580 	 * - Mask and clear all interrupts.
581   	 * - Reset the 82595.
582 	 */
583 	BANK_SEL(Bank1_Sel);
584 	ISA_PUT(REG1, ISA_GET(REG1) & ~TriST_INT);
585 	BANK_SEL(Bank0_Sel);
586 	ISA_PUT(CMD_REG, Rcv_Stop);
587 	sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
588 	sc->tx_last = 0; /* XXX I think these two lines are not necessary,
589 				because ex_init will always be called again
590 				to reinit the interface. */
591 	ISA_PUT(MASK_REG, All_Int);
592 	ISA_PUT(STATUS_REG, All_Int);
593 	ISA_PUT(CMD_REG, Reset_CMD);
594 	delay(200);
595 
596 	DODEBUG(Start_End, printf("ex_stop: finish\n"););
597 }
598 
599 
600 int
601 exintr(arg)
602 	void *arg;
603 {
604 	struct ex_softc *sc = arg;
605 	struct ifnet *ifp = &sc->arpcom.ac_if;
606 	int int_status, send_pkts;
607 	int handled;
608 
609 	DODEBUG(Start_End, printf("exintr: start\n"););
610 
611 #ifdef EXDEBUG
612 	if (++exintr_count != 1)
613 		printf("WARNING: nested interrupt (%d). Mail the author.\n",
614 	 	    exintr_count);
615 #endif
616 
617 	send_pkts = 0;
618 	while ((int_status = ISA_GET(STATUS_REG)) & (Tx_Int | Rx_Int)) {
619 		if (int_status & Rx_Int) {
620 			ISA_PUT(STATUS_REG, Rx_Int);
621 			handled = 1;
622 			ex_rx_intr(sc);
623 		} else if (int_status & Tx_Int) {
624 			ISA_PUT(STATUS_REG, Tx_Int);
625 			handled = 1;
626 			ex_tx_intr(sc);
627 			send_pkts = 1;
628   		} else
629 			handled = 0;
630    	}
631 
632   	/*
633 	 * If any packet has been transmitted, and there are queued packets to
634  	 * be sent, attempt to send more packets to the network card.
635 	 */
636 
637 	if (send_pkts && IFQ_IS_EMPTY(&ifp->if_snd) == 0)
638 		ex_start(ifp);
639 #ifdef EXDEBUG
640 	exintr_count--;
641 #endif
642 	DODEBUG(Start_End, printf("exintr: finish\n"););
643 
644 	return handled;
645 }
646 
647 
648 void
649 ex_tx_intr(sc)
650 	struct ex_softc *sc;
651 {
652 	register struct ifnet *ifp = &sc->arpcom.ac_if;
653 	int tx_status;
654 
655 	DODEBUG(Start_End, printf("ex_tx_intr: start\n"););
656 	/*
657 	 * - Cancel the watchdog.
658 	 * For all packets transmitted since last transmit interrupt:
659 	 * - Advance chain pointer to next queued packet.
660 	 * - Update statistics.
661 	 */
662 	ifp->if_timer = 0;
663 	while (sc->tx_head != sc->tx_tail) {
664 		ISA_PUT_2(HOST_ADDR_REG, sc->tx_head);
665 		if (! ISA_GET_2(IO_PORT_REG) & Done_bit)
666 			break;
667 		tx_status = ISA_GET_2(IO_PORT_REG);
668 		sc->tx_head = ISA_GET_2(IO_PORT_REG);
669 		if (tx_status & TX_OK_bit)
670 			ifp->if_opackets++;
671 		else
672 			ifp->if_oerrors++;
673 		ifp->if_collisions += tx_status & No_Collisions_bits;
674 	}
675 
676 	/* The card should be ready to accept more packets now. */
677 	ifp->if_flags &= ~IFF_OACTIVE;
678 	DODEBUG(Status, printf("OIDLE tx_intr\n"););
679 
680 	DODEBUG(Start_End, printf("ex_tx_intr: finish\n"););
681 }
682 
683 
684 void
685 ex_rx_intr(sc)
686 	struct ex_softc *sc;
687 {
688 	register struct ifnet *ifp = &sc->arpcom.ac_if;
689 	int rx_status, pkt_len, QQQ;
690 	register struct mbuf *m, *ipkt;
691 	struct ether_header *eh;
692 
693 	DODEBUG(Start_End, printf("ex_rx_intr: start\n"););
694 	/*
695 	 * For all packets received since last receive interrupt:
696 	 * - If packet ok, read it into a new mbuf and queue it to interface,
697 	 *   updating statistics.
698 	 * - If packet bad, just discard it, and update statistics.
699 	 * Finally, advance receive stop limit in card's memory to new location.
700 	 */
701 	ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
702 	while (ISA_GET_2(IO_PORT_REG) == RCV_Done) {
703 		rx_status = ISA_GET_2(IO_PORT_REG);
704 		sc->rx_head = ISA_GET_2(IO_PORT_REG);
705 		QQQ = pkt_len = ISA_GET_2(IO_PORT_REG);
706 		if (rx_status & RCV_OK_bit) {
707 			MGETHDR(m, M_DONTWAIT, MT_DATA);
708 			ipkt = m;
709 			if (ipkt == NULL)
710 				ifp->if_iqdrops++;
711 			else {
712 				ipkt->m_pkthdr.rcvif = ifp;
713 				ipkt->m_pkthdr.len = pkt_len;
714 				ipkt->m_len = MHLEN;
715 				while (pkt_len > 0) {
716 					if (pkt_len > MINCLSIZE) {
717 						MCLGET(m, M_DONTWAIT);
718 						if (m->m_flags & M_EXT)
719 							m->m_len = MCLBYTES;
720 						else {
721 							m_freem(ipkt);
722 							ifp->if_iqdrops++;
723 							goto rx_another;
724 						}
725 					}
726 					m->m_len = min(m->m_len, pkt_len);
727 					/*
728 					 * NOTE: I'm assuming that all mbufs
729 					 * allocated are of even length, except
730 					 * for the last one in an odd-length
731 					 * packet.
732 					 */
733 					ISA_GET_2_MULTI(IO_PORT_REG,
734 					    mtod(m, caddr_t), m->m_len / 2);
735 					if (m->m_len & 1)
736 						*(mtod(m, caddr_t) +
737 						    m->m_len - 1) =
738 						    ISA_GET(IO_PORT_REG);
739 					pkt_len -= m->m_len;
740 					if (pkt_len > 0) {
741 						MGET(m->m_next, M_DONTWAIT,
742 						    MT_DATA);
743 					if (m->m_next == NULL) {
744 						m_freem(ipkt);
745 						ifp->if_iqdrops++;
746 						goto rx_another;
747 					}
748 					m = m->m_next;
749 					m->m_len = MLEN;
750 				}
751 			}
752 			eh = mtod(ipkt, struct ether_header *);
753 #ifdef EXDEBUG
754 			if (debug_mask & Rcvd_Pkts) {
755 				if ((eh->ether_dhost[5] != 0xff) ||
756 				    (eh->ether_dhost[0] != 0xff)) {
757 					printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
758 					printf("%6D\n", eh->ether_dhost, ":");
759 				} /* QQQ */
760 			}
761 #endif
762 #if NBPFILTER > 0
763 			if (ifp->if_bpf != NULL)
764 				bpf_mtap(ifp->if_bpf, ipkt);
765 #endif
766 			m_adj(ipkt, sizeof(struct ether_header));
767 			ether_input(ifp, eh, ipkt);
768 			ifp->if_ipackets++;
769       		}
770     	} else
771       		ifp->if_ierrors++;
772 		ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
773 		rx_another: ;
774   	}
775 	if (sc->rx_head < sc->rx_lower_limit + 2)
776 		ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit);
777 	else
778 		ISA_PUT_2(RCV_STOP_REG, sc->rx_head - 2);
779 
780 	DODEBUG(Start_End, printf("ex_rx_intr: finish\n"););
781 }
782 
783 
784 int
785 ex_ioctl(ifp, cmd, data)
786 	register struct ifnet *ifp;
787 	u_long cmd;
788 	caddr_t data;
789 {
790 	register struct ifaddr *ifa = (struct ifaddr *) data;
791 	struct ex_softc *sc = ifp->if_softc;
792 	struct ifreq *ifr = (struct ifreq *) data;
793 	int s, error = 0;
794 
795 	DODEBUG(Start_End, printf("ex_ioctl: start "););
796 
797 	s = splimp();
798 
799 	switch(cmd) {
800 		case SIOCSIFADDR:
801 			DODEBUG(Start_End, printf("SIOCSIFADDR"););
802 			ifp->if_flags |= IFF_UP;
803 
804 			switch(ifa->ifa_addr->sa_family) {
805 #ifdef INET
806 				case AF_INET:
807 					ex_init(sc);
808 					arp_ifinit((struct arpcom *) ifp, ifa);
809 					break;
810 #endif
811 #ifdef IPX_NOTYET
812 				case AF_IPX:
813 				{
814 					register struct ipx_addr *ina =
815 					    &(IA_SIPX(ifa)->sipx_addr);
816 
817 					if (ipx_nullhost(*ina))
818 					ina->x_host = *(union ipx_host *)
819 					    (sc->arpcom.ac_enaddr);
820 					else {
821 	  					ifp->if_flags &= ~IFF_RUNNING;
822 	  					bcopy((caddr_t)
823 						    ina->x_host.c_host,
824 						    (caddr_t)
825 						    sc->arpcom.ac_enaddr,
826 						    sizeof(sc->arpcom.ac_enaddr)
827 						    );
828 					}
829 					ex_init(sc);
830 					break;
831      				}
832 #endif
833 #ifdef NS
834 				case AF_NS:
835       				{
836 	register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
837 
838 	if (ns_nullhost(*ina))
839 	  ina->x_host = *(union ns_host *) (sc->arpcom.ac_enaddr);
840 	else {
841 	  ifp->if_flags &= ~IFF_RUNNING;
842 	  bcopy((caddr_t) ina->x_host.c_host, (caddr_t) sc->arpcom.ac_enaddr,
843 		sizeof(sc->arpcom.ac_enaddr));
844 	}
845 	ex_init(sc);
846 	break;
847       }
848 #endif
849     default:
850       ex_init(sc);
851       break;
852     }
853     break;
854   case SIOCGIFADDR:
855     {
856       struct sockaddr *sa;
857 
858       DODEBUG(Start_End, printf("SIOCGIFADDR"););
859       sa = (struct sockaddr *) &ifr->ifr_data;
860       bcopy((caddr_t) sc->arpcom.ac_enaddr, (caddr_t) sa->sa_data,
861 	    ETHER_ADDR_LEN);
862     }
863   break;
864   case SIOCSIFFLAGS:
865     DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
866     if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
867       ifp->if_flags &= ~IFF_RUNNING;
868       ex_stop(sc);
869     }
870     else
871       ex_init(sc);
872     break;
873 #ifdef NODEF
874   case SIOCGHWADDR:
875     DODEBUG(Start_End, printf("SIOCGHWADDR"););
876     bcopy((caddr_t) sc->sc_addr, (caddr_t) &ifr->ifr_data, sizeof(sc->sc_addr));
877     break;
878 #endif
879 #if 0						/* XXX can we do this? */
880   case SIOCSIFMTU:
881     DODEBUG(Start_End, printf("SIOCSIFMTU"););
882     if (ifr->if_mtu > ETHERMTU)
883       error = EINVAL;
884     else
885       ifp->if_mtu = ifr->ifr_mtu;
886     break;
887 #endif
888   case SIOCADDMULTI:
889     DODEBUG(Start_End, printf("SIOCADDMULTI"););
890   case SIOCDELMULTI:
891     DODEBUG(Start_End, printf("SIOCDELMULTI"););
892     /* XXX Support not done yet. */
893     error = EINVAL;
894     break;
895   default:
896     DODEBUG(Start_End, printf("unknown"););
897     error = EINVAL;
898   }
899 
900   splx(s);
901 
902   DODEBUG(Start_End, printf("\nex_ioctl: finish\n"););
903   return(error);
904 }
905 
906 
907 void
908 ex_reset(sc)
909 	struct ex_softc *sc;
910 {
911 	int s;
912 
913 	DODEBUG(Start_End, printf("ex_reset: start\n"););
914 
915 	s = splimp();
916 	ex_stop(sc);
917 	ex_init(sc);
918 	splx(s);
919 
920 	DODEBUG(Start_End, printf("ex_reset: finish\n"););
921 }
922 
923 
924 void
925 ex_watchdog(ifp)
926 	struct ifnet *ifp;
927 {
928 	struct ex_softc *sc = ifp->if_softc;
929 
930 	DODEBUG(Start_End, printf("ex_watchdog: start\n"););
931 
932 	ifp->if_flags &= ~IFF_OACTIVE;
933 	DODEBUG(Status, printf("OIDLE watchdog\n"););
934 	ifp->if_oerrors++;
935 	ex_reset(sc);
936 	ex_start(ifp);
937 
938 	DODEBUG(Start_End, printf("ex_watchdog: finish\n"););
939 }
940 
941 
942 static u_short
943 eeprom_read(sc, location)
944 	struct ex_softc *sc;
945 	int location;
946 {
947 	int i;
948 	u_short data = 0;
949 	int read_cmd = location | EE_READ_CMD;
950 	short ctrl_val = EECS;
951 
952 	BANK_SEL(Bank2_Sel);
953 	ISA_PUT(EEPROM_REG, EECS);
954 	for (i = 8; i >= 0; i--) {
955 		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI :
956 		    ctrl_val;
957 		ISA_PUT(EEPROM_REG, outval);
958 		ISA_PUT(EEPROM_REG, outval | EESK);
959 		delay(3);
960 		ISA_PUT(EEPROM_REG, outval);
961 		delay(2);
962 	}
963 	ISA_PUT(EEPROM_REG, ctrl_val);
964 	for (i = 16; i > 0; i--) {
965 		ISA_PUT(EEPROM_REG, ctrl_val | EESK);
966 		delay(3);
967 		data = (data << 1) | ((ISA_GET(EEPROM_REG) & EEDO) ? 1 : 0);
968 		ISA_PUT(EEPROM_REG, ctrl_val);
969 		delay(2);
970 	}
971 	ctrl_val &= ~EECS;
972 	ISA_PUT(EEPROM_REG, ctrl_val | EESK);
973 	delay(3);
974 	ISA_PUT(EEPROM_REG, ctrl_val);
975 	delay(2);
976 	BANK_SEL(Bank0_Sel);
977 	return(data);
978 }
979 
980 #endif /* NEX > 0 */
981