if_ex.c revision 148654
122347Spst/*-
222347Spst * Copyright (c) 1996, Javier Mart�n Rueda (jmrueda@diatel.upm.es)
329967Sache * All rights reserved.
492914Smarkm *
522347Spst * Redistribution and use in source and binary forms, with or without
622347Spst * modification, are permitted provided that the following conditions
722347Spst * are met:
822347Spst * 1. Redistributions of source code must retain the above copyright
922347Spst *    notice unmodified, this list of conditions, and the following
1022347Spst *    disclaimer.
1122347Spst * 2. Redistributions in binary form must reproduce the above copyright
1222347Spst *    notice, this list of conditions and the following disclaimer in the
1322347Spst *    documentation and/or other materials provided with the distribution.
1422347Spst *
1522347Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1622347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1722347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1822347Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1922347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2022347Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2122347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2259121Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2322347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2422347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2522347Spst * SUCH DAMAGE.
2622347Spst *
2722347Spst *
2822347Spst * MAINTAINER: Matthew N. Dodd <winter@jurai.net>
2922347Spst *                             <mdodd@FreeBSD.org>
3022347Spst */
3122347Spst
3222347Spst#include <sys/cdefs.h>
3322347Spst__FBSDID("$FreeBSD: head/sys/dev/ex/if_ex.c 148654 2005-08-03 00:18:35Z rwatson $");
3422347Spst
3522347Spst/*
3622347Spst * Intel EtherExpress Pro/10, Pro/10+ Ethernet driver
3722347Spst *
3822347Spst * Revision history:
3922347Spst *
4022347Spst * dd-mmm-yyyy: Multicast support ported from NetBSD's if_iy driver.
4122347Spst * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
4222347Spst */
4322347Spst
4422347Spst#include <sys/param.h>
4522347Spst#include <sys/systm.h>
4622347Spst#include <sys/kernel.h>
4722347Spst#include <sys/sockio.h>
4822347Spst#include <sys/mbuf.h>
4922347Spst#include <sys/socket.h>
5022347Spst
5122347Spst#include <sys/module.h>
5222347Spst#include <sys/bus.h>
5322347Spst
5422347Spst#include <machine/bus.h>
5522347Spst#include <machine/resource.h>
5622347Spst#include <sys/rman.h>
5722347Spst
5822347Spst#include <net/if.h>
5922347Spst#include <net/if_arp.h>
6022347Spst#include <net/if_dl.h>
6122347Spst#include <net/if_media.h>
6222347Spst#include <net/if_types.h>
6322347Spst#include <net/ethernet.h>
6422347Spst#include <net/bpf.h>
6522347Spst
6622347Spst#include <netinet/in.h>
6722347Spst#include <netinet/if_ether.h>
6822347Spst
6922347Spst
7022347Spst#include <isa/isavar.h>
7122347Spst#include <isa/pnpvar.h>
7222347Spst
7322347Spst#include <dev/ex/if_exreg.h>
7422347Spst#include <dev/ex/if_exvar.h>
7522347Spst
7622347Spst#ifdef EXDEBUG
7722347Spst# define Start_End 1
7822347Spst# define Rcvd_Pkts 2
7922347Spst# define Sent_Pkts 4
8022347Spst# define Status    8
8122347Spststatic int debug_mask = 0;
8222347Spst# define DODEBUG(level, action) if (level & debug_mask) action
8322372Spst#else
8422372Spst# define DODEBUG(level, action)
8522372Spst#endif
8622347Spst
8722347Spstdevclass_t ex_devclass;
8822347Spst
8922347Spstchar irq2eemap[] =
9022347Spst	{ -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 };
9122347Spstu_char ee2irqmap[] =
9222347Spst	{ 9, 3, 5, 10, 11, 0, 0, 0 };
9322347Spst
9422347Spstchar plus_irq2eemap[] =
9522347Spst	{ -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 };
9622347Spstu_char plus_ee2irqmap[] =
9722347Spst	{ 3, 4, 5, 7, 9, 10, 11, 12 };
9822347Spst
9922347Spst/* Network Interface Functions */
10022347Spststatic void	ex_init(void *);
101static void	ex_start(struct ifnet *);
102static int	ex_ioctl(struct ifnet *, u_long, caddr_t);
103static void	ex_watchdog(struct ifnet *);
104
105/* ifmedia Functions	*/
106static int	ex_ifmedia_upd(struct ifnet *);
107static void	ex_ifmedia_sts(struct ifnet *, struct ifmediareq *);
108
109static int	ex_get_media(struct ex_softc *);
110
111static void	ex_reset(struct ex_softc *);
112static void	ex_setmulti(struct ex_softc *);
113
114static void	ex_tx_intr(struct ex_softc *);
115static void	ex_rx_intr(struct ex_softc *);
116
117void
118ex_get_address(struct ex_softc *sc, u_char *enaddr)
119{
120	uint16_t	eaddr_tmp;
121
122	eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Lo);
123	enaddr[5] = eaddr_tmp & 0xff;
124	enaddr[4] = eaddr_tmp >> 8;
125	eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Mid);
126	enaddr[3] = eaddr_tmp & 0xff;
127	enaddr[2] = eaddr_tmp >> 8;
128	eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Hi);
129	enaddr[1] = eaddr_tmp & 0xff;
130	enaddr[0] = eaddr_tmp >> 8;
131
132	return;
133}
134
135int
136ex_card_type(u_char *enaddr)
137{
138	if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9))
139		return (CARD_TYPE_EX_10_PLUS);
140
141	return (CARD_TYPE_EX_10);
142}
143
144/*
145 * Caller is responsible for eventually calling
146 * ex_release_resources() on failure.
147 */
148int
149ex_alloc_resources(device_t dev)
150{
151	struct ex_softc *	sc = device_get_softc(dev);
152	int			error = 0;
153
154	sc->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
155					    &sc->ioport_rid, RF_ACTIVE);
156	if (!sc->ioport) {
157		device_printf(dev, "No I/O space?!\n");
158		error = ENOMEM;
159		goto bad;
160	}
161	sc->bst = rman_get_bustag(sc->ioport);
162	sc->bsh = rman_get_bushandle(sc->ioport);
163
164	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
165					RF_ACTIVE);
166
167	if (!sc->irq) {
168		device_printf(dev, "No IRQ?!\n");
169		error = ENOMEM;
170		goto bad;
171	}
172
173bad:
174	return (error);
175}
176
177void
178ex_release_resources(device_t dev)
179{
180	struct ex_softc *	sc = device_get_softc(dev);
181
182	if (sc->ih) {
183		bus_teardown_intr(dev, sc->irq, sc->ih);
184		sc->ih = NULL;
185	}
186
187	if (sc->ioport) {
188		bus_release_resource(dev, SYS_RES_IOPORT,
189					sc->ioport_rid, sc->ioport);
190		sc->ioport = NULL;
191	}
192
193	if (sc->irq) {
194		bus_release_resource(dev, SYS_RES_IRQ,
195					sc->irq_rid, sc->irq);
196		sc->irq = NULL;
197	}
198
199	return;
200}
201
202int
203ex_attach(device_t dev)
204{
205	struct ex_softc *	sc = device_get_softc(dev);
206	struct ifnet *		ifp;
207	struct ifmedia *	ifm;
208	uint16_t		temp;
209
210	ifp = sc->ifp = if_alloc(IFT_ETHER);
211	if (ifp == NULL) {
212		device_printf(dev, "can not if_alloc()\n");
213		return (ENOSPC);
214	}
215	/* work out which set of irq <-> internal tables to use */
216	if (ex_card_type(sc->enaddr) == CARD_TYPE_EX_10_PLUS) {
217		sc->irq2ee = plus_irq2eemap;
218		sc->ee2irq = plus_ee2irqmap;
219	} else {
220		sc->irq2ee = irq2eemap;
221		sc->ee2irq = ee2irqmap;
222	}
223
224	sc->mem_size = CARD_RAM_SIZE;	/* XXX This should be read from the card itself. */
225
226	/*
227	 * Initialize the ifnet structure.
228	 */
229	ifp->if_softc = sc;
230	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
231	ifp->if_mtu = ETHERMTU;
232	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
233	    IFF_NEEDSGIANT;
234	ifp->if_start = ex_start;
235	ifp->if_ioctl = ex_ioctl;
236	ifp->if_watchdog = ex_watchdog;
237	ifp->if_init = ex_init;
238	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
239
240	ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
241
242	temp = ex_eeprom_read(sc, EE_W5);
243	if (temp & EE_W5_PORT_TPE)
244		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
245	if (temp & EE_W5_PORT_BNC)
246		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
247	if (temp & EE_W5_PORT_AUI)
248		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
249
250	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
251	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL);
252	ifmedia_set(&sc->ifmedia, ex_get_media(sc));
253
254	ifm = &sc->ifmedia;
255	ifm->ifm_media = ifm->ifm_cur->ifm_media;
256	ex_ifmedia_upd(ifp);
257
258	/*
259	 * Attach the interface.
260	 */
261	ether_ifattach(ifp, sc->enaddr);
262
263	return(0);
264}
265
266int
267ex_detach(device_t dev)
268{
269	struct ex_softc	*sc;
270	struct ifnet	*ifp;
271
272	sc = device_get_softc(dev);
273	ifp = sc->ifp;
274
275        ex_stop(sc);
276
277        ifp->if_flags &= ~IFF_RUNNING;
278	ether_ifdetach(ifp);
279	if_free(ifp);
280
281	ex_release_resources(dev);
282
283	return (0);
284}
285
286static void
287ex_init(void *xsc)
288{
289	struct ex_softc *	sc = (struct ex_softc *) xsc;
290	struct ifnet *		ifp = sc->ifp;
291	int			s;
292	int			i;
293	unsigned short		temp_reg;
294
295	DODEBUG(Start_End, printf("%s: ex_init: start\n", ifp->if_xname););
296
297	s = splimp();
298	ifp->if_timer = 0;
299
300	/*
301	 * Load the ethernet address into the card.
302	 */
303	CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
304	temp_reg = CSR_READ_1(sc, EEPROM_REG);
305	if (temp_reg & Trnoff_Enable) {
306		CSR_WRITE_1(sc, EEPROM_REG, temp_reg & ~Trnoff_Enable);
307	}
308	for (i = 0; i < ETHER_ADDR_LEN; i++) {
309		CSR_WRITE_1(sc, I_ADDR_REG0 + i, IFP2ENADDR(sc->ifp)[i]);
310	}
311	/*
312	 * - Setup transmit chaining and discard bad received frames.
313	 * - Match broadcast.
314	 * - Clear test mode.
315	 * - Set receiving mode.
316	 * - Set IRQ number.
317	 */
318	CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr);
319	CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | No_SA_Ins | RX_CRC_InMem);
320	CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3) & 0x3f /* XXX constants. */ );
321	CSR_WRITE_1(sc, CMD_REG, Bank1_Sel);
322	CSR_WRITE_1(sc, INT_NO_REG, (CSR_READ_1(sc, INT_NO_REG) & 0xf8) | sc->irq2ee[sc->irq_no]);
323
324	/*
325	 * Divide the available memory in the card into rcv and xmt buffers.
326	 * By default, I use the first 3/4 of the memory for the rcv buffer,
327	 * and the remaining 1/4 of the memory for the xmt buffer.
328	 */
329	sc->rx_mem_size = sc->mem_size * 3 / 4;
330	sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
331	sc->rx_lower_limit = 0x0000;
332	sc->rx_upper_limit = sc->rx_mem_size - 2;
333	sc->tx_lower_limit = sc->rx_mem_size;
334	sc->tx_upper_limit = sc->mem_size - 2;
335	CSR_WRITE_1(sc, RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
336	CSR_WRITE_1(sc, RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
337	CSR_WRITE_1(sc, XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
338	CSR_WRITE_1(sc, XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
339
340	/*
341	 * Enable receive and transmit interrupts, and clear any pending int.
342	 */
343	CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | TriST_INT);
344	CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
345	CSR_WRITE_1(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
346	CSR_WRITE_1(sc, STATUS_REG, All_Int);
347
348	/*
349	 * Initialize receive and transmit ring buffers.
350	 */
351	CSR_WRITE_2(sc, RCV_BAR, sc->rx_lower_limit);
352	sc->rx_head = sc->rx_lower_limit;
353	CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
354	CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit);
355	sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
356
357	ifp->if_flags |= IFF_RUNNING;
358	ifp->if_flags &= ~IFF_OACTIVE;
359	DODEBUG(Status, printf("OIDLE init\n"););
360
361	ex_setmulti(sc);
362
363	/*
364	 * Final reset of the board, and enable operation.
365	 */
366	CSR_WRITE_1(sc, CMD_REG, Sel_Reset_CMD);
367	DELAY(2);
368	CSR_WRITE_1(sc, CMD_REG, Rcv_Enable_CMD);
369
370	ex_start(ifp);
371	splx(s);
372
373	DODEBUG(Start_End, printf("%s: ex_init: finish\n", ifp->if_xname););
374}
375
376
377static void
378ex_start(struct ifnet *ifp)
379{
380	struct ex_softc *	sc = ifp->if_softc;
381	int			i, s, len, data_len, avail, dest, next;
382	unsigned char		tmp16[2];
383	struct mbuf *		opkt;
384	struct mbuf *		m;
385
386	DODEBUG(Start_End, printf("ex_start%d: start\n", unit););
387
388	s = splimp();
389
390	/*
391	 * Main loop: send outgoing packets to network card until there are no
392	 * more packets left, or the card cannot accept any more yet.
393	 */
394	while (((opkt = ifp->if_snd.ifq_head) != NULL) &&
395	       !(ifp->if_flags & IFF_OACTIVE)) {
396
397		/*
398		 * Ensure there is enough free transmit buffer space for
399		 * this packet, including its header. Note: the header
400		 * cannot wrap around the end of the transmit buffer and
401		 * must be kept together, so we allow space for twice the
402		 * length of the header, just in case.
403		 */
404
405		for (len = 0, m = opkt; m != NULL; m = m->m_next) {
406			len += m->m_len;
407		}
408
409		data_len = len;
410
411		DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
412
413		if (len & 1) {
414			len += XMT_HEADER_LEN + 1;
415		} else {
416			len += XMT_HEADER_LEN;
417		}
418
419		if ((i = sc->tx_tail - sc->tx_head) >= 0) {
420			avail = sc->tx_mem_size - i;
421		} else {
422			avail = -i;
423		}
424
425		DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
426
427		if (avail >= len + XMT_HEADER_LEN) {
428			IF_DEQUEUE(&ifp->if_snd, opkt);
429
430#ifdef EX_PSA_INTR
431			/*
432			 * Disable rx and tx interrupts, to avoid corruption
433			 * of the host address register by interrupt service
434			 * routines.
435			 * XXX Is this necessary with splimp() enabled?
436			 */
437			CSR_WRITE_1(sc, MASK_REG, All_Int);
438#endif
439
440			/*
441			 * Compute the start and end addresses of this
442			 * frame in the tx buffer.
443			 */
444			dest = sc->tx_tail;
445			next = dest + len;
446
447			if (next > sc->tx_upper_limit) {
448				if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
449				    XMT_HEADER_LEN) {
450					dest = sc->tx_lower_limit;
451					next = dest + len;
452				} else {
453					next = sc->tx_lower_limit +
454						next - sc->tx_upper_limit - 2;
455				}
456			}
457
458			/*
459			 * Build the packet frame in the card's ring buffer.
460			 */
461			DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
462
463			CSR_WRITE_2(sc, HOST_ADDR_REG, dest);
464			CSR_WRITE_2(sc, IO_PORT_REG, Transmit_CMD);
465			CSR_WRITE_2(sc, IO_PORT_REG, 0);
466			CSR_WRITE_2(sc, IO_PORT_REG, next);
467			CSR_WRITE_2(sc, IO_PORT_REG, data_len);
468
469			/*
470			 * Output the packet data to the card. Ensure all
471			 * transfers are 16-bit wide, even if individual
472			 * mbufs have odd length.
473			 */
474			for (m = opkt, i = 0; m != NULL; m = m->m_next) {
475				DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
476				if (i) {
477					tmp16[1] = *(mtod(m, caddr_t));
478					CSR_WRITE_MULTI_2(sc, IO_PORT_REG,
479					    (uint16_t *) tmp16, 1);
480				}
481				CSR_WRITE_MULTI_2(sc, IO_PORT_REG,
482				    (uint16_t *) (mtod(m, caddr_t) + i),
483				    (m->m_len - i) / 2);
484				if ((i = (m->m_len - i) & 1) != 0) {
485					tmp16[0] = *(mtod(m, caddr_t) +
486						   m->m_len - 1);
487				}
488			}
489			if (i)
490				CSR_WRITE_MULTI_2(sc, IO_PORT_REG,
491				    (uint16_t *) tmp16, 1);
492			/*
493			 * If there were other frames chained, update the
494			 * chain in the last one.
495			 */
496			if (sc->tx_head != sc->tx_tail) {
497				if (sc->tx_tail != dest) {
498					CSR_WRITE_2(sc, HOST_ADDR_REG,
499					     sc->tx_last + XMT_Chain_Point);
500					CSR_WRITE_2(sc, IO_PORT_REG, dest);
501				}
502				CSR_WRITE_2(sc, HOST_ADDR_REG,
503				     sc->tx_last + XMT_Byte_Count);
504				i = CSR_READ_2(sc, IO_PORT_REG);
505				CSR_WRITE_2(sc, HOST_ADDR_REG,
506				     sc->tx_last + XMT_Byte_Count);
507				CSR_WRITE_2(sc, IO_PORT_REG, i | Ch_bit);
508			}
509
510			/*
511			 * Resume normal operation of the card:
512			 * - Make a dummy read to flush the DRAM write
513			 *   pipeline.
514			 * - Enable receive and transmit interrupts.
515			 * - Send Transmit or Resume_XMT command, as
516			 *   appropriate.
517			 */
518			CSR_READ_2(sc, IO_PORT_REG);
519#ifdef EX_PSA_INTR
520			CSR_WRITE_1(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
521#endif
522			if (sc->tx_head == sc->tx_tail) {
523				CSR_WRITE_2(sc, XMT_BAR, dest);
524				CSR_WRITE_1(sc, CMD_REG, Transmit_CMD);
525				sc->tx_head = dest;
526				DODEBUG(Sent_Pkts, printf("Transmit\n"););
527			} else {
528				CSR_WRITE_1(sc, CMD_REG, Resume_XMT_List_CMD);
529				DODEBUG(Sent_Pkts, printf("Resume\n"););
530			}
531
532			sc->tx_last = dest;
533			sc->tx_tail = next;
534
535			BPF_MTAP(ifp, opkt);
536
537			ifp->if_timer = 2;
538			ifp->if_opackets++;
539			m_freem(opkt);
540		} else {
541			ifp->if_flags |= IFF_OACTIVE;
542			DODEBUG(Status, printf("OACTIVE start\n"););
543		}
544	}
545
546	splx(s);
547
548	DODEBUG(Start_End, printf("ex_start%d: finish\n", unit););
549}
550
551void
552ex_stop(struct ex_softc *sc)
553{
554
555	DODEBUG(Start_End, printf("ex_stop%d: start\n", unit););
556
557	/*
558	 * Disable card operation:
559	 * - Disable the interrupt line.
560	 * - Flush transmission and disable reception.
561	 * - Mask and clear all interrupts.
562	 * - Reset the 82595.
563	 */
564	CSR_WRITE_1(sc, CMD_REG, Bank1_Sel);
565	CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) & ~TriST_INT);
566	CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
567	CSR_WRITE_1(sc, CMD_REG, Rcv_Stop);
568	sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
569	sc->tx_last = 0; /* XXX I think these two lines are not necessary, because ex_init will always be called again to reinit the interface. */
570	CSR_WRITE_1(sc, MASK_REG, All_Int);
571	CSR_WRITE_1(sc, STATUS_REG, All_Int);
572	CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
573	DELAY(200);
574
575	DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit););
576
577	return;
578}
579
580void
581ex_intr(void *arg)
582{
583	struct ex_softc *sc = (struct ex_softc *)arg;
584	struct ifnet 	*ifp = sc->ifp;
585	int		int_status, send_pkts;
586	int		loops = 100;
587
588	DODEBUG(Start_End, printf("ex_intr%d: start\n", unit););
589
590	send_pkts = 0;
591	while (loops-- > 0 &&
592	    (int_status = CSR_READ_1(sc, STATUS_REG)) & (Tx_Int | Rx_Int)) {
593		/* don't loop forever */
594		if (int_status == 0xff)
595			break;
596		if (int_status & Rx_Int) {
597			CSR_WRITE_1(sc, STATUS_REG, Rx_Int);
598			ex_rx_intr(sc);
599		} else if (int_status & Tx_Int) {
600			CSR_WRITE_1(sc, STATUS_REG, Tx_Int);
601			ex_tx_intr(sc);
602			send_pkts = 1;
603		}
604	}
605	if (loops == 0)
606		printf("100 loops are not enough\n");
607
608	/*
609	 * If any packet has been transmitted, and there are queued packets to
610	 * be sent, attempt to send more packets to the network card.
611	 */
612	if (send_pkts && (ifp->if_snd.ifq_head != NULL))
613		ex_start(ifp);
614
615	DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit););
616
617	return;
618}
619
620static void
621ex_tx_intr(struct ex_softc *sc)
622{
623	struct ifnet *	ifp = sc->ifp;
624	int		tx_status;
625
626	DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit););
627
628	/*
629	 * - Cancel the watchdog.
630	 * For all packets transmitted since last transmit interrupt:
631	 * - Advance chain pointer to next queued packet.
632	 * - Update statistics.
633	 */
634
635	ifp->if_timer = 0;
636
637	while (sc->tx_head != sc->tx_tail) {
638		CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_head);
639
640		if (! CSR_READ_2(sc, IO_PORT_REG) & Done_bit)
641			break;
642
643		tx_status = CSR_READ_2(sc, IO_PORT_REG);
644		sc->tx_head = CSR_READ_2(sc, IO_PORT_REG);
645
646		if (tx_status & TX_OK_bit) {
647			ifp->if_opackets++;
648		} else {
649			ifp->if_oerrors++;
650		}
651
652		ifp->if_collisions += tx_status & No_Collisions_bits;
653	}
654
655	/*
656	 * The card should be ready to accept more packets now.
657	 */
658
659	ifp->if_flags &= ~IFF_OACTIVE;
660
661	DODEBUG(Status, printf("OIDLE tx_intr\n"););
662	DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit););
663
664	return;
665}
666
667static void
668ex_rx_intr(struct ex_softc *sc)
669{
670	struct ifnet *		ifp = sc->ifp;
671	int			rx_status;
672	int			pkt_len;
673	int			QQQ;
674	struct mbuf *		m;
675	struct mbuf *		ipkt;
676	struct ether_header *	eh;
677
678	DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit););
679
680	/*
681	 * For all packets received since last receive interrupt:
682	 * - If packet ok, read it into a new mbuf and queue it to interface,
683	 *   updating statistics.
684	 * - If packet bad, just discard it, and update statistics.
685	 * Finally, advance receive stop limit in card's memory to new location.
686	 */
687
688	CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head);
689
690	while (CSR_READ_2(sc, IO_PORT_REG) == RCV_Done) {
691
692		rx_status = CSR_READ_2(sc, IO_PORT_REG);
693		sc->rx_head = CSR_READ_2(sc, IO_PORT_REG);
694		QQQ = pkt_len = CSR_READ_2(sc, IO_PORT_REG);
695
696		if (rx_status & RCV_OK_bit) {
697			MGETHDR(m, M_DONTWAIT, MT_DATA);
698			ipkt = m;
699			if (ipkt == NULL) {
700				ifp->if_iqdrops++;
701			} else {
702				ipkt->m_pkthdr.rcvif = ifp;
703				ipkt->m_pkthdr.len = pkt_len;
704				ipkt->m_len = MHLEN;
705
706				while (pkt_len > 0) {
707					if (pkt_len >= MINCLSIZE) {
708						MCLGET(m, M_DONTWAIT);
709						if (m->m_flags & M_EXT) {
710							m->m_len = MCLBYTES;
711						} else {
712							m_freem(ipkt);
713							ifp->if_iqdrops++;
714							goto rx_another;
715						}
716					}
717					m->m_len = min(m->m_len, pkt_len);
718
719	  /*
720	   * NOTE: I'm assuming that all mbufs allocated are of even length,
721	   * except for the last one in an odd-length packet.
722	   */
723
724					CSR_READ_MULTI_2(sc, IO_PORT_REG,
725					    mtod(m, uint16_t *), m->m_len / 2);
726
727					if (m->m_len & 1) {
728						*(mtod(m, caddr_t) + m->m_len - 1) = CSR_READ_1(sc, IO_PORT_REG);
729					}
730					pkt_len -= m->m_len;
731
732					if (pkt_len > 0) {
733						MGET(m->m_next, M_DONTWAIT, MT_DATA);
734						if (m->m_next == NULL) {
735							m_freem(ipkt);
736							ifp->if_iqdrops++;
737							goto rx_another;
738						}
739						m = m->m_next;
740						m->m_len = MLEN;
741					}
742				}
743				eh = mtod(ipkt, struct ether_header *);
744#ifdef EXDEBUG
745	if (debug_mask & Rcvd_Pkts) {
746		if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) {
747			printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
748			printf("%6D\n", eh->ether_dhost, ":");
749		} /* QQQ */
750	}
751#endif
752				(*ifp->if_input)(ifp, ipkt);
753				ifp->if_ipackets++;
754			}
755		} else {
756			ifp->if_ierrors++;
757		}
758		CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head);
759rx_another: ;
760	}
761
762	if (sc->rx_head < sc->rx_lower_limit + 2)
763		CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit);
764	else
765		CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_head - 2);
766
767	DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit););
768
769	return;
770}
771
772
773static int
774ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data)
775{
776	struct ex_softc *	sc = ifp->if_softc;
777	struct ifreq *		ifr = (struct ifreq *)data;
778	int			s;
779	int			error = 0;
780
781	DODEBUG(Start_End, printf("%s: ex_ioctl: start ", ifp->if_xname););
782
783	s = splimp();
784
785	switch(cmd) {
786		case SIOCSIFADDR:
787		case SIOCGIFADDR:
788		case SIOCSIFMTU:
789			error = ether_ioctl(ifp, cmd, data);
790			break;
791
792		case SIOCSIFFLAGS:
793			DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
794			if ((ifp->if_flags & IFF_UP) == 0 &&
795			    (ifp->if_flags & IFF_RUNNING)) {
796
797				ifp->if_flags &= ~IFF_RUNNING;
798				ex_stop(sc);
799			} else {
800      				ex_init(sc);
801			}
802			break;
803#ifdef NODEF
804		case SIOCGHWADDR:
805			DODEBUG(Start_End, printf("SIOCGHWADDR"););
806			bcopy((caddr_t)sc->sc_addr, (caddr_t)&ifr->ifr_data,
807			      sizeof(sc->sc_addr));
808			break;
809#endif
810		case SIOCADDMULTI:
811		case SIOCDELMULTI:
812			ex_init(sc);
813			error = 0;
814			break;
815		case SIOCSIFMEDIA:
816		case SIOCGIFMEDIA:
817			error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
818			break;
819		default:
820			DODEBUG(Start_End, printf("unknown"););
821			error = EINVAL;
822	}
823
824	splx(s);
825
826	DODEBUG(Start_End, printf("\n%s: ex_ioctl: finish\n", ifp->if_xname););
827
828	return(error);
829}
830
831static void
832ex_setmulti(struct ex_softc *sc)
833{
834	struct ifnet *ifp;
835	struct ifmultiaddr *maddr;
836	uint16_t *addr;
837	int count;
838	int timeout, status;
839
840	ifp = sc->ifp;
841
842	count = 0;
843	IF_ADDR_LOCK(ifp);
844	TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) {
845		if (maddr->ifma_addr->sa_family != AF_LINK)
846			continue;
847		count++;
848	}
849	IF_ADDR_UNLOCK(ifp);
850
851	if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI)
852			|| count > 63) {
853		/* Interface is in promiscuous mode or there are too many
854		 * multicast addresses for the card to handle */
855		CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
856		CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Promisc_Mode);
857		CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
858		CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
859	}
860	else if ((ifp->if_flags & IFF_MULTICAST) && (count > 0)) {
861		/* Program multicast addresses plus our MAC address
862		 * into the filter */
863		CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
864		CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Multi_IA);
865		CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
866		CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
867
868		/* Borrow space from TX buffer; this should be safe
869		 * as this is only called from ex_init */
870
871		CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_lower_limit);
872		CSR_WRITE_2(sc, IO_PORT_REG, MC_Setup_CMD);
873		CSR_WRITE_2(sc, IO_PORT_REG, 0);
874		CSR_WRITE_2(sc, IO_PORT_REG, 0);
875		CSR_WRITE_2(sc, IO_PORT_REG, (count + 1) * 6);
876
877		IF_ADDR_LOCK(ifp);
878		TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) {
879			if (maddr->ifma_addr->sa_family != AF_LINK)
880				continue;
881
882			addr = (uint16_t*)LLADDR((struct sockaddr_dl *)
883					maddr->ifma_addr);
884			CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
885			CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
886			CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
887		}
888		IF_ADDR_UNLOCK(ifp);
889
890		/* Program our MAC address as well */
891		/* XXX: Is this necessary?  The Linux driver does this
892		 * but the NetBSD driver does not */
893		addr = (uint16_t*)(&IFP2ENADDR(sc->ifp));
894		CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
895		CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
896		CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
897
898		CSR_READ_2(sc, IO_PORT_REG);
899		CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit);
900		CSR_WRITE_1(sc, CMD_REG, MC_Setup_CMD);
901
902		sc->tx_head = sc->tx_lower_limit;
903		sc->tx_tail = sc->tx_head + XMT_HEADER_LEN + (count + 1) * 6;
904
905		for (timeout=0; timeout<100; timeout++) {
906			DELAY(2);
907			if ((CSR_READ_1(sc, STATUS_REG) & Exec_Int) == 0)
908				continue;
909
910			status = CSR_READ_1(sc, CMD_REG);
911			CSR_WRITE_1(sc, STATUS_REG, Exec_Int);
912			break;
913		}
914
915		sc->tx_head = sc->tx_tail;
916	}
917	else
918	{
919		/* No multicast or promiscuous mode */
920		CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
921		CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) & 0xDE);
922			/* ~(Multi_IA | Promisc_Mode) */
923		CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
924		CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
925	}
926}
927
928static void
929ex_reset(struct ex_softc *sc)
930{
931	int s;
932
933	DODEBUG(Start_End, printf("ex_reset%d: start\n", unit););
934
935	s = splimp();
936
937	ex_stop(sc);
938	ex_init(sc);
939
940	splx(s);
941
942	DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit););
943
944	return;
945}
946
947static void
948ex_watchdog(struct ifnet *ifp)
949{
950	struct ex_softc *	sc = ifp->if_softc;
951
952	DODEBUG(Start_End, printf("%s: ex_watchdog: start\n", ifp->if_xname););
953
954	ifp->if_flags &= ~IFF_OACTIVE;
955
956	DODEBUG(Status, printf("OIDLE watchdog\n"););
957
958	ifp->if_oerrors++;
959	ex_reset(sc);
960	ex_start(ifp);
961
962	DODEBUG(Start_End, printf("%s: ex_watchdog: finish\n", ifp->if_xname););
963
964	return;
965}
966
967static int
968ex_get_media(struct ex_softc *sc)
969{
970	int	current;
971	int	media;
972
973	media = ex_eeprom_read(sc, EE_W5);
974
975	CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
976	current = CSR_READ_1(sc, REG3);
977	CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
978
979	if ((current & TPE_bit) && (media & EE_W5_PORT_TPE))
980		return(IFM_ETHER|IFM_10_T);
981	if ((current & BNC_bit) && (media & EE_W5_PORT_BNC))
982		return(IFM_ETHER|IFM_10_2);
983
984	if (media & EE_W5_PORT_AUI)
985		return (IFM_ETHER|IFM_10_5);
986
987	return (IFM_ETHER|IFM_AUTO);
988}
989
990static int
991ex_ifmedia_upd(ifp)
992	struct ifnet *		ifp;
993{
994	struct ex_softc *       sc = ifp->if_softc;
995
996	if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER)
997		return EINVAL;
998
999	return (0);
1000}
1001
1002static void
1003ex_ifmedia_sts(ifp, ifmr)
1004	struct ifnet *          ifp;
1005	struct ifmediareq *     ifmr;
1006{
1007	struct ex_softc *       sc = ifp->if_softc;
1008
1009	ifmr->ifm_active = ex_get_media(sc);
1010	ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
1011
1012	return;
1013}
1014
1015u_short
1016ex_eeprom_read(struct ex_softc *sc, int location)
1017{
1018	int i;
1019	u_short data = 0;
1020	int read_cmd = location | EE_READ_CMD;
1021	short ctrl_val = EECS;
1022
1023	CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
1024	CSR_WRITE_1(sc, EEPROM_REG, EECS);
1025	for (i = 8; i >= 0; i--) {
1026		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
1027		CSR_WRITE_1(sc, EEPROM_REG, outval);
1028		CSR_WRITE_1(sc, EEPROM_REG, outval | EESK);
1029		DELAY(3);
1030		CSR_WRITE_1(sc, EEPROM_REG, outval);
1031		DELAY(2);
1032	}
1033	CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
1034
1035	for (i = 16; i > 0; i--) {
1036		CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK);
1037		DELAY(3);
1038		data = (data << 1) |
1039		    ((CSR_READ_1(sc, EEPROM_REG) & EEDO) ? 1 : 0);
1040		CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
1041		DELAY(2);
1042	}
1043
1044	ctrl_val &= ~EECS;
1045	CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK);
1046	DELAY(3);
1047	CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
1048	DELAY(2);
1049	CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
1050	return(data);
1051}
1052