if_sn.c revision 81122
164562Sgshapiro/*
2261370Sgshapiro * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
390792Sgshapiro * All rights reserved.
490792Sgshapiro *
590792Sgshapiro * Redistribution and use in source and binary forms, with or without
690792Sgshapiro * modification, are permitted provided that the following conditions
790792Sgshapiro * are met:
890792Sgshapiro * 1. Redistributions of source code must retain the above copyright
9261370Sgshapiro *    notice, this list of conditions and the following disclaimer.
1090792Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright
1190792Sgshapiro *    notice, this list of conditions and the following disclaimer in the
1264562Sgshapiro *    documentation and/or other materials provided with the distribution.
1364562Sgshapiro * 3. All advertising materials mentioning features or use of this software
1464562Sgshapiro *    must display the following acknowledgement:
1564562Sgshapiro *      This product includes software developed by Gardner Buchanan.
1664562Sgshapiro * 4. The name of Gardner Buchanan may not be used to endorse or promote
1764562Sgshapiro *    products derived from this software without specific prior written
1890792Sgshapiro *    permission.
1990792Sgshapiro *
2064562Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2164562Sgshapiro * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2264562Sgshapiro * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2364562Sgshapiro * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2464562Sgshapiro * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2564562Sgshapiro * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26110560Sgshapiro * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2764562Sgshapiro * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2864562Sgshapiro * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2964562Sgshapiro * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3090792Sgshapiro *
3164562Sgshapiro *   $FreeBSD: head/sys/dev/sn/if_sn.c 81122 2001-08-04 05:27:52Z imp $
3290792Sgshapiro */
3364562Sgshapiro
3464562Sgshapiro/*
3564562Sgshapiro * This is a driver for SMC's 9000 series of Ethernet adapters.
3690792Sgshapiro *
3790792Sgshapiro * This FreeBSD driver is derived from the smc9194 Linux driver by
3890792Sgshapiro * Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman.
3990792Sgshapiro * This driver also shamelessly borrows from the FreeBSD ep driver
4064562Sgshapiro * which is Copyright (C) 1994 Herb Peyerl <hpeyerl@novatel.ca>
4190792Sgshapiro * All rights reserved.
4290792Sgshapiro *
4364562Sgshapiro * It is set up for my SMC91C92 equipped Ampro LittleBoard embedded
4464562Sgshapiro * PC.  It is adapted from Erik Stahlman's Linux driver which worked
4564562Sgshapiro * with his EFA Info*Express SVC VLB adaptor.  According to SMC's databook,
4664562Sgshapiro * it will work for the entire SMC 9xxx series. (Ha Ha)
4771345Sgshapiro *
4864562Sgshapiro * "Features" of the SMC chip:
4964562Sgshapiro *   4608 byte packet memory. (for the 91C92.  Others have more)
5090792Sgshapiro *   EEPROM for configuration
5164562Sgshapiro *   AUI/TP selection
5264562Sgshapiro *
5364562Sgshapiro * Authors:
5464562Sgshapiro *      Erik Stahlman                   erik@vt.edu
5564562Sgshapiro *      Herb Peyerl                     hpeyerl@novatel.ca
5664562Sgshapiro *      Andres Vega Garcia              avega@sophia.inria.fr
5764562Sgshapiro *      Serge Babkin                    babkin@hq.icb.chel.su
5864562Sgshapiro *      Gardner Buchanan                gbuchanan@shl.com
5990792Sgshapiro *
6064562Sgshapiro * Sources:
6164562Sgshapiro *    o   SMC databook
6264562Sgshapiro *    o   "smc9194.c:v0.10(FIXED) 02/15/96 by Erik Stahlman (erik@vt.edu)"
6390792Sgshapiro *    o   "if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp"
6464562Sgshapiro *
6564562Sgshapiro * Known Bugs:
6664562Sgshapiro *    o   The hardware multicast filter isn't used yet.
6764562Sgshapiro *    o   Setting of the hardware address isn't supported.
6864562Sgshapiro *    o   Hardware padding isn't used.
6964562Sgshapiro */
7064562Sgshapiro
7164562Sgshapiro/*
7264562Sgshapiro * Modifications for Megahertz X-Jack Ethernet Card (XJ-10BT)
7364562Sgshapiro *
7464562Sgshapiro * Copyright (c) 1996 by Tatsumi Hosokawa <hosokawa@jp.FreeBSD.org>
7590792Sgshapiro *                       BSD-nomads, Tokyo, Japan.
7664562Sgshapiro */
7790792Sgshapiro/*
7864562Sgshapiro * Multicast support by Kei TANAKA <kei@pal.xerox.com>
7964562Sgshapiro * Special thanks to itojun@itojun.org
8090792Sgshapiro */
8164562Sgshapiro
8264562Sgshapiro#include <sys/param.h>
8364562Sgshapiro#include <sys/systm.h>
8464562Sgshapiro#include <sys/errno.h>
8564562Sgshapiro#include <sys/sockio.h>
8664562Sgshapiro#include <sys/mbuf.h>
8764562Sgshapiro#include <sys/socket.h>
8864562Sgshapiro#include <sys/syslog.h>
8964562Sgshapiro
9090792Sgshapiro#include <sys/module.h>
9164562Sgshapiro#include <sys/bus.h>
9264562Sgshapiro
9364562Sgshapiro#include <machine/bus.h>
9490792Sgshapiro#include <machine/resource.h>
9564562Sgshapiro#include <sys/rman.h>
9664562Sgshapiro
9764562Sgshapiro#include <net/ethernet.h>
9864562Sgshapiro#include <net/if.h>
9964562Sgshapiro#include <net/if_arp.h>
10064562Sgshapiro#include <net/if_dl.h>
10164562Sgshapiro#include <net/if_types.h>
10264562Sgshapiro#include <net/if_mib.h>
10364562Sgshapiro
10464562Sgshapiro#ifdef INET
10564562Sgshapiro#include <netinet/in.h>
10664562Sgshapiro#include <netinet/in_systm.h>
10790792Sgshapiro#include <netinet/in_var.h>
10864562Sgshapiro#include <netinet/ip.h>
10964562Sgshapiro#endif
11090792Sgshapiro
11164562Sgshapiro#ifdef NS
11264562Sgshapiro#include <netns/ns.h>
11390792Sgshapiro#include <netns/ns_if.h>
11464562Sgshapiro#endif
11564562Sgshapiro
11664562Sgshapiro#include <net/bpf.h>
11764562Sgshapiro#include <net/bpfdesc.h>
11864562Sgshapiro
11964562Sgshapiro
12064562Sgshapiro#include <dev/sn/if_snreg.h>
12164562Sgshapiro#include <dev/sn/if_snvar.h>
12264562Sgshapiro
12364562Sgshapiro/* Exported variables */
12464562Sgshapirodevclass_t sn_devclass;
12564562Sgshapiro
12664562Sgshapirostatic int snioctl(struct ifnet * ifp, u_long, caddr_t);
12764562Sgshapiro
12890792Sgshapirostatic void snresume(struct ifnet *);
12964562Sgshapiro
13064562Sgshapirovoid sninit(void *);
13190792Sgshapirovoid snread(struct ifnet *);
13264562Sgshapirovoid snreset(struct sn_softc *);
13364562Sgshapirovoid snstart(struct ifnet *);
13490792Sgshapirovoid snstop(struct sn_softc *);
13564562Sgshapirovoid snwatchdog(struct ifnet *);
13664562Sgshapiro
13764562Sgshapirostatic void sn_setmcast(struct sn_softc *);
13864562Sgshapirostatic int sn_getmcf(struct arpcom *ac, u_char *mcf);
13964562Sgshapirostatic u_int smc_crc(u_char *);
14064562Sgshapiro
14164562Sgshapiro/* I (GB) have been unlucky getting the hardware padding
14264562Sgshapiro * to work properly.
14364562Sgshapiro */
14464562Sgshapiro#define SW_PAD
14590792Sgshapiro
14690792Sgshapirostatic const char *chip_ids[15] = {
14764562Sgshapiro	NULL, NULL, NULL,
14890792Sgshapiro	 /* 3 */ "SMC91C90/91C92",
14964562Sgshapiro	 /* 4 */ "SMC91C94",
15064562Sgshapiro	 /* 5 */ "SMC91C95",
15164562Sgshapiro	NULL,
15264562Sgshapiro	 /* 7 */ "SMC91C100",
15364562Sgshapiro	 /* 8 */ "SMC91C100FD",
15464562Sgshapiro	NULL, NULL, NULL,
15564562Sgshapiro	NULL, NULL, NULL
15664562Sgshapiro};
15764562Sgshapiro
15864562Sgshapiroint
15964562Sgshapirosn_attach(device_t dev)
16090792Sgshapiro{
16190792Sgshapiro	struct sn_softc *sc = device_get_softc(dev);
16264562Sgshapiro	struct ifnet   *ifp = &sc->arpcom.ac_if;
16390792Sgshapiro	u_short         i;
16464562Sgshapiro	u_char         *p;
16564562Sgshapiro	struct ifaddr  *ifa;
16664562Sgshapiro	struct sockaddr_dl *sdl;
16764562Sgshapiro	int             rev;
16864562Sgshapiro	u_short         address;
16964562Sgshapiro	int		j;
17064562Sgshapiro
17164562Sgshapiro	sn_activate(dev);
17264562Sgshapiro
17364562Sgshapiro	snstop(sc);
17490792Sgshapiro
17564562Sgshapiro	sc->dev = dev;
17690792Sgshapiro	sc->pages_wanted = -1;
17764562Sgshapiro
17866494Sgshapiro	device_printf(dev, " ");
17964562Sgshapiro
18064562Sgshapiro	SMC_SELECT_BANK(3);
18164562Sgshapiro	rev = inw(BASE + REVISION_REG_W);
18264562Sgshapiro	if (chip_ids[(rev >> 4) & 0xF])
18364562Sgshapiro		printf("%s ", chip_ids[(rev >> 4) & 0xF]);
18464562Sgshapiro
18564562Sgshapiro	SMC_SELECT_BANK(1);
18664562Sgshapiro	i = inw(BASE + CONFIG_REG_W);
18764562Sgshapiro	printf(i & CR_AUI_SELECT ? "AUI" : "UTP");
18864562Sgshapiro
18964562Sgshapiro	if (sc->pccard_enaddr)
19066494Sgshapiro		for (j = 0; j < 3; j++) {
19164562Sgshapiro			u_short	w;
19264562Sgshapiro
19364562Sgshapiro			w = (u_short)sc->arpcom.ac_enaddr[j * 2] |
19490792Sgshapiro				(((u_short)sc->arpcom.ac_enaddr[j * 2 + 1]) << 8);
19564562Sgshapiro			outw(BASE + IAR_ADDR0_REG_W + j * 2, w);
19664562Sgshapiro		}
19764562Sgshapiro
19864562Sgshapiro	/*
19964562Sgshapiro	 * Read the station address from the chip. The MAC address is bank 1,
20064562Sgshapiro	 * regs 4 - 9
20164562Sgshapiro	 */
20264562Sgshapiro	SMC_SELECT_BANK(1);
20390792Sgshapiro	p = (u_char *) & sc->arpcom.ac_enaddr;
20464562Sgshapiro	for (i = 0; i < 6; i += 2) {
20564562Sgshapiro		address = inw(BASE + IAR_ADDR0_REG_W + i);
20664562Sgshapiro		p[i + 1] = address >> 8;
20790792Sgshapiro		p[i] = address & 0xFF;
20864562Sgshapiro	}
20964562Sgshapiro	printf(" MAC address %6D\n", sc->arpcom.ac_enaddr, ":");
21064562Sgshapiro	ifp->if_softc = sc;
21164562Sgshapiro	ifp->if_unit = device_get_unit(dev);
21264562Sgshapiro	ifp->if_name = "sn";
21364562Sgshapiro	ifp->if_mtu = ETHERMTU;
21464562Sgshapiro	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
21564562Sgshapiro	ifp->if_output = ether_output;
21664562Sgshapiro	ifp->if_start = snstart;
21764562Sgshapiro	ifp->if_ioctl = snioctl;
21890792Sgshapiro	ifp->if_watchdog = snwatchdog;
21990792Sgshapiro	ifp->if_init = sninit;
22090792Sgshapiro	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
22164562Sgshapiro	ifp->if_timer = 0;
22290792Sgshapiro
22364562Sgshapiro	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
22464562Sgshapiro
22564562Sgshapiro	/*
22664562Sgshapiro	 * Fill the hardware address into ifa_addr if we find an AF_LINK
22764562Sgshapiro	 * entry. We need to do this so bpf's can get the hardware addr of
22864562Sgshapiro	 * this card. netstat likes this too!
22964562Sgshapiro	 */
23064562Sgshapiro	ifa = TAILQ_FIRST(&ifp->if_addrhead);
23164562Sgshapiro	while ((ifa != 0) && (ifa->ifa_addr != 0) &&
23264562Sgshapiro	       (ifa->ifa_addr->sa_family != AF_LINK))
23364562Sgshapiro		ifa = TAILQ_NEXT(ifa, ifa_link);
23464562Sgshapiro
23564562Sgshapiro	if ((ifa != 0) && (ifa->ifa_addr != 0)) {
23664562Sgshapiro		sdl = (struct sockaddr_dl *) ifa->ifa_addr;
23790792Sgshapiro		sdl->sdl_type = IFT_ETHER;
23864562Sgshapiro		sdl->sdl_alen = ETHER_ADDR_LEN;
23964562Sgshapiro		sdl->sdl_slen = 0;
24064562Sgshapiro		bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
24190792Sgshapiro	}
24264562Sgshapiro
24364562Sgshapiro	return 0;
24490792Sgshapiro}
24564562Sgshapiro
24690792Sgshapiro
24764562Sgshapiroint
24864562Sgshapirosn_detach(device_t dev)
24964562Sgshapiro{
25064562Sgshapiro	struct sn_softc *sc = device_get_softc(dev);
25164562Sgshapiro
25264562Sgshapiro	sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
25390792Sgshapiro	ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
25464562Sgshapiro	sn_deactivate(dev);
25564562Sgshapiro	return 0;
25664562Sgshapiro}
25764562Sgshapiro
25864562Sgshapiro/*
25964562Sgshapiro * Reset and initialize the chip
26064562Sgshapiro */
26164562Sgshapirovoid
26264562Sgshapirosninit(void *xsc)
26364562Sgshapiro{
26464562Sgshapiro	register struct sn_softc *sc = xsc;
26590792Sgshapiro	register struct ifnet *ifp = &sc->arpcom.ac_if;
26664562Sgshapiro	int             s;
26764562Sgshapiro	int             flags;
26864562Sgshapiro	int             mask;
26990792Sgshapiro
27064562Sgshapiro	s = splimp();
27164562Sgshapiro
27264562Sgshapiro	/*
27364562Sgshapiro	 * This resets the registers mostly to defaults, but doesn't affect
27464562Sgshapiro	 * EEPROM.  After the reset cycle, we pause briefly for the chip to
27564562Sgshapiro	 * be happy.
27664562Sgshapiro	 */
27764562Sgshapiro	SMC_SELECT_BANK(0);
27864562Sgshapiro	outw(BASE + RECV_CONTROL_REG_W, RCR_SOFTRESET);
27964562Sgshapiro	SMC_DELAY();
28064562Sgshapiro	outw(BASE + RECV_CONTROL_REG_W, 0x0000);
28164562Sgshapiro	SMC_DELAY();
28264562Sgshapiro	SMC_DELAY();
28364562Sgshapiro
28464562Sgshapiro	outw(BASE + TXMIT_CONTROL_REG_W, 0x0000);
28590792Sgshapiro
28690792Sgshapiro	/*
28790792Sgshapiro	 * Set the control register to automatically release succesfully
28864562Sgshapiro	 * transmitted packets (making the best use out of our limited
28964562Sgshapiro	 * memory) and to enable the EPH interrupt on certain TX errors.
29064562Sgshapiro	 */
29164562Sgshapiro	SMC_SELECT_BANK(1);
29264562Sgshapiro	outw(BASE + CONTROL_REG_W, (CTR_AUTO_RELEASE | CTR_TE_ENABLE |
29364562Sgshapiro				    CTR_CR_ENABLE | CTR_LE_ENABLE));
29464562Sgshapiro
29564562Sgshapiro	/* Set squelch level to 240mV (default 480mV) */
29664562Sgshapiro	flags = inw(BASE + CONFIG_REG_W);
29764562Sgshapiro	flags |= CR_SET_SQLCH;
29864562Sgshapiro	outw(BASE + CONFIG_REG_W, flags);
29964562Sgshapiro
30064562Sgshapiro	/*
30171345Sgshapiro	 * Reset the MMU and wait for it to be un-busy.
30264562Sgshapiro	 */
30371345Sgshapiro	SMC_SELECT_BANK(2);
30471345Sgshapiro	outw(BASE + MMU_CMD_REG_W, MMUCR_RESET);
30564562Sgshapiro	while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
30664562Sgshapiro		;
30764562Sgshapiro
30890792Sgshapiro	/*
30964562Sgshapiro	 * Disable all interrupts
31064562Sgshapiro	 */
31190792Sgshapiro	outb(BASE + INTR_MASK_REG_B, 0x00);
31264562Sgshapiro
31364562Sgshapiro	sn_setmcast(sc);
31464562Sgshapiro
31564562Sgshapiro	/*
31664562Sgshapiro	 * Set the transmitter control.  We want it enabled.
31764562Sgshapiro	 */
31864562Sgshapiro	flags = TCR_ENABLE;
31964562Sgshapiro
32064562Sgshapiro#ifndef SW_PAD
32164562Sgshapiro	/*
32264562Sgshapiro	 * I (GB) have been unlucky getting this to work.
32364562Sgshapiro	 */
32490792Sgshapiro	flags |= TCR_PAD_ENABLE;
32564562Sgshapiro#endif	/* SW_PAD */
32690792Sgshapiro
32764562Sgshapiro	outw(BASE + TXMIT_CONTROL_REG_W, flags);
32864562Sgshapiro
32964562Sgshapiro
33064562Sgshapiro	/*
33164562Sgshapiro	 * Now, enable interrupts
33264562Sgshapiro	 */
33364562Sgshapiro	SMC_SELECT_BANK(2);
33464562Sgshapiro
33564562Sgshapiro	mask = IM_EPH_INT |
33664562Sgshapiro		IM_RX_OVRN_INT |
33764562Sgshapiro		IM_RCV_INT |
33864562Sgshapiro		IM_TX_INT;
33964562Sgshapiro
34064562Sgshapiro	outb(BASE + INTR_MASK_REG_B, mask);
34164562Sgshapiro	sc->intr_mask = mask;
34264562Sgshapiro	sc->pages_wanted = -1;
34364562Sgshapiro
34464562Sgshapiro
34564562Sgshapiro	/*
34664562Sgshapiro	 * Mark the interface running but not active.
34764562Sgshapiro	 */
34864562Sgshapiro	ifp->if_flags |= IFF_RUNNING;
34964562Sgshapiro	ifp->if_flags &= ~IFF_OACTIVE;
35064562Sgshapiro
35164562Sgshapiro	/*
35264562Sgshapiro	 * Attempt to push out any waiting packets.
35364562Sgshapiro	 */
35464562Sgshapiro	snstart(ifp);
35564562Sgshapiro
35664562Sgshapiro	splx(s);
35764562Sgshapiro}
35866494Sgshapiro
35966494Sgshapiro
36064562Sgshapirovoid
361snstart(struct ifnet *ifp)
362{
363	register struct sn_softc *sc = ifp->if_softc;
364	register u_int  len;
365	register struct mbuf *m;
366	struct mbuf    *top;
367	int             s, pad;
368	int             mask;
369	u_short         length;
370	u_short         numPages;
371	u_char          packet_no;
372	int             time_out;
373	int		junk = 0;
374
375	s = splimp();
376
377	if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
378		splx(s);
379		return;
380	}
381	if (sc->pages_wanted != -1) {
382		splx(s);
383		printf("sn%d: snstart() while memory allocation pending\n",
384		       ifp->if_unit);
385		return;
386	}
387startagain:
388
389	/*
390	 * Sneak a peek at the next packet
391	 */
392	m = sc->arpcom.ac_if.if_snd.ifq_head;
393	if (m == 0) {
394		splx(s);
395		return;
396	}
397	/*
398	 * Compute the frame length and set pad to give an overall even
399	 * number of bytes.  Below we assume that the packet length is even.
400	 */
401	for (len = 0, top = m; m; m = m->m_next)
402		len += m->m_len;
403
404	pad = (len & 1);
405
406	/*
407	 * We drop packets that are too large. Perhaps we should truncate
408	 * them instead?
409	 */
410	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
411		printf("sn%d: large packet discarded (A)\n", ifp->if_unit);
412		++sc->arpcom.ac_if.if_oerrors;
413		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
414		m_freem(m);
415		goto readcheck;
416	}
417#ifdef SW_PAD
418
419	/*
420	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
421	 */
422	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
423		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
424
425#endif	/* SW_PAD */
426
427	length = pad + len;
428
429	/*
430	 * The MMU wants the number of pages to be the number of 256 byte
431	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
432	 * include space for the status word, byte count and control bytes in
433	 * the allocation request.
434	 */
435	numPages = (length + 6) >> 8;
436
437
438	/*
439	 * Now, try to allocate the memory
440	 */
441	SMC_SELECT_BANK(2);
442	outw(BASE + MMU_CMD_REG_W, MMUCR_ALLOC | numPages);
443
444	/*
445	 * Wait a short amount of time to see if the allocation request
446	 * completes.  Otherwise, I enable the interrupt and wait for
447	 * completion asyncronously.
448	 */
449
450	time_out = MEMORY_WAIT_TIME;
451	do {
452		if (inb(BASE + INTR_STAT_REG_B) & IM_ALLOC_INT)
453			break;
454	} while (--time_out);
455
456	if (!time_out || junk > 10) {
457
458		/*
459		 * No memory now.  Oh well, wait until the chip finds memory
460		 * later.   Remember how many pages we were asking for and
461		 * enable the allocation completion interrupt. Also set a
462		 * watchdog in case  we miss the interrupt. We mark the
463		 * interface active since there is no point in attempting an
464		 * snstart() until after the memory is available.
465		 */
466		mask = inb(BASE + INTR_MASK_REG_B) | IM_ALLOC_INT;
467		outb(BASE + INTR_MASK_REG_B, mask);
468		sc->intr_mask = mask;
469
470		sc->arpcom.ac_if.if_timer = 1;
471		sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
472		sc->pages_wanted = numPages;
473
474		splx(s);
475		return;
476	}
477	/*
478	 * The memory allocation completed.  Check the results.
479	 */
480	packet_no = inb(BASE + ALLOC_RESULT_REG_B);
481	if (packet_no & ARR_FAILED) {
482		if (junk++ > 10)
483			printf("sn%d: Memory allocation failed\n", ifp->if_unit);
484		goto startagain;
485	}
486	/*
487	 * We have a packet number, so tell the card to use it.
488	 */
489	outb(BASE + PACKET_NUM_REG_B, packet_no);
490
491	/*
492	 * Point to the beginning of the packet
493	 */
494	outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000);
495
496	/*
497	 * Send the packet length (+6 for status, length and control byte)
498	 * and the status word (set to zeros)
499	 */
500	outw(BASE + DATA_REG_W, 0);
501	outb(BASE + DATA_REG_B, (length + 6) & 0xFF);
502	outb(BASE + DATA_REG_B, (length + 6) >> 8);
503
504	/*
505	 * Get the packet from the kernel.  This will include the Ethernet
506	 * frame header, MAC Addresses etc.
507	 */
508	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
509
510	/*
511	 * Push out the data to the card.
512	 */
513	for (top = m; m != 0; m = m->m_next) {
514
515		/*
516		 * Push out words.
517		 */
518		outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2);
519
520		/*
521		 * Push out remaining byte.
522		 */
523		if (m->m_len & 1)
524			outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
525	}
526
527	/*
528	 * Push out padding.
529	 */
530	while (pad > 1) {
531		outw(BASE + DATA_REG_W, 0);
532		pad -= 2;
533	}
534	if (pad)
535		outb(BASE + DATA_REG_B, 0);
536
537	/*
538	 * Push out control byte and unused packet byte The control byte is 0
539	 * meaning the packet is even lengthed and no special CRC handling is
540	 * desired.
541	 */
542	outw(BASE + DATA_REG_W, 0);
543
544	/*
545	 * Enable the interrupts and let the chipset deal with it Also set a
546	 * watchdog in case we miss the interrupt.
547	 */
548	mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
549	outb(BASE + INTR_MASK_REG_B, mask);
550	sc->intr_mask = mask;
551
552	outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE);
553
554	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
555	sc->arpcom.ac_if.if_timer = 1;
556
557	if (ifp->if_bpf) {
558		bpf_mtap(ifp, top);
559	}
560
561	sc->arpcom.ac_if.if_opackets++;
562	m_freem(top);
563
564
565readcheck:
566
567	/*
568	 * Is another packet coming in?  We don't want to overflow the tiny
569	 * RX FIFO.  If nothing has arrived then attempt to queue another
570	 * transmit packet.
571	 */
572	if (inw(BASE + FIFO_PORTS_REG_W) & FIFO_REMPTY)
573		goto startagain;
574
575	splx(s);
576	return;
577}
578
579
580
581/* Resume a packet transmit operation after a memory allocation
582 * has completed.
583 *
584 * This is basically a hacked up copy of snstart() which handles
585 * a completed memory allocation the same way snstart() does.
586 * It then passes control to snstart to handle any other queued
587 * packets.
588 */
589static void
590snresume(struct ifnet *ifp)
591{
592	register struct sn_softc *sc = ifp->if_softc;
593	register u_int  len;
594	register struct mbuf *m;
595	struct mbuf    *top;
596	int             pad;
597	int             mask;
598	u_short         length;
599	u_short         numPages;
600	u_short         pages_wanted;
601	u_char          packet_no;
602
603	if (sc->pages_wanted < 0)
604		return;
605
606	pages_wanted = sc->pages_wanted;
607	sc->pages_wanted = -1;
608
609	/*
610	 * Sneak a peek at the next packet
611	 */
612	m = sc->arpcom.ac_if.if_snd.ifq_head;
613	if (m == 0) {
614		printf("sn%d: snresume() with nothing to send\n", ifp->if_unit);
615		return;
616	}
617	/*
618	 * Compute the frame length and set pad to give an overall even
619	 * number of bytes.  Below we assume that the packet length is even.
620	 */
621	for (len = 0, top = m; m; m = m->m_next)
622		len += m->m_len;
623
624	pad = (len & 1);
625
626	/*
627	 * We drop packets that are too large. Perhaps we should truncate
628	 * them instead?
629	 */
630	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
631		printf("sn%d: large packet discarded (B)\n", ifp->if_unit);
632		++sc->arpcom.ac_if.if_oerrors;
633		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
634		m_freem(m);
635		return;
636	}
637#ifdef SW_PAD
638
639	/*
640	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
641	 */
642	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
643		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
644
645#endif	/* SW_PAD */
646
647	length = pad + len;
648
649
650	/*
651	 * The MMU wants the number of pages to be the number of 256 byte
652	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
653	 * include space for the status word, byte count and control bytes in
654	 * the allocation request.
655	 */
656	numPages = (length + 6) >> 8;
657
658
659	SMC_SELECT_BANK(2);
660
661	/*
662	 * The memory allocation completed.  Check the results. If it failed,
663	 * we simply set a watchdog timer and hope for the best.
664	 */
665	packet_no = inb(BASE + ALLOC_RESULT_REG_B);
666	if (packet_no & ARR_FAILED) {
667		printf("sn%d: Memory allocation failed.  Weird.\n", ifp->if_unit);
668		sc->arpcom.ac_if.if_timer = 1;
669		goto try_start;
670	}
671	/*
672	 * We have a packet number, so tell the card to use it.
673	 */
674	outb(BASE + PACKET_NUM_REG_B, packet_no);
675
676	/*
677	 * Now, numPages should match the pages_wanted recorded when the
678	 * memory allocation was initiated.
679	 */
680	if (pages_wanted != numPages) {
681		printf("sn%d: memory allocation wrong size.  Weird.\n", ifp->if_unit);
682		/*
683		 * If the allocation was the wrong size we simply release the
684		 * memory once it is granted. Wait for the MMU to be un-busy.
685		 */
686		while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
687			;
688		outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT);
689
690		return;
691	}
692	/*
693	 * Point to the beginning of the packet
694	 */
695	outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000);
696
697	/*
698	 * Send the packet length (+6 for status, length and control byte)
699	 * and the status word (set to zeros)
700	 */
701	outw(BASE + DATA_REG_W, 0);
702	outb(BASE + DATA_REG_B, (length + 6) & 0xFF);
703	outb(BASE + DATA_REG_B, (length + 6) >> 8);
704
705	/*
706	 * Get the packet from the kernel.  This will include the Ethernet
707	 * frame header, MAC Addresses etc.
708	 */
709	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
710
711	/*
712	 * Push out the data to the card.
713	 */
714	for (top = m; m != 0; m = m->m_next) {
715
716		/*
717		 * Push out words.
718		 */
719		outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2);
720
721		/*
722		 * Push out remaining byte.
723		 */
724		if (m->m_len & 1)
725			outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
726	}
727
728	/*
729	 * Push out padding.
730	 */
731	while (pad > 1) {
732		outw(BASE + DATA_REG_W, 0);
733		pad -= 2;
734	}
735	if (pad)
736		outb(BASE + DATA_REG_B, 0);
737
738	/*
739	 * Push out control byte and unused packet byte The control byte is 0
740	 * meaning the packet is even lengthed and no special CRC handling is
741	 * desired.
742	 */
743	outw(BASE + DATA_REG_W, 0);
744
745	/*
746	 * Enable the interrupts and let the chipset deal with it Also set a
747	 * watchdog in case we miss the interrupt.
748	 */
749	mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
750	outb(BASE + INTR_MASK_REG_B, mask);
751	sc->intr_mask = mask;
752	outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE);
753
754	if (ifp->if_bpf) {
755		bpf_mtap(ifp, top);
756	}
757
758	sc->arpcom.ac_if.if_opackets++;
759	m_freem(top);
760
761try_start:
762
763	/*
764	 * Now pass control to snstart() to queue any additional packets
765	 */
766	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
767	snstart(ifp);
768
769	/*
770	 * We've sent something, so we're active.  Set a watchdog in case the
771	 * TX_EMPTY interrupt is lost.
772	 */
773	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
774	sc->arpcom.ac_if.if_timer = 1;
775
776	return;
777}
778
779
780void
781sn_intr(void *arg)
782{
783	int             status, interrupts;
784	register struct sn_softc *sc = (struct sn_softc *) arg;
785	struct ifnet   *ifp = &sc->arpcom.ac_if;
786	int             x;
787
788	/*
789	 * Chip state registers
790	 */
791	u_char          mask;
792	u_char          packet_no;
793	u_short         tx_status;
794	u_short         card_stats;
795
796	/*
797	 * if_ep.c did this, so I do too.  Yet if_ed.c doesn't. I wonder...
798	 */
799	x = splbio();
800
801	/*
802	 * Clear the watchdog.
803	 */
804	ifp->if_timer = 0;
805
806	SMC_SELECT_BANK(2);
807
808	/*
809	 * Obtain the current interrupt mask and clear the hardware mask
810	 * while servicing interrupts.
811	 */
812	mask = inb(BASE + INTR_MASK_REG_B);
813	outb(BASE + INTR_MASK_REG_B, 0x00);
814
815	/*
816	 * Get the set of interrupts which occurred and eliminate any which
817	 * are masked.
818	 */
819	interrupts = inb(BASE + INTR_STAT_REG_B);
820	status = interrupts & mask;
821
822	/*
823	 * Now, process each of the interrupt types.
824	 */
825
826	/*
827	 * Receive Overrun.
828	 */
829	if (status & IM_RX_OVRN_INT) {
830
831		/*
832		 * Acknowlege Interrupt
833		 */
834		SMC_SELECT_BANK(2);
835		outb(BASE + INTR_ACK_REG_B, IM_RX_OVRN_INT);
836
837		++sc->arpcom.ac_if.if_ierrors;
838	}
839	/*
840	 * Got a packet.
841	 */
842	if (status & IM_RCV_INT) {
843#if 1
844		int             packet_number;
845
846		SMC_SELECT_BANK(2);
847		packet_number = inw(BASE + FIFO_PORTS_REG_W);
848
849		if (packet_number & FIFO_REMPTY) {
850
851			/*
852			 * we got called , but nothing was on the FIFO
853			 */
854			printf("sn: Receive interrupt with nothing on FIFO\n");
855
856			goto out;
857		}
858#endif
859		snread(ifp);
860	}
861	/*
862	 * An on-card memory allocation came through.
863	 */
864	if (status & IM_ALLOC_INT) {
865
866		/*
867		 * Disable this interrupt.
868		 */
869		mask &= ~IM_ALLOC_INT;
870		sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
871		snresume(&sc->arpcom.ac_if);
872	}
873	/*
874	 * TX Completion.  Handle a transmit error message. This will only be
875	 * called when there is an error, because of the AUTO_RELEASE mode.
876	 */
877	if (status & IM_TX_INT) {
878
879		/*
880		 * Acknowlege Interrupt
881		 */
882		SMC_SELECT_BANK(2);
883		outb(BASE + INTR_ACK_REG_B, IM_TX_INT);
884
885		packet_no = inw(BASE + FIFO_PORTS_REG_W);
886		packet_no &= FIFO_TX_MASK;
887
888		/*
889		 * select this as the packet to read from
890		 */
891		outb(BASE + PACKET_NUM_REG_B, packet_no);
892
893		/*
894		 * Position the pointer to the first word from this packet
895		 */
896		outw(BASE + POINTER_REG_W, PTR_AUTOINC | PTR_READ | 0x0000);
897
898		/*
899		 * Fetch the TX status word.  The value found here will be a
900		 * copy of the EPH_STATUS_REG_W at the time the transmit
901		 * failed.
902		 */
903		tx_status = inw(BASE + DATA_REG_W);
904
905		if (tx_status & EPHSR_TX_SUC) {
906			device_printf(sc->dev,
907			    "Successful packet caused interrupt\n");
908		} else {
909			++sc->arpcom.ac_if.if_oerrors;
910		}
911
912		if (tx_status & EPHSR_LATCOL)
913			++sc->arpcom.ac_if.if_collisions;
914
915		/*
916		 * Some of these errors will have disabled transmit.
917		 * Re-enable transmit now.
918		 */
919		SMC_SELECT_BANK(0);
920
921#ifdef SW_PAD
922		outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE);
923#else
924		outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE | TCR_PAD_ENABLE);
925#endif	/* SW_PAD */
926
927		/*
928		 * kill the failed packet. Wait for the MMU to be un-busy.
929		 */
930		SMC_SELECT_BANK(2);
931		while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
932			;
933		outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT);
934
935		/*
936		 * Attempt to queue more transmits.
937		 */
938		sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
939		snstart(&sc->arpcom.ac_if);
940	}
941	/*
942	 * Transmit underrun.  We use this opportunity to update transmit
943	 * statistics from the card.
944	 */
945	if (status & IM_TX_EMPTY_INT) {
946
947		/*
948		 * Acknowlege Interrupt
949		 */
950		SMC_SELECT_BANK(2);
951		outb(BASE + INTR_ACK_REG_B, IM_TX_EMPTY_INT);
952
953		/*
954		 * Disable this interrupt.
955		 */
956		mask &= ~IM_TX_EMPTY_INT;
957
958		SMC_SELECT_BANK(0);
959		card_stats = inw(BASE + COUNTER_REG_W);
960
961		/*
962		 * Single collisions
963		 */
964		sc->arpcom.ac_if.if_collisions += card_stats & ECR_COLN_MASK;
965
966		/*
967		 * Multiple collisions
968		 */
969		sc->arpcom.ac_if.if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
970
971		SMC_SELECT_BANK(2);
972
973		/*
974		 * Attempt to enqueue some more stuff.
975		 */
976		sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
977		snstart(&sc->arpcom.ac_if);
978	}
979	/*
980	 * Some other error.  Try to fix it by resetting the adapter.
981	 */
982	if (status & IM_EPH_INT) {
983		snstop(sc);
984		sninit(sc);
985	}
986
987out:
988	/*
989	 * Handled all interrupt sources.
990	 */
991
992	SMC_SELECT_BANK(2);
993
994	/*
995	 * Reestablish interrupts from mask which have not been deselected
996	 * during this interrupt.  Note that the hardware mask, which was set
997	 * to 0x00 at the start of this service routine, may have been
998	 * updated by one or more of the interrupt handers and we must let
999	 * those new interrupts stay enabled here.
1000	 */
1001	mask |= inb(BASE + INTR_MASK_REG_B);
1002	outb(BASE + INTR_MASK_REG_B, mask);
1003	sc->intr_mask = mask;
1004
1005	splx(x);
1006}
1007
1008void
1009snread(register struct ifnet *ifp)
1010{
1011        struct sn_softc *sc = ifp->if_softc;
1012	struct ether_header *eh;
1013	struct mbuf    *m;
1014	short           status;
1015	int             packet_number;
1016	u_short         packet_length;
1017	u_char         *data;
1018
1019	SMC_SELECT_BANK(2);
1020#if 0
1021	packet_number = inw(BASE + FIFO_PORTS_REG_W);
1022
1023	if (packet_number & FIFO_REMPTY) {
1024
1025		/*
1026		 * we got called , but nothing was on the FIFO
1027		 */
1028		printf("sn: Receive interrupt with nothing on FIFO\n");
1029		return;
1030	}
1031#endif
1032read_another:
1033
1034	/*
1035	 * Start reading from the start of the packet. Since PTR_RCV is set,
1036	 * packet number is found in FIFO_PORTS_REG_W, FIFO_RX_MASK.
1037	 */
1038	outw(BASE + POINTER_REG_W, PTR_READ | PTR_RCV | PTR_AUTOINC | 0x0000);
1039
1040	/*
1041	 * First two words are status and packet_length
1042	 */
1043	status = inw(BASE + DATA_REG_W);
1044	packet_length = inw(BASE + DATA_REG_W) & RLEN_MASK;
1045
1046	/*
1047	 * The packet length contains 3 extra words: status, length, and a
1048	 * extra word with the control byte.
1049	 */
1050	packet_length -= 6;
1051
1052	/*
1053	 * Account for receive errors and discard.
1054	 */
1055	if (status & RS_ERRORS) {
1056		++sc->arpcom.ac_if.if_ierrors;
1057		goto out;
1058	}
1059	/*
1060	 * A packet is received.
1061	 */
1062
1063	/*
1064	 * Adjust for odd-length packet.
1065	 */
1066	if (status & RS_ODDFRAME)
1067		packet_length++;
1068
1069	/*
1070	 * Allocate a header mbuf from the kernel.
1071	 */
1072	MGETHDR(m, M_DONTWAIT, MT_DATA);
1073	if (m == NULL)
1074		goto out;
1075
1076	m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1077	m->m_pkthdr.len = m->m_len = packet_length;
1078
1079	/*
1080	 * Attach an mbuf cluster
1081	 */
1082	MCLGET(m, M_DONTWAIT);
1083
1084	/*
1085	 * Insist on getting a cluster
1086	 */
1087	if ((m->m_flags & M_EXT) == 0) {
1088		m_freem(m);
1089		++sc->arpcom.ac_if.if_ierrors;
1090		printf("sn: snread() kernel memory allocation problem\n");
1091		goto out;
1092	}
1093	eh = mtod(m, struct ether_header *);
1094
1095	/*
1096	 * Get packet, including link layer address, from interface.
1097	 */
1098
1099	data = (u_char *) eh;
1100	insw(BASE + DATA_REG_W, data, packet_length >> 1);
1101	if (packet_length & 1) {
1102		data += packet_length & ~1;
1103		*data = inb(BASE + DATA_REG_B);
1104	}
1105	++sc->arpcom.ac_if.if_ipackets;
1106
1107	/*
1108	 * Remove link layer addresses and whatnot.
1109	 */
1110	m->m_pkthdr.len = m->m_len = packet_length - sizeof(struct ether_header);
1111	m->m_data += sizeof(struct ether_header);
1112
1113	ether_input(&sc->arpcom.ac_if, eh, m);
1114
1115out:
1116
1117	/*
1118	 * Error or good, tell the card to get rid of this packet Wait for
1119	 * the MMU to be un-busy.
1120	 */
1121	SMC_SELECT_BANK(2);
1122	while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
1123		;
1124	outw(BASE + MMU_CMD_REG_W, MMUCR_RELEASE);
1125
1126	/*
1127	 * Check whether another packet is ready
1128	 */
1129	packet_number = inw(BASE + FIFO_PORTS_REG_W);
1130	if (packet_number & FIFO_REMPTY) {
1131		return;
1132	}
1133	goto read_another;
1134}
1135
1136
1137/*
1138 * Handle IOCTLS.  This function is completely stolen from if_ep.c
1139 * As with its progenitor, it does not handle hardware address
1140 * changes.
1141 */
1142static int
1143snioctl(register struct ifnet *ifp, u_long cmd, caddr_t data)
1144{
1145	struct sn_softc *sc = ifp->if_softc;
1146	int             s, error = 0;
1147
1148	s = splimp();
1149
1150	switch (cmd) {
1151	case SIOCSIFADDR:
1152	case SIOCGIFADDR:
1153	case SIOCSIFMTU:
1154		error = ether_ioctl(ifp, cmd, data);
1155		break;
1156
1157	case SIOCSIFFLAGS:
1158		if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1159			ifp->if_flags &= ~IFF_RUNNING;
1160			snstop(sc);
1161			break;
1162		} else {
1163			/* reinitialize card on any parameter change */
1164			sninit(sc);
1165			break;
1166		}
1167		break;
1168
1169#ifdef notdef
1170	case SIOCGHWADDR:
1171		bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
1172		      sizeof(sc->sc_addr));
1173		break;
1174#endif
1175
1176	case SIOCADDMULTI:
1177	    /* update multicast filter list. */
1178	    sn_setmcast(sc);
1179	    error = 0;
1180	    break;
1181	case SIOCDELMULTI:
1182	    /* update multicast filter list. */
1183	    sn_setmcast(sc);
1184	    error = 0;
1185	    break;
1186	default:
1187		error = EINVAL;
1188	}
1189
1190	splx(s);
1191
1192	return (error);
1193}
1194
1195void
1196snreset(struct sn_softc *sc)
1197{
1198	int	s;
1199
1200	s = splimp();
1201	snstop(sc);
1202	sninit(sc);
1203
1204	splx(s);
1205}
1206
1207void
1208snwatchdog(struct ifnet *ifp)
1209{
1210	int	s;
1211	s = splimp();
1212	sn_intr(ifp->if_softc);
1213	splx(s);
1214}
1215
1216
1217/* 1. zero the interrupt mask
1218 * 2. clear the enable receive flag
1219 * 3. clear the enable xmit flags
1220 */
1221void
1222snstop(struct sn_softc *sc)
1223{
1224
1225	struct ifnet   *ifp = &sc->arpcom.ac_if;
1226
1227	/*
1228	 * Clear interrupt mask; disable all interrupts.
1229	 */
1230	SMC_SELECT_BANK(2);
1231	outb(BASE + INTR_MASK_REG_B, 0x00);
1232
1233	/*
1234	 * Disable transmitter and Receiver
1235	 */
1236	SMC_SELECT_BANK(0);
1237	outw(BASE + RECV_CONTROL_REG_W, 0x0000);
1238	outw(BASE + TXMIT_CONTROL_REG_W, 0x0000);
1239
1240	/*
1241	 * Cancel watchdog.
1242	 */
1243	ifp->if_timer = 0;
1244}
1245
1246
1247int
1248sn_activate(device_t dev)
1249{
1250	struct sn_softc *sc = device_get_softc(dev);
1251	int err;
1252
1253	sc->port_rid = 0;
1254	sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
1255	    0, ~0, SMC_IO_EXTENT, RF_ACTIVE);
1256	if (!sc->port_res) {
1257		if (bootverbose)
1258			device_printf(dev, "Cannot allocate ioport\n");
1259		return ENOMEM;
1260	}
1261
1262	sc->irq_rid = 0;
1263	sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
1264	    0, ~0, 1, RF_ACTIVE);
1265	if (!sc->irq_res) {
1266		if (bootverbose)
1267			device_printf(dev, "Cannot allocate irq\n");
1268		sn_deactivate(dev);
1269		return ENOMEM;
1270	}
1271	if ((err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, sn_intr, sc,
1272	    &sc->intrhand)) != 0) {
1273		sn_deactivate(dev);
1274		return err;
1275	}
1276
1277	sc->sn_io_addr = rman_get_start(sc->port_res);
1278	return (0);
1279}
1280
1281void
1282sn_deactivate(device_t dev)
1283{
1284	struct sn_softc *sc = device_get_softc(dev);
1285
1286	if (sc->intrhand)
1287		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
1288	sc->intrhand = 0;
1289	if (sc->port_res)
1290		bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
1291		    sc->port_res);
1292	sc->port_res = 0;
1293	if (sc->irq_res)
1294		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
1295		    sc->irq_res);
1296	sc->irq_res = 0;
1297	return;
1298}
1299
1300/*
1301 * Function: sn_probe( device_t dev, int pccard )
1302 *
1303 * Purpose:
1304 *      Tests to see if a given ioaddr points to an SMC9xxx chip.
1305 *      Tries to cause as little damage as possible if it's not a SMC chip.
1306 *      Returns a 0 on success
1307 *
1308 * Algorithm:
1309 *      (1) see if the high byte of BANK_SELECT is 0x33
1310 *      (2) compare the ioaddr with the base register's address
1311 *      (3) see if I recognize the chip ID in the appropriate register
1312 *
1313 *
1314 */
1315int
1316sn_probe(device_t dev, int pccard)
1317{
1318	struct sn_softc *sc = device_get_softc(dev);
1319	u_int           bank;
1320	u_short         revision_register;
1321	u_short         base_address_register;
1322	u_short		ioaddr;
1323	int		err;
1324
1325	if ((err = sn_activate(dev)) != 0)
1326		return err;
1327
1328	ioaddr = sc->sn_io_addr;
1329#ifdef SN_DEBUG
1330	device_printf(dev, "ioaddr is 0x%x\n", ioaddr);
1331#endif
1332	/*
1333	 * First, see if the high byte is 0x33
1334	 */
1335	bank = inw(ioaddr + BANK_SELECT_REG_W);
1336	if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
1337#ifdef	SN_DEBUG
1338		device_printf(dev, "test1 failed\n");
1339#endif
1340		goto error;
1341	}
1342	/*
1343	 * The above MIGHT indicate a device, but I need to write to further
1344	 * test this.  Go to bank 0, then test that the register still
1345	 * reports the high byte is 0x33.
1346	 */
1347	outw(ioaddr + BANK_SELECT_REG_W, 0x0000);
1348	bank = inw(ioaddr + BANK_SELECT_REG_W);
1349	if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
1350#ifdef	SN_DEBUG
1351		device_printf(dev, "test2 failed\n");
1352#endif
1353		goto error;
1354	}
1355	/*
1356	 * well, we've already written once, so hopefully another time won't
1357	 * hurt.  This time, I need to switch the bank register to bank 1, so
1358	 * I can access the base address register.  The contents of the
1359	 * BASE_ADDR_REG_W register, after some jiggery pokery, is expected
1360	 * to match the I/O port address where the adapter is being probed.
1361	 */
1362	outw(ioaddr + BANK_SELECT_REG_W, 0x0001);
1363	base_address_register = inw(ioaddr + BASE_ADDR_REG_W);
1364
1365	/*
1366	 * This test is nonsence on PC-card architecture, so if
1367	 * pccard == 1, skip this test. (hosokawa)
1368	 */
1369	if (!pccard && (ioaddr != (base_address_register >> 3 & 0x3E0))) {
1370
1371		/*
1372		 * Well, the base address register didn't match.  Must not
1373		 * have been a SMC chip after all.
1374		 */
1375#ifdef	SN_DEBUG
1376		device_printf(dev, "test3 failed ioaddr = 0x%x, "
1377		    "base_address_register = 0x%x\n", ioaddr,
1378		    base_address_register >> 3 & 0x3E0);
1379#endif
1380		goto error;
1381	}
1382
1383	/*
1384	 * Check if the revision register is something that I recognize.
1385	 * These might need to be added to later, as future revisions could
1386	 * be added.
1387	 */
1388	outw(ioaddr + BANK_SELECT_REG_W, 0x3);
1389	revision_register = inw(ioaddr + REVISION_REG_W);
1390	if (!chip_ids[(revision_register >> 4) & 0xF]) {
1391
1392		/*
1393		 * I don't regonize this chip, so...
1394		 */
1395#ifdef	SN_DEBUG
1396		device_printf(dev, "test4 failed\n");
1397#endif
1398		goto error;
1399	}
1400
1401	/*
1402	 * at this point I'll assume that the chip is an SMC9xxx. It might be
1403	 * prudent to check a listing of MAC addresses against the hardware
1404	 * address, or do some other tests.
1405	 */
1406	sn_deactivate(dev);
1407	return 0;
1408 error:
1409	sn_deactivate(dev);
1410	return ENXIO;
1411}
1412
1413#define MCFSZ 8
1414
1415static void
1416sn_setmcast(struct sn_softc *sc)
1417{
1418	struct ifnet *ifp = (struct ifnet *)sc;
1419	int flags;
1420
1421	/*
1422	 * Set the receiver filter.  We want receive enabled and auto strip
1423	 * of CRC from received packet.  If we are promiscuous then set that
1424	 * bit too.
1425	 */
1426	flags = RCR_ENABLE | RCR_STRIP_CRC;
1427
1428	if (ifp->if_flags & IFF_PROMISC) {
1429		flags |= RCR_PROMISC | RCR_ALMUL;
1430	} else if (ifp->if_flags & IFF_ALLMULTI) {
1431		flags |= RCR_ALMUL;
1432	} else {
1433		u_char mcf[MCFSZ];
1434		if (sn_getmcf(&sc->arpcom, mcf)) {
1435			/* set filter */
1436			SMC_SELECT_BANK(3);
1437			outw(BASE + MULTICAST1_REG_W,
1438			    ((u_short)mcf[1] << 8) |  mcf[0]);
1439			outw(BASE + MULTICAST2_REG_W,
1440			    ((u_short)mcf[3] << 8) |  mcf[2]);
1441			outw(BASE + MULTICAST3_REG_W,
1442			    ((u_short)mcf[5] << 8) |  mcf[4]);
1443			outw(BASE + MULTICAST4_REG_W,
1444			    ((u_short)mcf[7] << 8) |  mcf[6]);
1445		} else {
1446			flags |= RCR_ALMUL;
1447		}
1448	}
1449	SMC_SELECT_BANK(0);
1450	outw(BASE + RECV_CONTROL_REG_W, flags);
1451}
1452
1453static int
1454sn_getmcf(struct arpcom *ac, u_char *mcf)
1455{
1456	int i;
1457	register u_int index, index2;
1458	register u_char *af = (u_char *) mcf;
1459	struct ifmultiaddr *ifma;
1460
1461	bzero(mcf, MCFSZ);
1462
1463	TAILQ_FOREACH(ifma, &ac->ac_if.if_multiaddrs, ifma_link) {
1464	    if (ifma->ifma_addr->sa_family != AF_LINK)
1465		return 0;
1466	    index = smc_crc(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)) & 0x3f;
1467	    index2 = 0;
1468	    for (i = 0; i < 6; i++) {
1469		index2 <<= 1;
1470		index2 |= (index & 0x01);
1471		index >>= 1;
1472	    }
1473	    af[index2 >> 3] |= 1 << (index2 & 7);
1474	}
1475	return 1;  /* use multicast filter */
1476}
1477
1478static u_int
1479smc_crc(u_char *s)
1480{
1481	int perByte;
1482	int perBit;
1483	const u_int poly = 0xedb88320;
1484	u_int v = 0xffffffff;
1485	u_char c;
1486
1487	for (perByte = 0; perByte < ETHER_ADDR_LEN; perByte++) {
1488		c = s[perByte];
1489		for (perBit = 0; perBit < 8; perBit++) {
1490			v = (v >> 1)^(((v ^ c) & 0x01) ? poly : 0);
1491			c >>= 1;
1492		}
1493	}
1494	return v;
1495}
1496