smc91cxx.c revision 1.22
1/*	$NetBSD: smc91cxx.c,v 1.22 2000/02/02 16:04:42 itojun Exp $	*/
2
3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the NetBSD
22 *	Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 *    contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*
41 * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 *    notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 *    notice, this list of conditions and the following disclaimer in the
51 *    documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 *    must display the following acknowledgement:
54 *	This product includes software developed by Gardner Buchanan.
55 * 4. The name of Gardner Buchanan may not be used to endorse or promote
56 *    products derived from this software without specific prior written
57 *    permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 *
70 *   from FreeBSD Id: if_sn.c,v 1.4 1996/03/18 15:47:16 gardner Exp
71 */
72
73/*
74 * Core driver for the SMC 91Cxx family of Ethernet chips.
75 *
76 * Memory allocation interrupt logic is drived from an SMC 91C90 driver
77 * written for NetBSD/amiga by Michael Hitch.
78 */
79
80#include "opt_inet.h"
81#include "opt_ccitt.h"
82#include "opt_llc.h"
83#include "opt_ns.h"
84#include "bpfilter.h"
85#include "rnd.h"
86
87#include <sys/param.h>
88#include <sys/systm.h>
89#include <sys/mbuf.h>
90#include <sys/syslog.h>
91#include <sys/socket.h>
92#include <sys/device.h>
93#include <sys/malloc.h>
94#include <sys/ioctl.h>
95#include <sys/errno.h>
96#if NRND > 0
97#include <sys/rnd.h>
98#endif
99
100#include <machine/bus.h>
101#include <machine/intr.h>
102
103#include <net/if.h>
104#include <net/if_dl.h>
105#include <net/if_ether.h>
106#include <net/if_media.h>
107
108#ifdef INET
109#include <netinet/in.h>
110#include <netinet/if_inarp.h>
111#include <netinet/in_systm.h>
112#include <netinet/in_var.h>
113#include <netinet/ip.h>
114#endif
115
116#ifdef NS
117#include <netns/ns.h>
118#include <netns/ns_if.h>
119#endif
120
121#if defined(CCITT) && defined(LLC)
122#include <sys/socketvar.h>
123#include <netccitt/x25.h>
124#include <netccitt/pk.h>
125#include <netccitt/pk_var.h>
126#include <netccitt/pk_extern.h>
127#endif
128
129#if NBPFILTER > 0
130#include <net/bpf.h>
131#include <net/bpfdesc.h>
132#endif
133
134#include <dev/ic/smc91cxxreg.h>
135#include <dev/ic/smc91cxxvar.h>
136
137/* XXX Hardware padding doesn't work yet(?) */
138#define	SMC91CXX_SW_PAD
139
140const char *smc91cxx_idstrs[] = {
141	NULL,				/* 0 */
142	NULL,				/* 1 */
143	NULL,				/* 2 */
144	"SMC91C90/91C92",		/* 3 */
145	"SMC91C94",			/* 4 */
146	"SMC91C95",			/* 5 */
147	NULL,				/* 6 */
148	"SMC91C100",			/* 7 */
149	NULL,				/* 8 */
150	NULL,				/* 9 */
151	NULL,				/* 10 */
152	NULL,				/* 11 */
153	NULL,				/* 12 */
154	NULL,				/* 13 */
155	NULL,				/* 14 */
156	NULL,				/* 15 */
157};
158
159/* Supported media types. */
160const int smc91cxx_media[] = {
161	IFM_ETHER|IFM_10_T,
162	IFM_ETHER|IFM_10_5,
163};
164#define	NSMC91CxxMEDIA	(sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0]))
165
166int	smc91cxx_mediachange __P((struct ifnet *));
167void	smc91cxx_mediastatus __P((struct ifnet *, struct ifmediareq *));
168
169int	smc91cxx_set_media __P((struct smc91cxx_softc *, int));
170
171void	smc91cxx_init __P((struct smc91cxx_softc *));
172void	smc91cxx_read __P((struct smc91cxx_softc *));
173void	smc91cxx_reset __P((struct smc91cxx_softc *));
174void	smc91cxx_start __P((struct ifnet *));
175void	smc91cxx_resume __P((struct smc91cxx_softc *));
176void	smc91cxx_stop __P((struct smc91cxx_softc *));
177void	smc91cxx_watchdog __P((struct ifnet *));
178int	smc91cxx_ioctl __P((struct ifnet *, u_long, caddr_t));
179
180static __inline int ether_cmp __P((void *, void *));
181static __inline int
182ether_cmp(va, vb)
183	void *va, *vb;
184{
185	u_int8_t *a = va;
186	u_int8_t *b = vb;
187
188	return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
189		(a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
190}
191
192void
193smc91cxx_attach(sc, myea)
194	struct smc91cxx_softc *sc;
195	u_int8_t *myea;
196{
197	struct ifnet *ifp = &sc->sc_ec.ec_if;
198	bus_space_tag_t bst = sc->sc_bst;
199	bus_space_handle_t bsh = sc->sc_bsh;
200	const char *idstr;
201	u_int16_t tmp;
202	u_int8_t enaddr[ETHER_ADDR_LEN];
203	int i, aui;
204
205	/* Make sure the chip is stopped. */
206	smc91cxx_stop(sc);
207
208	SMC_SELECT_BANK(sc, 3);
209	tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
210	/* check magic number */
211	if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
212		idstr = NULL;
213		printf("%s: invalid BSR 0x%04x\n", sc->sc_dev.dv_xname, tmp);
214	} else
215		idstr = smc91cxx_idstrs[RR_ID(tmp)];
216	printf("%s: ", sc->sc_dev.dv_xname);
217	if (idstr != NULL)
218		printf("%s, ", idstr);
219	else
220		printf("unknown chip id %d, ", RR_ID(tmp));
221	printf("revision %d\n", RR_REV(tmp));
222
223	/* Read the station address from the chip. */
224	SMC_SELECT_BANK(sc, 1);
225	if (myea == NULL) {
226		myea = enaddr;
227		for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
228			tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
229			myea[i + 1] = (tmp >> 8) & 0xff;
230			myea[i] = tmp & 0xff;
231		}
232	}
233	printf("%s: MAC address %s, ", sc->sc_dev.dv_xname,
234	    ether_sprintf(myea));
235
236	/* ..and default media. */
237	tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
238	printf("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
239	    "AUI" : "UTP");
240
241	/* Initialize the ifnet structure. */
242	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
243	ifp->if_softc = sc;
244	ifp->if_start = smc91cxx_start;
245	ifp->if_ioctl = smc91cxx_ioctl;
246	ifp->if_watchdog = smc91cxx_watchdog;
247	ifp->if_flags =
248	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
249
250	/* Attach the interface. */
251	if_attach(ifp);
252	ether_ifattach(ifp, myea);
253
254	/* Initialize the media structures. */
255	ifmedia_init(&sc->sc_media, 0, smc91cxx_mediachange,
256	    smc91cxx_mediastatus);
257	for (i = 0; i < NSMC91CxxMEDIA; i++)
258		ifmedia_add(&sc->sc_media, smc91cxx_media[i], 0, NULL);
259	ifmedia_set(&sc->sc_media, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T));
260
261#if NBPFILTER > 0
262	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
263#endif
264
265#if NRND > 0
266	rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
267			  RND_TYPE_NET, 0);
268#endif
269}
270
271/*
272 * Change media according to request.
273 */
274int
275smc91cxx_mediachange(ifp)
276	struct ifnet *ifp;
277{
278	struct smc91cxx_softc *sc = ifp->if_softc;
279
280	return (smc91cxx_set_media(sc, sc->sc_media.ifm_media));
281}
282
283int
284smc91cxx_set_media(sc, media)
285	struct smc91cxx_softc *sc;
286	int media;
287{
288	bus_space_tag_t bst = sc->sc_bst;
289	bus_space_handle_t bsh = sc->sc_bsh;
290	u_int16_t tmp;
291
292	/*
293	 * If the interface is not currently powered on, just return.
294	 * When it is enabled later, smc91cxx_init() will properly set
295	 * up the media for us.
296	 */
297	if (sc->sc_enabled == 0)
298		return (0);
299
300	if (IFM_TYPE(media) != IFM_ETHER)
301		return (EINVAL);
302
303	switch (IFM_SUBTYPE(media)) {
304	case IFM_10_T:
305	case IFM_10_5:
306		SMC_SELECT_BANK(sc, 1);
307		tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
308		if (IFM_SUBTYPE(media) == IFM_10_5)
309			tmp |= CR_AUI_SELECT;
310		else
311			tmp &= ~CR_AUI_SELECT;
312		bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
313		delay(20000);	/* XXX is this needed? */
314		break;
315
316	default:
317		return (EINVAL);
318	}
319
320	return (0);
321}
322
323/*
324 * Notify the world which media we're using.
325 */
326void
327smc91cxx_mediastatus(ifp, ifmr)
328	struct ifnet *ifp;
329	struct ifmediareq *ifmr;
330{
331	struct smc91cxx_softc *sc = ifp->if_softc;
332	bus_space_tag_t bst = sc->sc_bst;
333	bus_space_handle_t bsh = sc->sc_bsh;
334	u_int16_t tmp;
335
336	if (sc->sc_enabled == 0) {
337		ifmr->ifm_active = IFM_ETHER | IFM_NONE;
338		ifmr->ifm_status = 0;
339		return;
340	}
341
342	SMC_SELECT_BANK(sc, 1);
343	tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
344	ifmr->ifm_active =
345	    IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
346}
347
348/*
349 * Reset and initialize the chip.
350 */
351void
352smc91cxx_init(sc)
353	struct smc91cxx_softc *sc;
354{
355	struct ifnet *ifp = &sc->sc_ec.ec_if;
356	bus_space_tag_t bst = sc->sc_bst;
357	bus_space_handle_t bsh = sc->sc_bsh;
358	u_int16_t tmp;
359	u_int8_t *enaddr;
360	int s, i;
361
362	s = splnet();
363
364	/*
365	 * This resets the registersmostly to defaults, but doesn't
366	 * affect the EEPROM.  After the reset cycle, we pause briefly
367	 * for the chip to recover.
368	 *
369	 * XXX how long are we really supposed to delay?  --thorpej
370	 */
371	SMC_SELECT_BANK(sc, 0);
372	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
373	delay(100);
374	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
375	delay(200);
376
377	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
378
379	/* Set the Ethernet address. */
380	SMC_SELECT_BANK(sc, 1);
381	enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
382	for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
383		tmp = enaddr[i + 1] << 8 | enaddr[i];
384		bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
385	}
386
387	/*
388	 * Set the control register to automatically release successfully
389	 * transmitted packets (making the best use of our limited memory)
390	 * and enable the EPH interrupt on certain TX errors.
391	 */
392	bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
393	    CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
394
395	/*
396	 * Reset the MMU and wait for it to be un-busy.
397	 */
398	SMC_SELECT_BANK(sc, 2);
399	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
400	while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
401		/* XXX bound this loop! */ ;
402
403	/*
404	 * Disable all interrupts.
405	 */
406	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
407
408	/*
409	 * Set current media.
410	 */
411	smc91cxx_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
412
413	/*
414	 * Set the receive filter.  We want receive enable and auto
415	 * strip of CRC from received packet.  If we are in promisc. mode,
416	 * then set that bit as well.
417	 *
418	 * XXX Initialize multicast filter.  For now, we just accept
419	 * XXX all multicast.
420	 */
421	SMC_SELECT_BANK(sc, 0);
422
423	tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
424	if (ifp->if_flags & IFF_PROMISC)
425		tmp |= RCR_PROMISC;
426
427	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
428
429	/*
430	 * Set transmitter control to "enabled".
431	 */
432	tmp = TCR_ENABLE;
433
434#ifndef SMC91CXX_SW_PAD
435	/*
436	 * Enable hardware padding of transmitted packets.
437	 * XXX doesn't work?
438	 */
439	tmp |= TCR_PAD_ENABLE;
440#endif
441
442	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
443
444	/*
445	 * Now, enable interrupts.
446	 */
447	SMC_SELECT_BANK(sc, 2);
448
449	bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
450	    IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
451
452	/* Interface is now running, with no output active. */
453	ifp->if_flags |= IFF_RUNNING;
454	ifp->if_flags &= ~IFF_OACTIVE;
455
456	/*
457	 * Attempt to start any pending transmission.
458	 */
459	smc91cxx_start(ifp);
460
461	splx(s);
462}
463
464/*
465 * Start output on an interface.
466 * Must be called at splnet or interrupt level.
467 */
468void
469smc91cxx_start(ifp)
470	struct ifnet *ifp;
471{
472	struct smc91cxx_softc *sc = ifp->if_softc;
473	bus_space_tag_t bst = sc->sc_bst;
474	bus_space_handle_t bsh = sc->sc_bsh;
475	u_int len;
476	struct mbuf *m, *top;
477	u_int16_t length, npages;
478	u_int8_t packetno;
479	int timo, pad;
480
481	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
482		return;
483
484 again:
485	/*
486	 * Peek at the next packet.
487	 */
488	if ((m = ifp->if_snd.ifq_head) == NULL)
489		return;
490
491	/*
492	 * Compute the frame length and set pad to give an overall even
493	 * number of bytes.  Below, we assume that the packet length
494	 * is even.
495	 */
496	for (len = 0, top = m; m != NULL; m = m->m_next)
497		len += m->m_len;
498	pad = (len & 1);
499
500	/*
501	 * We drop packets that are too large.  Perhaps we should
502	 * truncate them instead?
503	 */
504	if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
505		printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
506		ifp->if_oerrors++;
507		IF_DEQUEUE(&ifp->if_snd, m);
508		m_freem(m);
509		goto readcheck;
510	}
511
512#ifdef SMC91CXX_SW_PAD
513	/*
514	 * Not using hardware padding; pad to ETHER_MIN_LEN.
515	 */
516	if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
517		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
518#endif
519
520	length = pad + len;
521
522	/*
523	 * The MMU has a 256 byte page size.  The MMU expects us to
524	 * ask for "npages - 1".  We include space for the status word,
525	 * byte count, and control bytes in the allocation request.
526	 */
527	npages = (length + 6) >> 8;
528
529	/*
530	 * Now allocate the memory.
531	 */
532	SMC_SELECT_BANK(sc, 2);
533	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
534
535	timo = MEMORY_WAIT_TIME;
536	do {
537		if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
538			break;
539		delay(1);
540	} while (--timo);
541
542	packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
543
544	if (packetno & ARR_FAILED || timo == 0) {
545		/*
546		 * No transmit memory is available.  Record the number
547		 * of requestd pages and enable the allocation completion
548		 * interrupt.  Set up the watchdog timer in case we miss
549		 * the interrupt.  Mark the interface as active so that
550		 * no one else attempts to transmit while we're allocating
551		 * memory.
552		 */
553		bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
554		    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
555
556		ifp->if_timer = 5;
557		ifp->if_flags |= IFF_OACTIVE;
558
559		return;
560	}
561
562	/*
563	 * We have a packet number - set the data window.
564	 */
565	bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
566
567	/*
568	 * Point to the beginning of the packet.
569	 */
570	bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
571
572	/*
573	 * Send the packet length (+6 for stats, length, and control bytes)
574	 * and the status word (set to zeros).
575	 */
576	bus_space_write_2(bst, bsh, DATA_REG_W, 0);
577	bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
578	bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
579
580	/*
581	 * Get the packet from the kernel.  This will include the Ethernet
582	 * frame header, MAC address, etc.
583	 */
584	IF_DEQUEUE(&ifp->if_snd, m);
585
586	/*
587	 * Push the packet out to the card.
588	 */
589	for (top = m; m != NULL; m = m->m_next) {
590		/* Words... */
591		bus_space_write_multi_2(bst, bsh, DATA_REG_W,
592		    mtod(m, u_int16_t *), m->m_len >> 1);
593
594		/* ...and the remaining byte, if any. */
595		if (m->m_len & 1)
596			bus_space_write_1(bst, bsh, DATA_REG_B,
597			  *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
598	}
599
600#ifdef SMC91CXX_SW_PAD
601	/*
602	 * Push out padding.
603	 */
604	while (pad > 1) {
605		bus_space_write_2(bst, bsh, DATA_REG_W, 0);
606		pad -= 2;
607	}
608	if (pad)
609		bus_space_write_1(bst, bsh, DATA_REG_B, 0);
610#endif
611
612	/*
613	 * Push out control byte and unused packet byte.  The control byte
614	 * is 0, meaning the packet is even lengthed and no special
615	 * CRC handling is necessary.
616	 */
617	bus_space_write_2(bst, bsh, DATA_REG_W, 0);
618
619	/*
620	 * Enable transmit interrupts and let the chip go.  Set a watchdog
621	 * in case we miss the interrupt.
622	 */
623	bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
624	    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
625	    IM_TX_INT | IM_TX_EMPTY_INT);
626
627	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
628
629	ifp->if_timer = 5;
630
631#if NBPFILTER > 0
632	/* Hand off a copy to the bpf. */
633	if (ifp->if_bpf)
634		bpf_mtap(ifp->if_bpf, top);
635#endif
636
637	ifp->if_opackets++;
638	m_freem(top);
639
640 readcheck:
641	/*
642	 * Check for incoming pcakets.  We don't want to overflow the small
643	 * RX FIFO.  If nothing has arrived, attempt to queue another
644	 * transmit packet.
645	 */
646	if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
647		goto again;
648}
649
650/*
651 * Interrupt service routine.
652 */
653int
654smc91cxx_intr(arg)
655	void *arg;
656{
657	struct smc91cxx_softc *sc = arg;
658	struct ifnet *ifp = &sc->sc_ec.ec_if;
659	bus_space_tag_t bst = sc->sc_bst;
660	bus_space_handle_t bsh = sc->sc_bsh;
661	u_int8_t mask, interrupts, status;
662	u_int16_t packetno, tx_status, card_stats;
663
664	if (sc->sc_enabled == 0 ||
665	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
666		return (0);
667
668	SMC_SELECT_BANK(sc, 2);
669
670	/*
671	 * Obtain the current interrupt mask.
672	 */
673	mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
674
675	/*
676	 * Get the set of interrupt which occurred and eliminate any
677	 * which are not enabled.
678	 */
679	interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
680	status = interrupts & mask;
681
682	/* Ours? */
683	if (status == 0)
684		return (0);
685
686	/*
687	 * It's ours; disable all interrupts while we process them.
688	 */
689	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
690
691	/*
692	 * Receive overrun interrupts.
693	 */
694	if (status & IM_RX_OVRN_INT) {
695		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
696		ifp->if_ierrors++;
697	}
698
699	/*
700	 * Receive interrupts.
701	 */
702	if (status & IM_RCV_INT) {
703#if 1 /* DIAGNOSTIC */
704		packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
705		if (packetno & FIFO_REMPTY)
706			printf("%s: receive interrupt on empty fifo\n",
707			    sc->sc_dev.dv_xname);
708		else
709#endif
710		smc91cxx_read(sc);
711	}
712
713	/*
714	 * Memory allocation interrupts.
715	 */
716	if (status & IM_ALLOC_INT) {
717		/* Disable this interrupt. */
718		mask &= ~IM_ALLOC_INT;
719
720		/*
721		 * Release the just-allocated memory.  We will reallocate
722		 * it through the normal start logic.
723		 */
724		while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
725			/* XXX bound this loop! */ ;
726		bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
727
728		ifp->if_flags &= ~IFF_OACTIVE;
729		ifp->if_timer = 0;
730	}
731
732	/*
733	 * Transmit complete interrupt.  Handle transmission error messages.
734	 * This will only be called on error condition because of AUTO RELEASE
735	 * mode.
736	 */
737	if (status & IM_TX_INT) {
738		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
739
740		packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
741		    FIFO_TX_MASK;
742
743		/*
744		 * Select this as the packet to read from.
745		 */
746		bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
747
748		/*
749		 * Position the pointer to the beginning of the packet.
750		 */
751		bus_space_write_2(bst, bsh, POINTER_REG_W,
752		    PTR_AUTOINC | PTR_READ /* | 0x0000 */);
753
754		/*
755		 * Fetch the TX status word.  This will be a copy of
756		 * the EPH_STATUS_REG_W at the time of the transmission
757		 * failure.
758		 */
759		tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
760
761		if (tx_status & EPHSR_TX_SUC)
762			printf("%s: successful packet caused TX interrupt?!\n",
763			    sc->sc_dev.dv_xname);
764		else
765			ifp->if_oerrors++;
766
767		if (tx_status & EPHSR_LATCOL)
768			ifp->if_collisions++;
769
770		/*
771		 * Some of these errors disable the transmitter; reenable it.
772		 */
773		SMC_SELECT_BANK(sc, 0);
774#ifdef SMC91CXX_SW_PAD
775		bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
776#else
777		bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
778		    TCR_ENABLE | TCR_PAD_ENABLE);
779#endif
780
781		/*
782		 * Kill the failed packet and wait for the MMU to unbusy.
783		 */
784		SMC_SELECT_BANK(sc, 2);
785		while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
786			/* XXX bound this loop! */ ;
787		bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
788
789		ifp->if_timer = 0;
790	}
791
792	/*
793	 * Transmit underrun interrupts.  We use this opportunity to
794	 * update transmit statistics from the card.
795	 */
796	if (status & IM_TX_EMPTY_INT) {
797		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
798
799		/* Disable this interrupt. */
800		mask &= ~IM_TX_EMPTY_INT;
801
802		SMC_SELECT_BANK(sc, 0);
803		card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
804
805		/* Single collisions. */
806		ifp->if_collisions += card_stats & ECR_COLN_MASK;
807
808		/* Multiple collisions. */
809		ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
810
811		SMC_SELECT_BANK(sc, 2);
812
813		ifp->if_timer = 0;
814	}
815
816	/*
817	 * Other errors.  Reset the interface.
818	 */
819	if (status & IM_EPH_INT) {
820		smc91cxx_stop(sc);
821		smc91cxx_init(sc);
822	}
823
824	/*
825	 * Attempt to queue more packets for transmission.
826	 */
827	smc91cxx_start(ifp);
828
829	/*
830	 * Reenable the interrupts we wish to receive now that processing
831	 * is complete.
832	 */
833	mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
834	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
835
836#if NRND > 0
837	if (status)
838		rnd_add_uint32(&sc->rnd_source, status);
839#endif
840
841	return (1);
842}
843
844/*
845 * Read a packet from the card and pass it up to the kernel.
846 * NOTE!  WE EXPECT TO BE IN REGISTER WINDOW 2!
847 */
848void
849smc91cxx_read(sc)
850	struct smc91cxx_softc *sc;
851{
852	struct ifnet *ifp = &sc->sc_ec.ec_if;
853	bus_space_tag_t bst = sc->sc_bst;
854	bus_space_handle_t bsh = sc->sc_bsh;
855	struct ether_header *eh;
856	struct mbuf *m;
857	u_int16_t status, packetno, packetlen;
858	u_int8_t *data;
859
860 again:
861	/*
862	 * Set data pointer to the beginning of the packet.  Since
863	 * PTR_RCV is set, the packet number will be found automatically
864	 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
865	 */
866	bus_space_write_2(bst, bsh, POINTER_REG_W,
867	    PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
868
869	/*
870	 * First two words are status and packet length.
871	 */
872	status = bus_space_read_2(bst, bsh, DATA_REG_W);
873	packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
874
875	/*
876	 * The packet length includes 3 extra words: status, length,
877	 * and an extra word that includes the control byte.
878	 */
879	packetlen -= 6;
880
881	/*
882	 * Account for receive errors and discard.
883	 */
884	if (status & RS_ERRORS) {
885		ifp->if_ierrors++;
886		goto out;
887	}
888
889	/*
890	 * Adjust for odd-length packet.
891	 */
892	if (status & RS_ODDFRAME)
893		packetlen++;
894
895	/*
896	 * Allocate a header mbuf.
897	 */
898	MGETHDR(m, M_DONTWAIT, MT_DATA);
899	if (m == NULL)
900		goto out;
901
902	m->m_pkthdr.rcvif = ifp;
903	m->m_pkthdr.len = m->m_len = packetlen;
904
905	/*
906	 * Always put the packet in a cluster.
907	 * XXX should chain small mbufs if less than threshold.
908	 */
909	MCLGET(m, M_DONTWAIT);
910	if ((m->m_flags & M_EXT) == 0) {
911		m_freem(m);
912		ifp->if_ierrors++;
913		printf("%s: can't allocate cluster for incoming packet\n",
914		    sc->sc_dev.dv_xname);
915		goto out;
916	}
917
918	/*
919	 * Pull the packet off the interface.
920	 */
921	eh = mtod(m, struct ether_header *);
922	data = mtod(m, u_int8_t *);
923	bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data,
924	    packetlen >> 1);
925	if (packetlen & 1) {
926		data += packetlen & ~1;
927		*data = bus_space_read_1(bst, bsh, DATA_REG_B);
928	}
929
930	ifp->if_ipackets++;
931
932	/*
933	 * Make sure to behave as IFF_SIMPLEX in all cases.
934	 * This is to cope with SMC91C92 (Megahertz XJ10BT), which
935	 * loops back packets to itself on promiscuous mode.
936	 * (should be ensured by chipset configuration)
937	 */
938	if ((ifp->if_flags & IFF_PROMISC) != 0) {
939		/*
940		 * Drop multicast/broadcast packet looped back from myself.
941		 */
942		if ((eh->ether_dhost[0] & 1) == 1 &&	/* mcast || bcast */
943		    ether_cmp(eh->ether_shost, LLADDR(ifp->if_sadl)) == 0) {
944			m_freem(m);
945			goto out;
946		}
947
948		/*
949		 * If this is unicast and not for me, drop it.
950		 */
951		if ((eh->ether_dhost[0] & 1) == 0 &&	/* !mcast and !bcast */
952		    ether_cmp(eh->ether_dhost, LLADDR(ifp->if_sadl)) != 0) {
953			m_freem(m);
954			goto out;
955		}
956	}
957
958#if NBPFILTER > 0
959	/*
960	 * Hand the packet off to bpf listeners.
961	 */
962	if (ifp->if_bpf)
963		bpf_mtap(ifp->if_bpf, m);
964#endif
965
966	m->m_pkthdr.len = m->m_len = packetlen;
967	(*ifp->if_input)(ifp, m);
968
969 out:
970	/*
971	 * Tell the card to free the memory occupied by this packet.
972	 */
973	while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
974		/* XXX bound this loop! */ ;
975	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
976
977	/*
978	 * Check for another packet.
979	 */
980	packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
981	if (packetno & FIFO_REMPTY)
982		return;
983	goto again;
984}
985
986/*
987 * Process an ioctl request.
988 */
989int
990smc91cxx_ioctl(ifp, cmd, data)
991	struct ifnet *ifp;
992	u_long cmd;
993	caddr_t data;
994{
995	struct smc91cxx_softc *sc = ifp->if_softc;
996	struct ifaddr *ifa = (struct ifaddr *)data;
997	struct ifreq *ifr = (struct ifreq *)data;
998	int s, error = 0;
999
1000	s = splnet();
1001
1002	switch (cmd) {
1003	case SIOCSIFADDR:
1004		if ((error = smc91cxx_enable(sc)) != 0)
1005			break;
1006		ifp->if_flags |= IFF_UP;
1007		switch (ifa->ifa_addr->sa_family) {
1008#ifdef INET
1009		case AF_INET:
1010		smc91cxx_init(sc);
1011		arp_ifinit(ifp, ifa);
1012		break;
1013#endif
1014#ifdef NS
1015		case AF_NS:
1016		    {
1017			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1018
1019			if (ns_nullhost(*ina))
1020				ina->x_host =
1021				    *(union ns_host *)LLADDR(ifp->if_sadl);
1022			else {
1023				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
1024				    ETHER_ADDR_LEN);
1025			}
1026
1027			/*
1028			 * Set new address.  Reset, because the receiver
1029			 * has to be stopped before we can set the new
1030			 * MAC address.
1031			 */
1032			smc91cxx_reset(sc);
1033			break;
1034		    }
1035#endif
1036		default:
1037			smc91cxx_init(sc);
1038			break;
1039		}
1040		break;
1041
1042#if defined(CCITT) && defined(LLC)
1043	case SIOCSIFCONF_X25:
1044		if ((error = smc91cxx_enable(sc)) != 0)
1045			break;
1046		ifp->if_flags |= IFF_UP;
1047		ifa->ifa_rtrequest = cons_rtrequest;	/* XXX */
1048		error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
1049		if (error == 0)
1050			smc91cxx_init(sc);
1051		break;
1052#endif
1053
1054	case SIOCSIFFLAGS:
1055		if ((ifp->if_flags & IFF_UP) == 0 &&
1056		    (ifp->if_flags & IFF_RUNNING) != 0) {
1057			/*
1058			 * If interface is marked down and it is running,
1059			 * stop it.
1060			 */
1061			smc91cxx_stop(sc);
1062			ifp->if_flags &= ~IFF_RUNNING;
1063			smc91cxx_disable(sc);
1064		} else if ((ifp->if_flags & IFF_UP) != 0 &&
1065			   (ifp->if_flags & IFF_RUNNING) == 0) {
1066			/*
1067			 * If interface is marked up and it is stopped,
1068			 * start it.
1069			 */
1070			if ((error = smc91cxx_enable(sc)) != 0)
1071				break;
1072			smc91cxx_init(sc);
1073		} else if ((ifp->if_flags & IFF_UP) != 0) {
1074			/*
1075			 * Reset the interface to pick up changes in any
1076			 * other flags that affect hardware registers.
1077			 */
1078			smc91cxx_reset(sc);
1079		}
1080		break;
1081
1082	case SIOCADDMULTI:
1083	case SIOCDELMULTI:
1084		if (sc->sc_enabled == 0) {
1085			error = EIO;
1086			break;
1087		}
1088
1089		error = (cmd == SIOCADDMULTI) ?
1090		    ether_addmulti(ifr, &sc->sc_ec) :
1091		    ether_delmulti(ifr, &sc->sc_ec);
1092		if (error == ENETRESET) {
1093			/*
1094			 * Multicast list has changed; set the hardware
1095			 * filter accordingly.
1096			 */
1097			smc91cxx_reset(sc);
1098			error = 0;
1099		}
1100		break;
1101
1102	case SIOCGIFMEDIA:
1103	case SIOCSIFMEDIA:
1104		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1105		break;
1106
1107	default:
1108		error = EINVAL;
1109		break;
1110	}
1111
1112	splx(s);
1113	return (error);
1114}
1115
1116/*
1117 * Reset the interface.
1118 */
1119void
1120smc91cxx_reset(sc)
1121	struct smc91cxx_softc *sc;
1122{
1123	int s;
1124
1125	s = splnet();
1126	smc91cxx_stop(sc);
1127	smc91cxx_init(sc);
1128	splx(s);
1129}
1130
1131/*
1132 * Watchdog timer.
1133 */
1134void
1135smc91cxx_watchdog(ifp)
1136	struct ifnet *ifp;
1137{
1138	struct smc91cxx_softc *sc = ifp->if_softc;
1139
1140	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1141	ifp->if_oerrors++;
1142	smc91cxx_reset(sc);
1143}
1144
1145/*
1146 * Stop output on the interface.
1147 */
1148void
1149smc91cxx_stop(sc)
1150	struct smc91cxx_softc *sc;
1151{
1152	bus_space_tag_t bst = sc->sc_bst;
1153	bus_space_handle_t bsh = sc->sc_bsh;
1154
1155	/*
1156	 * Clear interrupt mask; disable all interrupts.
1157	 */
1158	SMC_SELECT_BANK(sc, 2);
1159	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
1160
1161	/*
1162	 * Disable transmitter and receiver.
1163	 */
1164	SMC_SELECT_BANK(sc, 0);
1165	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
1166	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
1167
1168	/*
1169	 * Cancel watchdog timer.
1170	 */
1171	sc->sc_ec.ec_if.if_timer = 0;
1172}
1173
1174/*
1175 * Enable power on the interface.
1176 */
1177int
1178smc91cxx_enable(sc)
1179	struct smc91cxx_softc *sc;
1180{
1181
1182	if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
1183		if ((*sc->sc_enable)(sc) != 0) {
1184			printf("%s: device enable failed\n",
1185			    sc->sc_dev.dv_xname);
1186			return (EIO);
1187		}
1188	}
1189
1190	sc->sc_enabled = 1;
1191	return (0);
1192}
1193
1194/*
1195 * Disable power on the interface.
1196 */
1197void
1198smc91cxx_disable(sc)
1199	struct smc91cxx_softc *sc;
1200{
1201
1202	if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
1203		(*sc->sc_disable)(sc);
1204		sc->sc_enabled = 0;
1205	}
1206}
1207
1208int
1209smc91cxx_activate(self, act)
1210	struct device *self;
1211	enum devact act;
1212{
1213	struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1214	int rv = 0, s;
1215
1216	s = splnet();
1217	switch (act) {
1218	case DVACT_ACTIVATE:
1219		rv = EOPNOTSUPP;
1220		break;
1221
1222	case DVACT_DEACTIVATE:
1223#ifdef notyet
1224		/* First, kill off the interface. */
1225		if_detach(sc->sc_ec.ec_if);
1226#endif
1227
1228		/* Now disable the interface. */
1229		smc91cxx_disable(sc);
1230		break;
1231	}
1232	splx(s);
1233	return (rv);
1234}
1235
1236int
1237smc91cxx_detach(self, flags)
1238	struct device *self;
1239	int flags;
1240{
1241	struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1242	struct ifnet *ifp = &sc->sc_ec.ec_if;
1243
1244	/* dp8390_disable() checks sc->sc_enabled */
1245	smc91cxx_disable(sc);
1246
1247	/* smc91cxx_attach() never fails */
1248
1249	/* Delete all media. */
1250	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1251
1252#if NRND > 0
1253	rnd_detach_source(&sc->rnd_source);
1254#endif
1255#if NBPFILTER > 0
1256	bpfdetach(ifp);
1257#endif
1258	ether_ifdetach(ifp);
1259	if_detach(ifp);
1260
1261	return (0);
1262}
1263