diff options
-rw-r--r-- | sys/dev/eisa/files.eisa | 9 | ||||
-rw-r--r-- | sys/dev/eisa/if_ep_eisa.c | 171 | ||||
-rw-r--r-- | sys/dev/ic/elink3.c (renamed from sys/dev/isa/if_ep.c) | 533 | ||||
-rw-r--r-- | sys/dev/ic/elink3reg.h (renamed from sys/dev/isa/if_epreg.h) | 12 | ||||
-rw-r--r-- | sys/dev/ic/elink3var.h | 61 | ||||
-rw-r--r-- | sys/dev/isa/files.isa | 13 | ||||
-rw-r--r-- | sys/dev/isa/if_ep_isa.c | 216 | ||||
-rw-r--r-- | sys/dev/pci/files.pci | 9 | ||||
-rw-r--r-- | sys/dev/pci/if_ep_pci.c | 188 |
9 files changed, 671 insertions, 541 deletions
diff --git a/sys/dev/eisa/files.eisa b/sys/dev/eisa/files.eisa index cc0b5443475..c15670bbcf7 100644 --- a/sys/dev/eisa/files.eisa +++ b/sys/dev/eisa/files.eisa @@ -1,5 +1,5 @@ -# $OpenBSD: files.eisa,v 1.3 1996/04/21 22:20:50 deraadt Exp $ -# $NetBSD: files.eisa,v 1.7 1996/03/17 00:47:21 thorpej Exp $ +# $OpenBSD: files.eisa,v 1.4 1996/05/02 13:38:03 deraadt Exp $ +# $NetBSD: files.eisa,v 1.8 1996/04/25 02:16:39 thorpej Exp $ # # Config.new file and device description for machine-independent EISA code. # Included by ports that need it. Requires that the SCSI files be @@ -13,3 +13,8 @@ file dev/eisa/eisa.c eisa needs-flag device ahb: scsi attach ahb at eisa file dev/eisa/aha1742.c ahb + +# 3Com 3c579 and 3c509 masquerading as EISA Ethernet Controllers +# device declaration in sys/conf/files +attach ep at eisa with ep_eisa +file dev/eisa/if_ep_eisa.c ep_eisa diff --git a/sys/dev/eisa/if_ep_eisa.c b/sys/dev/eisa/if_ep_eisa.c new file mode 100644 index 00000000000..150426bd2d7 --- /dev/null +++ b/sys/dev/eisa/if_ep_eisa.c @@ -0,0 +1,171 @@ +/* $NetBSD: if_ep_eisa.c,v 1.1 1996/04/25 02:16:40 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Herb Peyerl. + * 4. The name of Herb Peyerl may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/select.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/netisr.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/cpu.h> +#include <machine/pio.h> + +#include <dev/ic/elink3var.h> +#include <dev/ic/elink3reg.h> + +#include <dev/eisa/eisareg.h> +#include <dev/eisa/eisavar.h> +#include <dev/eisa/eisadevs.h> + +int ep_eisa_match __P((struct device *, void *, void *)); +void ep_eisa_attach __P((struct device *, struct device *, void *)); + +struct cfattach ep_eisa_ca = { + sizeof(struct ep_softc), ep_eisa_match, ep_eisa_attach +}; + +/* XXX move these somewhere else */ +#define EISA_CONTROL 0x0c84 +#define EISA_RESET 0x04 +#define EISA_ERROR 0x02 +#define EISA_ENABLE 0x01 + +int +ep_eisa_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct eisa_attach_args *ea = aux; + + /* must match one of our known ID strings */ + if (strcmp(ea->ea_idstring, "TCM5091") && + strcmp(ea->ea_idstring, "TCM5092") && + strcmp(ea->ea_idstring, "TCM5093")) + return (0); + + return (1); +} + +void +ep_eisa_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ep_softc *sc = (void *)self; + struct eisa_attach_args *ea = aux; + int iobase, irq, k; + u_short conn = 0; + eisa_chipset_tag_t ec = ea->ea_ec; + eisa_intr_handle_t ih; + const char *model, *intrstr; + + sc->ep_iobase = iobase = EISA_SLOT_ADDR(ea->ea_slot); + sc->bustype = EP_BUS_EISA; + + /* Reset card. */ + outb(iobase + EISA_CONTROL, EISA_ENABLE | EISA_RESET); + delay(10); + outb(iobase + EISA_CONTROL, EISA_ENABLE); + /* Wait for reset? */ + delay(1000); + + /* XXX What is this doing?! */ + k = inw(iobase + EP_W0_ADDRESS_CFG); + k = (k & 0x1f) * 0x10 + 0x200; + + /* Read the IRQ from the card. */ + irq = inw(iobase + EP_W0_RESOURCE_CFG) >> 12; + + GO_WINDOW(0); + conn = inw(iobase + EP_W0_CONFIG_CTRL); + + if (strcmp(ea->ea_idstring, "TCM5091") == 0) + model = EISA_PRODUCT_TCM5091; + else if (strcmp(ea->ea_idstring, "TCM5092") == 0) + model = EISA_PRODUCT_TCM5092; + else if (strcmp(ea->ea_idstring, "TCM5093") == 0) + model = EISA_PRODUCT_TCM5093; + else + model = "unknown model!"; + printf(": %s\n", model); + + if (eisa_intr_map(ec, irq, &ih)) { + printf("%s: couldn't map interrupt (%d)\n", + sc->sc_dev.dv_xname, irq); + return; + } + intrstr = eisa_intr_string(ec, ih); + sc->sc_ih = eisa_intr_establish(ec, ih, IST_EDGE, IPL_NET, + epintr, sc, sc->sc_dev.dv_xname); + if (sc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + if (intrstr != NULL) + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, + intrstr); + + epconfig(sc, conn); +} diff --git a/sys/dev/isa/if_ep.c b/sys/dev/ic/elink3.c index f9eab4b8368..783ad4b1f39 100644 --- a/sys/dev/isa/if_ep.c +++ b/sys/dev/ic/elink3.c @@ -1,5 +1,4 @@ -/* $OpenBSD: if_ep.c,v 1.12 1996/04/29 14:16:41 hvozda Exp $ */ -/* $NetBSD: if_ep.c,v 1.90 1996/04/11 22:29:15 cgd Exp $ */ +/* $NetBSD: elink3.c,v 1.1 1996/04/25 02:17:34 thorpej Exp $ */ /* * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> @@ -31,9 +30,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "pcmcia.h" #include "bpfilter.h" -#include "ep.h" #include <sys/param.h> #include <sys/mbuf.h> @@ -43,7 +40,6 @@ #include <sys/syslog.h> #include <sys/select.h> #include <sys/device.h> -#include <sys/systm.h> #include <net/if.h> #include <net/netisr.h> @@ -69,81 +65,21 @@ #include <net/bpfdesc.h> #endif -#include "pci.h" - #include <machine/cpu.h> #include <machine/pio.h> -#include <dev/isa/isavar.h> -#include <dev/isa/if_epreg.h> -#include <dev/isa/elink.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.h> -#include <dev/pci/pcidevs.h> - -/* PCI constants */ -#define PCI_VENDORID(x) ((x) & 0xFFFF) -#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF) -#define PCI_CONN 0x48 /* Connector type */ -#define PCI_CBMA 0x10 /* Configuration Base Memory Address */ - +#include <dev/ic/elink3var.h> +#include <dev/ic/elink3reg.h> #define ETHER_MIN_LEN 64 #define ETHER_MAX_LEN 1518 #define ETHER_ADDR_LEN 6 -/* - * Ethernet software status per interface. - */ -struct ep_softc { - struct device sc_dev; - void *sc_ih; - - struct arpcom sc_arpcom; /* Ethernet common part */ - int ep_iobase; /* i/o bus address */ - char ep_connectors; /* Connectors on this card. */ -#define MAX_MBS 8 /* # of mbufs we keep around */ - struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */ - int next_mb; /* Which mbuf to use next. */ - int last_mb; /* Last mbuf. */ - int tx_start_thresh; /* Current TX_start_thresh. */ - int tx_succ_ok; /* # packets sent in sequence */ - /* w/o underrun */ - u_char bustype; -#define EP_BUS_ISA 0x0 -#define EP_BUS_PCMCIA 0x1 -#define EP_BUS_EISA 0x2 -#define EP_BUS_PCI 0x3 - -#define EP_IS_BUS_32(a) ((a) & 0x2) - - u_char pcmcia_flags; -#define EP_REATTACH 0x01 -#define EP_ABSENT 0x02 -}; - -static int epprobe __P((struct device *, void *, void *)); -static void epattach __P((struct device *, struct device *, void *)); - -/* XXX the following two structs should be different. */ -#if NEP_ISA > 0 -struct cfattach ep_isa_ca = { - sizeof(struct ep_softc), epprobe, epattach -}; -#endif - -#if NEP_PCI > 0 -struct cfattach ep_pci_ca = { - sizeof(struct ep_softc), epprobe, epattach -}; -#endif - struct cfdriver ep_cd = { NULL, "ep", DV_IFNET }; -int epintr __P((void *)); +static void epxstat __P((struct ep_softc *)); static int epstatus __P((struct ep_softc *)); void epinit __P((struct ep_softc *)); int epioctl __P((struct ifnet *, u_long, caddr_t)); @@ -152,371 +88,16 @@ void epwatchdog __P((int)); void epreset __P((struct ep_softc *)); void epread __P((struct ep_softc *)); struct mbuf *epget __P((struct ep_softc *, int)); -void epmbuffill __P((void *)); +void epmbuffill __P((struct ep_softc *)); void epmbufempty __P((struct ep_softc *)); void epstop __P((struct ep_softc *)); void epsetfilter __P((struct ep_softc *)); void epsetlink __P((struct ep_softc *)); -static void epconfig __P((struct ep_softc *, u_int)); +u_short epreadeeprom __P((int id_port, int offset)); -static u_short epreadeeprom __P((int id_port, int offset)); static int epbusyeeprom __P((struct ep_softc *)); -#define MAXEPCARDS 20 /* if you have 21 cards in your machine... you lose */ - -static struct epcard { - int iobase; - int irq; - char available; - char bustype; -} epcards[MAXEPCARDS]; -static int nepcards; - -static void -epaddcard(iobase, irq, bustype) - int iobase; - int irq; - char bustype; -{ - - if (nepcards >= MAXEPCARDS) - return; - epcards[nepcards].iobase = iobase; - epcards[nepcards].irq = (irq == 2) ? 9 : irq; - epcards[nepcards].available = 1; - epcards[nepcards].bustype = bustype; - nepcards++; -} - -#if NEP_PCMCIA > 0 -#include <dev/pcmcia/pcmciavar.h> - -int ep_pcmcia_match __P((struct device *, void *, void *)); -void ep_pcmcia_attach __P((struct device *, struct device *, void *)); -int ep_pcmcia_detach __P((struct device *)); - -static int ep_pcmcia_isa_attach __P((struct device *, void *, - void *, struct pcmcia_link *)); -static int epmod __P((struct pcmcia_link *, struct device *, - struct pcmcia_conf *, struct cfdata * cf)); -static int ep_remove __P((struct pcmcia_link *, struct device *)); - -struct cfattach ep_pcmcia_ca = { - sizeof(struct ep_softc), ep_pcmcia_match, epattach, ep_pcmcia_detach -}; - -/* additional setup needed for pcmcia devices */ -static int -ep_pcmcia_isa_attach(parent, match, aux, pc_link) - struct device *parent; - void *match; - void *aux; - struct pcmcia_link *pc_link; -{ - struct ep_softc *sc = (void *) match; -/* struct cfdata *cf = sc->sc_dev.dv_cfdata;*/ - struct isa_attach_args *ia = aux; -/* struct pcmciadevs *dev = pc_link->device;*/ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - int i; - extern int ifqmaxlen; - - outw(ia->ia_iobase + EP_COMMAND, WINDOW_SELECT | 0); - outw(ia->ia_iobase + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); - outw(ia->ia_iobase + EP_W0_RESOURCE_CFG, 0x3f00); - - /* - * ok til here. Now try to figure out which link we have. - * try coax first... - */ -#ifdef EP_COAX_DEFAULT - outw(ia->ia_iobase + EP_W0_ADDRESS_CFG, 0xC000); -#else - /* COAX as default is reported to be a problem */ - outw(ia->ia_iobase + EP_W0_ADDRESS_CFG, 0x0000); -#endif - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - epaddcard(ia->ia_iobase, ia->ia_irq, EP_BUS_PCMCIA); - - for (i = 0; i < nepcards; i++) { - if (epcards[i].available == 0) - continue; - if (ia->ia_iobase != IOBASEUNK && - ia->ia_iobase != epcards[i].iobase) - continue; - if (ia->ia_irq != IRQUNK && - ia->ia_irq != epcards[i].irq) - continue; - goto good; - } - return 0; - -good: - - epcards[i].available = 0; - ia->ia_iobase = epcards[i].iobase; - ia->ia_irq = epcards[i].irq; - ia->ia_iosize = 0x10; - ia->ia_msize = 0; - - sc->bustype = epcards[i].bustype; - sc->pcmcia_flags = (pc_link->flags & PCMCIA_REATTACH) ? EP_REATTACH:0; - return 1; -} - -/* modify config entry */ -static int -epmod(pc_link, self, pc_cf, cf) - struct pcmcia_link *pc_link; - struct device *self; - struct pcmcia_conf *pc_cf; - struct cfdata *cf; -{ - int err; -/* struct pcmciadevs *dev = pc_link->device;*/ -/* struct ep_softc *sc = (void *) self;*/ - - if ((err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self, - pc_cf, cf)) != 0) { - printf("bus_config failed %d\n", err); - return err; - } - - if (pc_cf->io[0].len > 0x10) - pc_cf->io[0].len = 0x10; -#if 0 - pc_cf->cfgtype = DOSRESET; -#endif - pc_cf->cfgtype = 1; - - return 0; -} - -static int -ep_remove(pc_link, self) - struct pcmcia_link *pc_link; - struct device *self; -{ - struct ep_softc *sc = (void *) self; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - if_down(ifp); - epstop(sc); - ifp->if_flags &= ~(IFF_RUNNING | IFF_UP); - sc->pcmcia_flags = EP_ABSENT; - return PCMCIA_BUS_UNCONFIG(pc_link->adapter, pc_link); -} - -static struct pcmcia_3com { - struct pcmcia_device pcd; -} pcmcia_3com = { - {"PCMCIA 3COM 3C589", epmod, ep_pcmcia_isa_attach, NULL, ep_remove} -}; - -struct pcmciadevs pcmcia_ep_devs[] = { - { - "ep", 0, "3Com Corporation", "3C589", -#if 0 - "TP/BNC LAN Card Ver. 1a", "000001", -#else - NULL, NULL, -#endif - (void *) -1, (void *) &pcmcia_3com - }, -#if 0 - { - "ep", 0, "3Com Corporation", "3C589", "TP/BNC LAN Card Ver. 2a", "000002", - (void *) -1, (void *) &pcmcia_3com - }, -#endif - { NULL } -}; -#define nep_pcmcia_devs sizeof(pcmcia_ep_devs)/sizeof(pcmcia_ep_devs[0]) - -int -ep_pcmcia_match(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - return pcmcia_slave_match(parent, match, aux, pcmcia_ep_devs, - nep_pcmcia_devs); -} - void -ep_pcmcia_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct pcmcia_attach_args *paa = aux; - - printf("ep_pcmcia_attach %p %p %p\n", parent, self, aux); - delay(2000000); - if (!pcmcia_configure(parent, self, paa->paa_link)) { - struct ep_softc *sc = (void *)self; - sc->pcmcia_flags |= EP_ABSENT; - printf(": not attached\n"); - } -} - -/* - * No detach; network devices are too well linked into the rest of the - * kernel. - */ -int -ep_pcmcia_detach(self) - struct device *self; -{ - return EBUSY; -} - -#endif - - -/* - * 3c579 cards on the EISA bus are probed by their slot number. 3c509 - * cards on the ISA bus are probed in ethernet address order. The probe - * sequence requires careful orchestration, and we'd like like to allow - * the irq and base address to be wildcarded. So, we probe all the cards - * the first time epprobe() is called. On subsequent calls we look for - * matching cards. - */ -int -epprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct ep_softc *sc = match; - struct isa_attach_args *ia = aux; - static int probed; - int slot, iobase, i; - u_short vendor, model; - int k, k2; - -#if NPCI > 0 - extern struct cfdriver pci_cd; - - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = (struct pci_attach_args *) aux; - - if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_3COM) - return 0; - - switch (PCI_CHIPID(pa->pa_id)) { - case PCI_PRODUCT_3COM_3C590: - case PCI_PRODUCT_3COM_3C595: - break; - default: - return 0; - } - - if (nepcards >= MAXEPCARDS) - return 0; - - epcards[nepcards++].available = 0; - return 1; - } -#endif - - if (!probed) { - probed = 1; - - /* find all EISA cards */ - for (slot = 1; slot < 16; slot++) { - iobase = 0x1000 * slot; - - vendor = htons(inw(iobase + EISA_VENDOR)); - if (vendor != MFG_ID) - continue; - - model = htons(inw(iobase + EISA_MODEL)); - if ((model & 0xfff0) != PROD_ID) { -#ifndef trusted - printf("epprobe: ignoring model %04x\n", model); -#endif - continue; - } - - outb(iobase + EISA_CONTROL, EISA_ENABLE | EISA_RESET); - delay(10); - outb(iobase + EISA_CONTROL, EISA_ENABLE); - /* Wait for reset? */ - delay(1000); - - k = inw(iobase + EP_W0_ADDRESS_CFG); - k = (k & 0x1f) * 0x10 + 0x200; - - k2 = inw(iobase + EP_W0_RESOURCE_CFG); - k2 >>= 12; - epaddcard(iobase, k2, EP_BUS_EISA); - } - - for (slot = 0; slot < 10; slot++) { - elink_reset(); - elink_idseq(ELINK_509_POLY); - - /* Untag all the adapters so they will talk to us. */ - if (slot == 0) - outb(ELINK_ID_PORT, TAG_ADAPTER + 0); - - vendor = - htons(epreadeeprom(ELINK_ID_PORT, EEPROM_MFG_ID)); - if (vendor != MFG_ID) - continue; - - model = - htons(epreadeeprom(ELINK_ID_PORT, EEPROM_PROD_ID)); - if ((model & 0xfff0) != PROD_ID) { -#ifndef trusted - printf("epprobe: ignoring model %04x\n", model); -#endif - continue; - } - - k = epreadeeprom(ELINK_ID_PORT, EEPROM_ADDR_CFG); - k = (k & 0x1f) * 0x10 + 0x200; - - k2 = epreadeeprom(ELINK_ID_PORT, EEPROM_RESOURCE_CFG); - k2 >>= 12; - epaddcard(k, k2, EP_BUS_ISA); - - /* so card will not respond to contention again */ - outb(ELINK_ID_PORT, TAG_ADAPTER + 1); - - /* - * XXX: this should probably not be done here - * because it enables the drq/irq lines from - * the board. Perhaps it should be done after - * we have checked for irq/drq collisions? - */ - outb(ELINK_ID_PORT, ACTIVATE_ADAPTER_TO_CONFIG); - } - /* XXX should we sort by ethernet address? */ - } - - for (i = 0; i < nepcards; i++) { - if (epcards[i].available == 0) - continue; - if (ia->ia_iobase != IOBASEUNK && - ia->ia_iobase != epcards[i].iobase) - continue; - if (ia->ia_irq != IRQUNK && - ia->ia_irq != epcards[i].irq) - continue; - goto good; - } - return 0; - -good: - epcards[i].available = 0; - sc->bustype = epcards[i].bustype; - ia->ia_iobase = epcards[i].iobase; - ia->ia_irq = epcards[i].irq; - ia->ia_iosize = 0x10; - ia->ia_msize = 0; - return 1; -} - -static void epconfig(sc, conn) struct ep_softc *sc; u_int conn; @@ -526,7 +107,7 @@ epconfig(sc, conn) struct ifnet *ifp = &sc->sc_arpcom.ac_if; sc->ep_connectors = 0; - printf(": "); + printf("%s: ", sc->sc_dev.dv_xname); if (conn & IS_AUI) { printf("aui"); sc->ep_connectors |= AUI; @@ -571,91 +152,15 @@ epconfig(sc, conn) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; - if ((sc->pcmcia_flags & EP_REATTACH) == 0) { - if_attach(ifp); - ether_ifattach(ifp); + if_attach(ifp); + ether_ifattach(ifp); #if NBPFILTER > 0 - bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, - sizeof(struct ether_header)); -#endif - } - sc->tx_start_thresh = 20; /* probably a good starting point. */ -} - -static void -epattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct ep_softc *sc = (void *)self; - u_short conn = 0; -#if NPCI > 0 - extern struct cfdriver pci_cd; - - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = aux; - int iobase; - u_short i; - - if (pci_map_io(pa->pa_tag, PCI_CBMA, &iobase)) { - printf("%s: couldn't map io\n", sc->sc_dev.dv_xname); - return; - } - sc->bustype = EP_BUS_PCI; - sc->ep_iobase = iobase; /* & 0xfffffff0 */ - i = pci_conf_read(pa->pa_bc, pa->pa_tag, PCI_CONN); - - /* - * Bits 13,12,9 of the isa adapter are the same as bits - * 5,4,3 of the pci adapter - */ - if (i & IS_PCI_AUI) - conn |= IS_AUI; - if (i & IS_PCI_BNC) - conn |= IS_BNC; - if (i & IS_PCI_UTP) - conn |= IS_UTP; - - GO_WINDOW(0); - } - else + bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, + sizeof(struct ether_header)); #endif - { - struct isa_attach_args *ia = aux; - - sc->ep_iobase = ia->ia_iobase; - GO_WINDOW(0); - conn = inw(ia->ia_iobase + EP_W0_CONFIG_CTRL); - } - - epconfig(sc, conn); - - -#if NPCI > 0 - if (parent->dv_cfdata->cf_driver == &pci_cd) { - struct pci_attach_args *pa = aux; - pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG, - pci_conf_read(pa->pa_bc, pa->pa_tag, - PCI_COMMAND_STATUS_REG) | - PCI_COMMAND_MASTER_ENABLE); - - sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, epintr, sc); - if (sc->sc_ih == NULL) { - printf("%s: couldn't map interrupt\n", - sc->sc_dev.dv_xname); - return; - } - epstop(sc); - } - else -#endif - { - struct isa_attach_args *ia = aux; - sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, - IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname); - } + sc->tx_start_thresh = 20; /* probably a good starting point. */ } /* @@ -1278,13 +783,6 @@ epioctl(ifp, cmd, data) int s, error = 0; s = splnet(); - if (sc->bustype == EP_BUS_PCMCIA && - (sc->pcmcia_flags & EP_ABSENT)) { - if_down(ifp); - printf("%s: device offline\n", sc->sc_dev.dv_xname); - splx(s); - return ENXIO; - } switch (cmd) { @@ -1432,7 +930,7 @@ epstop(sc) * returned to us by inb(). Hence; we read 16 times getting one * bit of data with each read. */ -static u_short +u_short epreadeeprom(id_port, offset) int id_port; int offset; @@ -1478,10 +976,9 @@ epbusyeeprom(sc) } void -epmbuffill(arg) - void *arg; +epmbuffill(sc) + struct ep_softc *sc; { - struct ep_softc *sc = arg; int s, i; s = splnet(); diff --git a/sys/dev/isa/if_epreg.h b/sys/dev/ic/elink3reg.h index e215d7cee43..a125013030e 100644 --- a/sys/dev/isa/if_epreg.h +++ b/sys/dev/ic/elink3reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_epreg.h,v 1.14 1995/11/10 19:39:25 christos Exp $ */ +/* $NetBSD: elink3reg.h,v 1.1 1996/04/25 02:17:35 thorpej Exp $ */ /* * Copyright (c) 1995 Herb Peyerl <hpeyerl@novatel.ca> @@ -336,13 +336,3 @@ #define IS_PCI_AUI (1<<5) #define IS_PCI_BNC (1<<4) #define IS_PCI_UTP (1<<3) - -/* - * EISA registers (offset from slot base) - */ -#define EISA_VENDOR 0x0c80 /* vendor ID (2 ports) */ -#define EISA_MODEL 0x0c82 /* model number (2 ports) */ -#define EISA_CONTROL 0x0c84 -#define EISA_RESET 0x04 -#define EISA_ERROR 0x02 -#define EISA_ENABLE 0x01 diff --git a/sys/dev/ic/elink3var.h b/sys/dev/ic/elink3var.h new file mode 100644 index 00000000000..c87e412e061 --- /dev/null +++ b/sys/dev/ic/elink3var.h @@ -0,0 +1,61 @@ +/* $NetBSD: elink3var.h,v 1.1 1996/04/25 02:17:36 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Herb Peyerl. + * 4. The name of Herb Peyerl may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Ethernet software status per interface. + */ +struct ep_softc { + struct device sc_dev; + void *sc_ih; + + struct arpcom sc_arpcom; /* Ethernet common part */ + int ep_iobase; /* i/o bus address */ + char ep_connectors; /* Connectors on this card. */ +#define MAX_MBS 8 /* # of mbufs we keep around */ + struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */ + int next_mb; /* Which mbuf to use next. */ + int last_mb; /* Last mbuf. */ + int tx_start_thresh; /* Current TX_start_thresh. */ + int tx_succ_ok; /* # packets sent in sequence */ + /* w/o underrun */ + u_char bustype; +#define EP_BUS_ISA 0x0 +#define EP_BUS_PCMCIA 0x1 +#define EP_BUS_EISA 0x2 +#define EP_BUS_PCI 0x3 + +#define EP_IS_BUS_32(a) ((a) & 0x2) +}; + +u_short epreadeeprom __P((int id_port, int offset)); +void epconfig __P((struct ep_softc *, u_int)); +int epintr __P((void *)); diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index 63341eb0196..4e0136ea6a7 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,5 +1,5 @@ -# $OpenBSD: files.isa,v 1.12 1996/05/02 07:43:07 niklas Exp $ -# $NetBSD: files.isa,v 1.17 1996/03/29 20:53:30 mycroft Exp $ +# $OpenBSD: files.isa,v 1.13 1996/05/02 13:38:09 deraadt Exp $ +# $NetBSD: files.isa,v 1.18 1996/04/25 02:15:42 thorpej Exp $ # # Config.new file and device description for machine-independent ISA code. # Included by ports that need it. Requires that the SCSI files be @@ -162,12 +162,9 @@ device el: ether, ifnet attach el at isa file dev/isa/if_el.c el -# 3Com 3C5x9, 3c59x (EtherLink III) family -device ep: ether, ifnet, elink -attach ep at isa with ep_isa -attach ep at pci with ep_pci -attach ep at pcmcia with ep_pcmcia -file dev/isa/if_ep.c ep & (ep_isa | ep_pci | ep_pcmcia) needs-flag +# 3Com 3C509 Ethernet controller +attach ep at isa with ep_isa: elink +file dev/isa/if_ep_isa.c ep_isa # Fujitsu MB8696[05]-based boards # (Allied Telesis AT1700) diff --git a/sys/dev/isa/if_ep_isa.c b/sys/dev/isa/if_ep_isa.c new file mode 100644 index 00000000000..a138daa7c03 --- /dev/null +++ b/sys/dev/isa/if_ep_isa.c @@ -0,0 +1,216 @@ +/* $NetBSD: if_ep_isa.c,v 1.1 1996/04/25 02:15:47 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Herb Peyerl. + * 4. The name of Herb Peyerl may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/select.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/netisr.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/cpu.h> +#include <machine/pio.h> + +#include <dev/ic/elink3var.h> +#include <dev/ic/elink3reg.h> + +#include <dev/isa/isavar.h> +#include <dev/isa/elink.h> + +int ep_isa_probe __P((struct device *, void *, void *)); +void ep_isa_attach __P((struct device *, struct device *, void *)); + +struct cfattach ep_isa_ca = { + sizeof(struct ep_softc), ep_isa_probe, ep_isa_attach +}; + +static void epaddcard __P((int, int)); + +#define MAXEPCARDS 10 /* 10 ISA slots */ + +static struct epcard { + int iobase; + int irq; + char available; +} epcards[MAXEPCARDS]; +static int nepcards; + +static void +epaddcard(iobase, irq) + int iobase; + int irq; +{ + + if (nepcards >= MAXEPCARDS) + return; + epcards[nepcards].iobase = iobase; + epcards[nepcards].irq = (irq == 2) ? 9 : irq; + epcards[nepcards].available = 1; + nepcards++; +} + +/* + * 3c509 cards on the ISA bus are probed in ethernet address order. + * The probe sequence requires careful orchestration, and we'd like + * like to allow the irq and base address to be wildcarded. So, we + * probe all the cards the first time epprobe() is called. On subsequent + * calls we look for matching cards. + */ +int +ep_isa_probe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct isa_attach_args *ia = aux; + static int probed; + int slot, iobase, irq, i; + u_short vendor, model; + + if (!probed) { + probed = 1; + + for (slot = 0; slot < MAXEPCARDS; slot++) { + elink_reset(); + elink_idseq(ELINK_509_POLY); + + /* Untag all the adapters so they will talk to us. */ + if (slot == 0) + outb(ELINK_ID_PORT, TAG_ADAPTER + 0); + + vendor = + htons(epreadeeprom(ELINK_ID_PORT, EEPROM_MFG_ID)); + if (vendor != MFG_ID) + continue; + + model = + htons(epreadeeprom(ELINK_ID_PORT, EEPROM_PROD_ID)); + if ((model & 0xfff0) != PROD_ID) { +#ifndef trusted + printf( + "ep_isa_probe: ignoring model %04x\n", model); +#endif + continue; + } + + iobase = epreadeeprom(ELINK_ID_PORT, EEPROM_ADDR_CFG); + iobase = (iobase & 0x1f) * 0x10 + 0x200; + + irq = epreadeeprom(ELINK_ID_PORT, EEPROM_RESOURCE_CFG); + irq >>= 12; + epaddcard(iobase, irq); + + /* so card will not respond to contention again */ + outb(ELINK_ID_PORT, TAG_ADAPTER + 1); + + /* + * XXX: this should probably not be done here + * because it enables the drq/irq lines from + * the board. Perhaps it should be done after + * we have checked for irq/drq collisions? + */ + outb(ELINK_ID_PORT, ACTIVATE_ADAPTER_TO_CONFIG); + } + /* XXX should we sort by ethernet address? */ + } + + for (i = 0; i < nepcards; i++) { + if (epcards[i].available == 0) + continue; + if (ia->ia_iobase != IOBASEUNK && + ia->ia_iobase != epcards[i].iobase) + continue; + if (ia->ia_irq != IRQUNK && + ia->ia_irq != epcards[i].irq) + continue; + goto good; + } + return 0; + +good: + epcards[i].available = 0; + ia->ia_iobase = epcards[i].iobase; + ia->ia_irq = epcards[i].irq; + ia->ia_iosize = 0x10; + ia->ia_msize = 0; + return 1; +} + +void +ep_isa_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ep_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + u_short conn = 0; + int iobase; + + sc->ep_iobase = iobase = ia->ia_iobase; + sc->bustype = EP_BUS_ISA; + + GO_WINDOW(0); + conn = inw(iobase + EP_W0_CONFIG_CTRL); + + printf(": 3Com 3C509 Ethernet\n"); + + epconfig(sc, conn); + + sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_NET, epintr, sc, sc->sc_dev.dv_xname); +} diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 149d0d98785..f77d9dddda3 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,5 +1,5 @@ -# $OpenBSD: files.pci,v 1.4 1996/04/21 22:25:06 deraadt Exp $ -# $NetBSD: files.pci,v 1.13 1996/03/17 00:55:24 thorpej Exp $ +# $OpenBSD: files.pci,v 1.5 1996/05/02 13:38:15 deraadt Exp $ +# $NetBSD: files.pci,v 1.14 1996/04/25 02:17:05 thorpej Exp $ # # Config.new file and device description for machine-independent PCI code. # Included by ports that need it. Requires that the SCSI files be @@ -34,3 +34,8 @@ file dev/pci/ncr.c ncr device ppb: pcibus attach ppb at pci file dev/pci/ppb.c ppb + +# 3Com 3c590 and 3c595 Ethernet controllers +# device declaration in sys/conf/files +attach ep at pci with ep_pci +file dev/pci/if_ep_pci.c ep_pci diff --git a/sys/dev/pci/if_ep_pci.c b/sys/dev/pci/if_ep_pci.c new file mode 100644 index 00000000000..5deec157195 --- /dev/null +++ b/sys/dev/pci/if_ep_pci.c @@ -0,0 +1,188 @@ +/* $NetBSD: if_ep_pci.c,v 1.1 1996/04/25 02:17:06 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Herb Peyerl. + * 4. The name of Herb Peyerl may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/select.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/cpu.h> +#include <machine/pio.h> + +#include <dev/ic/elink3var.h> +#include <dev/ic/elink3reg.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcidevs.h> + +/* PCI constants */ +#define PCI_VENDORID(x) ((x) & 0xFFFF) +#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF) +#define PCI_CONN 0x48 /* Connector type */ +#define PCI_CBMA 0x10 /* Configuration Base Memory Address */ + +int ep_pci_match __P((struct device *, void *, void *)); +void ep_pci_attach __P((struct device *, struct device *, void *)); + +struct cfattach ep_pci_ca = { + sizeof(struct ep_softc), ep_pci_match, ep_pci_attach +}; + +int +ep_pci_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct pci_attach_args *pa = (struct pci_attach_args *) aux; + + if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_3COM) + return 0; + + switch (PCI_CHIPID(pa->pa_id)) { + case PCI_PRODUCT_3COM_3C590: + case PCI_PRODUCT_3COM_3C595: + break; + default: + return 0; + } + + return 1; +} + +void +ep_pci_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ep_softc *sc = (void *)self; + u_short conn = 0; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + int iobase; + u_short i; + char *model; + const char *intrstr = NULL; + + if (pci_map_io(pa->pa_tag, PCI_CBMA, &iobase)) { + printf(": couldn't map io\n"); + return; + } + sc->bustype = EP_BUS_PCI; + sc->ep_iobase = iobase; /* & 0xfffffff0 */ + i = pci_conf_read(pc, pa->pa_tag, PCI_CONN); + + /* + * Bits 13,12,9 of the isa adapter are the same as bits + * 5,4,3 of the pci adapter + */ + if (i & IS_PCI_AUI) + conn |= IS_AUI; + if (i & IS_PCI_BNC) + conn |= IS_BNC; + if (i & IS_PCI_UTP) + conn |= IS_UTP; + + GO_WINDOW(0); + + switch (PCI_CHIPID(pa->pa_id)) { + case PCI_PRODUCT_3COM_3C590: + model = "3Com 3C590 Ethernet"; + break; + + case PCI_PRODUCT_3COM_3C595: + model = "3Com 3C595 Ethernet"; + break; + default: + model = "unknown model!"; + } + + printf(": %s\n", model); + + epconfig(sc, conn); + + /* Enable the card. */ + pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, + pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | + PCI_COMMAND_MASTER_ENABLE); + + /* Map and establish the interrupt. */ + if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, + pa->pa_intrline, &ih)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return; + } + intrstr = pci_intr_string(pc, ih); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, epintr, + sc, sc->sc_dev.dv_xname); + if (sc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); + + epstop(sc); +} |