diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index 42537ab156c..ec4873594a9 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/if_ed.c @@ -37,6 +37,7 @@ * */ +#include "ed.h" #include "bpf.h" #include @@ -72,43 +73,90 @@ #include #include +#include +#include #include -#include -#include -#include +/* + * ed_softc: per line info and status + */ +struct ed_softc { + struct arpcom arpcom; /* ethernet common */ -static int ed_alloc_port __P((device_t, int, int)); -static int ed_alloc_memory __P((device_t, int, int)); -static int ed_alloc_irq __P((device_t, int, int)); -static void ed_release_resources __P((device_t)); + char *type_str; /* pointer to type string */ + u_char vendor; /* interface vendor */ + u_char type; /* interface type code */ + u_char gone; /* HW missing, presumed having a good time */ + + u_short asic_addr; /* ASIC I/O bus address */ + u_short nic_addr; /* NIC (DS8390) I/O bus address */ + +/* + * The following 'proto' variable is part of a work-around for 8013EBT asics + * being write-only. It's sort of a prototype/shadow of the real thing. + */ + u_char wd_laar_proto; + u_char cr_proto; + u_char isa16bit; /* width of access to card 0=8 or 1=16 */ + int is790; /* set by the probe code if the card is 790 + * based */ + +/* + * HP PC LAN PLUS card support. + */ + + u_short hpp_options; /* flags controlling behaviour of the HP card */ + u_short hpp_id; /* software revision and other fields */ + caddr_t hpp_mem_start; /* Memory-mapped IO register address */ + + caddr_t mem_start; /* NIC memory start address */ + caddr_t mem_end; /* NIC memory end address */ + u_long mem_size; /* total NIC memory size */ + caddr_t mem_ring; /* start of RX ring-buffer (in NIC mem) */ + + u_char mem_shared; /* NIC memory is shared with host */ + u_char xmit_busy; /* transmitter is busy */ + u_char txb_cnt; /* number of transmit buffers */ + u_char txb_inuse; /* number of TX buffers currently in-use */ + + u_char txb_new; /* pointer to where new buffer will be added */ + u_char txb_next_tx; /* pointer to next buffer ready to xmit */ + u_short txb_len[8]; /* buffered xmit buffer lengths */ + u_char tx_page_start; /* first page of TX buffer area */ + u_char rec_page_start; /* first page of RX ring-buffer */ + u_char rec_page_stop; /* last page of RX ring-buffer */ + u_char next_packet; /* pointer to next unread RX packet */ + struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ +}; + +static struct ed_softc ed_softc[NED]; static int ed_attach __P((struct ed_softc *, int, int)); -static int ed_isa_attach __P((device_t)); +static int ed_attach_isa __P((struct isa_device *)); static void ed_init __P((void *)); -static driver_intr_t edintr; +static ointhand2_t edintr; static int ed_ioctl __P((struct ifnet *, u_long, caddr_t)); -static int ed_isa_probe __P((device_t)); +static int ed_probe __P((struct isa_device *)); static void ed_start __P((struct ifnet *)); static void ed_reset __P((struct ifnet *)); static void ed_watchdog __P((struct ifnet *)); static void ed_stop __P((struct ed_softc *)); static int ed_probe_generic8390 __P((struct ed_softc *)); -static int ed_probe_WD80x3 __P((device_t)); -static int ed_probe_3Com __P((device_t)); -static int ed_probe_Novell __P((device_t)); -static int ed_probe_Novell_generic __P((device_t, int, int)); -static int ed_probe_HP_pclanp __P((device_t)); +static int ed_probe_WD80x3 __P((struct isa_device *)); +static int ed_probe_3Com __P((struct isa_device *)); +static int ed_probe_Novell __P((struct isa_device *)); +static int ed_probe_Novell_generic __P((struct ed_softc *, int, int, int)); +static int ed_probe_HP_pclanp __P((struct isa_device *)); #include "pci.h" #if NPCI > 0 -int ed_attach_NE2000_pci __P((device_t, int)); +void *ed_attach_NE2000_pci __P((int, int)); #endif #include "card.h" -#if NCARDxx > 0 +#if NCARD > 0 static int ed_probe_pccard __P((struct isa_device *, u_char *)); #endif @@ -132,12 +180,13 @@ static void ed_pio_writemem __P((struct ed_softc *, char *, /* u_short */ int, /* u_short */ int)); static u_short ed_pio_write_mbufs __P((struct ed_softc *, struct mbuf *, int)); +void edintr_sc __P((struct ed_softc *)); static void ed_setrcr __P((struct ed_softc *)); static u_long ds_crc __P((u_char *ep)); -#if NCARDxx > 0 +#if NCARD > 0 #include #include #include @@ -163,7 +212,7 @@ edinit(struct pccard_devinfo *devi) struct ed_softc *sc = &ed_softc[devi->isahd.id_unit]; /* validate unit number. */ - if (devi->isahd.id_unit >= NEDTOT) + if (devi->isahd.id_unit >= NED) return(ENODEV); /* * Probe the device. If a value is returned, the @@ -178,7 +227,7 @@ edinit(struct pccard_devinfo *devi) if (e) for (i = 0; i < ETHER_ADDR_LEN; ++i) sc->arpcom.ac_enaddr[i] = devi->misc[i]; - if (ed_isa_attach(&devi->isahd) == 0) + if (ed_attach_isa(&devi->isahd) == 0) return(ENXIO); return(0); @@ -216,123 +265,102 @@ edunload(struct pccard_devinfo *devi) static int card_intr(struct pccard_devinfo *devi) { - edintr(&ed_softc[devi->isahd.id_unit]); + edintr_sc(&ed_softc[devi->isahd.id_unit]); return(1); } #endif /* NCARD > 0 */ +struct isa_driver eddriver = { + ed_probe, + ed_attach_isa, + "ed", + 1 /* We are ultra sensitive */ +}; + /* * Interrupt conversion table for WD/SMC ASIC/83C584 + * (IRQ* are defined in icu.h) */ -static unsigned short ed_intr_val[] = { - 9, - 3, - 5, - 7, - 10, - 11, - 15, - 4 +static unsigned short ed_intr_mask[] = { + IRQ9, + IRQ3, + IRQ5, + IRQ7, + IRQ10, + IRQ11, + IRQ15, + IRQ4 }; /* * Interrupt conversion table for 83C790 */ -static unsigned short ed_790_intr_val[] = { +static unsigned short ed_790_intr_mask[] = { 0, - 9, - 3, - 5, - 7, - 10, - 11, - 15 + IRQ9, + IRQ3, + IRQ5, + IRQ7, + IRQ10, + IRQ11, + IRQ15 }; /* * Interrupt conversion table for the HP PC LAN+ */ -static unsigned short ed_hpp_intr_val[] = { +static unsigned short ed_hpp_intr_mask[] = { 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ - 3, /* 3 */ - 4, /* 4 */ - 5, /* 5 */ - 6, /* 6 */ - 7, /* 7 */ + IRQ3, /* 3 */ + IRQ4, /* 4 */ + IRQ5, /* 5 */ + IRQ6, /* 6 */ + IRQ7, /* 7 */ 0, /* 8 */ - 9, /* 9 */ - 10, /* 10 */ - 11, /* 11 */ - 12, /* 12 */ + IRQ9, /* 9 */ + IRQ10, /* 10 */ + IRQ11, /* 11 */ + IRQ12, /* 12 */ 0, /* 13 */ 0, /* 14 */ - 15 /* 15 */ -}; - -static struct isa_pnp_id ed_ids[] = { - { 0xd680d041, "NE2000 Compatible" }, /* PNP80d6 */ - { 0x1980635e, "WSC8019" }, /* WSC8019 */ - { 0x0131d805, "Acer ALN-101T" }, /* ANX3101 */ - { 0x01200507, "PLANET ENW-2401" }, /* AXE2001 */ - { 0x19808c4a, "Realtek Plug & Play Ethernet Card" }, /* RTL8019 */ - { 0x0090252a, "CNet NE2000 Compatible" }, /* JQE9000 */ - { 0x0020832e, "Kingston EtheRX KNE20 Plug & Play ISA" }, /* KTC2000 */ - { 0, NULL} + IRQ15 /* 15 */ }; +/* + * Determine if the device is present + * + * on entry: + * a pointer to an isa_device struct + * on exit: + * NULL if device not found + * or # of i/o addresses used (if found) + */ static int -ed_isa_probe(dev) - device_t dev; +ed_probe(isa_dev) + struct isa_device *isa_dev; { - struct ed_softc *sc = device_get_softc(dev); - int error = 0; + int nports; - bzero(sc, sizeof(struct ed_softc)); + nports = ed_probe_WD80x3(isa_dev); + if (nports) + return (nports); - /* Check isapnp ids */ - error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids); + nports = ed_probe_3Com(isa_dev); + if (nports) + return (nports); - /* If the card had a PnP ID that didn't match any we know about */ - if (error == ENXIO) - goto end; + nports = ed_probe_Novell(isa_dev); + if (nports) + return (nports); - /* If we found a PnP card. */ - if (error == 0) { - error = ed_probe_Novell(dev); - goto end; - } - - /* Heuristic probes */ + nports = ed_probe_HP_pclanp(isa_dev); + if (nports) + return (nports); - error = ed_probe_WD80x3(dev); - if (error == 0) - goto end; - ed_release_resources(dev); - - error = ed_probe_3Com(dev); - if (error == 0) - goto end; - ed_release_resources(dev); - - error = ed_probe_Novell(dev); - if (error == 0) - goto end; - ed_release_resources(dev); - - error = ed_probe_HP_pclanp(dev); - if (error == 0) - goto end; - ed_release_resources(dev); - -end: - if (error == 0) - error = ed_alloc_irq(dev, 0, 0); - - ed_release_resources(dev); - return (error); + return (0); } /* @@ -376,22 +404,15 @@ ed_probe_generic8390(sc) * Probe and vendor-specific initialization routine for SMC/WD80x3 boards */ static int -ed_probe_WD80x3(dev) - device_t dev; +ed_probe_WD80x3(isa_dev) + struct isa_device *isa_dev; { - struct ed_softc *sc = device_get_softc(dev); - int error; + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; int i; - int flags = device_get_flags(dev); u_int memsize, maddr; u_char iptr, isa16bit, sum; - u_long conf_maddr, conf_msize, irq, junk; - error = ed_alloc_port(dev, 0, ED_WD_IO_PORTS); - if (error) - return (error); - - sc->asic_addr = rman_get_start(sc->port_res); + sc->asic_addr = isa_dev->id_iobase; sc->nic_addr = sc->asic_addr + ED_WD_NIC_OFFSET; sc->is790 = 0; @@ -418,7 +439,7 @@ ed_probe_WD80x3(dev) */ if (inb(sc->asic_addr + ED_WD_CARD_ID) != ED_TYPE_WD8003E || inb(sc->asic_addr + ED_WD_PROM + 7) != 0) - return (ENXIO); + return (0); } /* reset card to force it into a known state. */ #ifdef TOSH_ETHER @@ -553,15 +574,9 @@ ed_probe_WD80x3(dev) memsize = 8192; } - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_MEMORY, 0, - &conf_maddr, &conf_msize); - if (error) - return (error); - #if ED_DEBUG printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%d\n", - sc->type, sc->type_str, isa16bit, memsize, conf_msize); + sc->type, sc->type_str, isa16bit, memsize, isa_dev->id_msize); for (i = 0; i < 8; i++) printf("%x -> %x\n", i, inb(sc->asic_addr + i)); #endif @@ -569,23 +584,23 @@ ed_probe_WD80x3(dev) /* * Allow the user to override the autoconfiguration */ - if (conf_msize > 1) - memsize = conf_msize; + if (isa_dev->id_msize) + memsize = isa_dev->id_msize; - maddr = conf_maddr; + maddr = (u_int) isa_dev->id_maddr & 0xffffff; if (maddr < 0xa0000 || maddr + memsize > 0x1000000) { - device_printf(dev, "Invalid ISA memory address range configured: 0x%x - 0x%x\n", - maddr, maddr + memsize); - return (ENXIO); + printf("ed%d: Invalid ISA memory address range configured: 0x%x - 0x%x\n", + isa_dev->id_unit, maddr, maddr + memsize); + return 0; } /* * (note that if the user specifies both of the following flags that * '8bit' mode intentionally has precedence) */ - if (flags & ED_FLAGS_FORCE_16BIT_MODE) + if (isa_dev->id_flags & ED_FLAGS_FORCE_16BIT_MODE) isa16bit = 1; - if (flags & ED_FLAGS_FORCE_8BIT_MODE) + if (isa_dev->id_flags & ED_FLAGS_FORCE_8BIT_MODE) isa16bit = 0; /* @@ -597,76 +612,58 @@ ed_probe_WD80x3(dev) /* * Assemble together the encoded interrupt number. */ - iptr = (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_IR2) | - ((inb(sc->asic_addr + ED_WD_IRR) & + iptr = (inb(isa_dev->id_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) | + ((inb(isa_dev->id_iobase + ED_WD_IRR) & (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5); /* * If no interrupt specified (or "?"), use what the board tells us. */ - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - &irq, &junk); - if (error) { - ISA_SET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - ed_intr_val[iptr], 1); - } + if (isa_dev->id_irq <= 0) + isa_dev->id_irq = ed_intr_mask[iptr]; /* * Enable the interrupt. */ - outb(sc->asic_addr + ED_WD_IRR, - inb(sc->asic_addr + ED_WD_IRR) | ED_WD_IRR_IEN); + outb(isa_dev->id_iobase + ED_WD_IRR, + inb(isa_dev->id_iobase + ED_WD_IRR) | ED_WD_IRR_IEN); } if (sc->is790) { - outb(sc->asic_addr + ED_WD790_HWR, - inb(sc->asic_addr + ED_WD790_HWR) | ED_WD790_HWR_SWH); - iptr = (((inb(sc->asic_addr + ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) | - (inb(sc->asic_addr + ED_WD790_GCR) & + outb(isa_dev->id_iobase + ED_WD790_HWR, + inb(isa_dev->id_iobase + ED_WD790_HWR) | ED_WD790_HWR_SWH); + iptr = (((inb(isa_dev->id_iobase + ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) | + (inb(isa_dev->id_iobase + ED_WD790_GCR) & (ED_WD790_GCR_IR1 | ED_WD790_GCR_IR0)) >> 2); - outb(sc->asic_addr + ED_WD790_HWR, - inb(sc->asic_addr + ED_WD790_HWR) & ~ED_WD790_HWR_SWH); + outb(isa_dev->id_iobase + ED_WD790_HWR, + inb(isa_dev->id_iobase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH); /* * If no interrupt specified (or "?"), use what the board tells us. */ - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - &irq, &junk); - if (error) { - ISA_SET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - ed_790_intr_val[iptr], 1); - } + if (isa_dev->id_irq <= 0) + isa_dev->id_irq = ed_790_intr_mask[iptr]; /* * Enable interrupts. */ - outb(sc->asic_addr + ED_WD790_ICR, - inb(sc->asic_addr + ED_WD790_ICR) | ED_WD790_ICR_EIL); + outb(isa_dev->id_iobase + ED_WD790_ICR, + inb(isa_dev->id_iobase + ED_WD790_ICR) | ED_WD790_ICR_EIL); } - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - &irq, &junk); - if (error) { - device_printf(dev, "%s cards don't support auto-detected/assigned interrupts.\n", - sc->type_str); - return (ENXIO); + if (isa_dev->id_irq <= 0) { + printf("ed%d: %s cards don't support auto-detected/assigned interrupts.\n", + isa_dev->id_unit, sc->type_str); + return (0); } sc->isa16bit = isa16bit; sc->mem_shared = 1; - - error = ed_alloc_memory(dev, 0, memsize); - if (error) - return (error); - sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res); + isa_dev->id_msize = memsize; + sc->mem_start = (caddr_t) isa_dev->id_maddr; /* * allocate one xmit buffer if < 16k, two buffers otherwise */ if ((memsize < 16384) || - (flags & ED_FLAGS_NO_MULTI_BUFFERING)) { + (isa_dev->id_flags & ED_FLAGS_NO_MULTI_BUFFERING)) { sc->txb_cnt = 1; } else { sc->txb_cnt = 2; @@ -750,8 +747,8 @@ ed_probe_WD80x3(dev) for (i = 0; i < memsize; ++i) { if (sc->mem_start[i]) { - device_printf(dev, "failed to clear shared memory at %lx - check configuration\n", - kvtop(sc->mem_start + i)); + printf("ed%d: failed to clear shared memory at %lx - check configuration\n", + isa_dev->id_unit, kvtop(sc->mem_start + i)); /* * Disable 16 bit access to shared memory @@ -763,7 +760,7 @@ ed_probe_WD80x3(dev) outb(sc->asic_addr + ED_WD_LAAR, sc->wd_laar_proto & ~ED_WD_LAAR_M16EN); } - return (ENXIO); + return (0); } } @@ -782,30 +779,23 @@ ed_probe_WD80x3(dev) outb(sc->asic_addr + ED_WD_LAAR, sc->wd_laar_proto & ~ED_WD_LAAR_M16EN); } - return (0); + return (ED_WD_IO_PORTS); } /* * Probe and vendor-specific initialization routine for 3Com 3c503 boards */ static int -ed_probe_3Com(dev) - device_t dev; +ed_probe_3Com(isa_dev) + struct isa_device *isa_dev; { - struct ed_softc *sc = device_get_softc(dev); - int error; + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; int i; - int flags = device_get_flags(dev); u_int memsize; u_char isa16bit; - u_long conf_maddr, conf_msize, irq, junk; - error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS); - if (error) - return (error); - - sc->asic_addr = rman_get_start(sc->port_res) + ED_3COM_ASIC_OFFSET; - sc->nic_addr = rman_get_start(sc->port_res) + ED_3COM_NIC_OFFSET; + sc->asic_addr = isa_dev->id_iobase + ED_3COM_ASIC_OFFSET; + sc->nic_addr = isa_dev->id_iobase + ED_3COM_NIC_OFFSET; /* * Verify that the kernel configured I/O address matches the board @@ -813,70 +803,64 @@ ed_probe_3Com(dev) */ switch (inb(sc->asic_addr + ED_3COM_BCFR)) { case ED_3COM_BCFR_300: - if (rman_get_start(sc->port_res) != 0x300) - return (ENXIO); + if (isa_dev->id_iobase != 0x300) + return (0); break; case ED_3COM_BCFR_310: - if (rman_get_start(sc->port_res) != 0x310) - return (ENXIO); + if (isa_dev->id_iobase != 0x310) + return (0); break; case ED_3COM_BCFR_330: - if (rman_get_start(sc->port_res) != 0x330) - return (ENXIO); + if (isa_dev->id_iobase != 0x330) + return (0); break; case ED_3COM_BCFR_350: - if (rman_get_start(sc->port_res) != 0x350) - return (ENXIO); + if (isa_dev->id_iobase != 0x350) + return (0); break; case ED_3COM_BCFR_250: - if (rman_get_start(sc->port_res) != 0x250) - return (ENXIO); + if (isa_dev->id_iobase != 0x250) + return (0); break; case ED_3COM_BCFR_280: - if (rman_get_start(sc->port_res) != 0x280) - return (ENXIO); + if (isa_dev->id_iobase != 0x280) + return (0); break; case ED_3COM_BCFR_2A0: - if (rman_get_start(sc->port_res) != 0x2a0) - return (ENXIO); + if (isa_dev->id_iobase != 0x2a0) + return (0); break; case ED_3COM_BCFR_2E0: - if (rman_get_start(sc->port_res) != 0x2e0) - return (ENXIO); + if (isa_dev->id_iobase != 0x2e0) + return (0); break; default: - return (ENXIO); + return (0); } - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_MEMORY, 0, - &conf_maddr, &conf_msize); - if (error) - return (error); - /* * Verify that the kernel shared memory address matches the board * configured address. */ switch (inb(sc->asic_addr + ED_3COM_PCFR)) { case ED_3COM_PCFR_DC000: - if (conf_maddr != 0xdc000) - return (ENXIO); + if (kvtop(isa_dev->id_maddr) != 0xdc000) + return (0); break; case ED_3COM_PCFR_D8000: - if (conf_maddr != 0xd8000) - return (ENXIO); + if (kvtop(isa_dev->id_maddr) != 0xd8000) + return (0); break; case ED_3COM_PCFR_CC000: - if (conf_maddr != 0xcc000) - return (ENXIO); + if (kvtop(isa_dev->id_maddr) != 0xcc000) + return (0); break; case ED_3COM_PCFR_C8000: - if (conf_maddr != 0xc8000) - return (ENXIO); + if (kvtop(isa_dev->id_maddr) != 0xc8000) + return (0); break; default: - return (ENXIO); + return (0); } @@ -968,11 +952,7 @@ ed_probe_3Com(dev) */ outb(sc->nic_addr + ED_P2_CR, ED_CR_RD2 | ED_CR_STP); - error = ed_alloc_memory(dev, 0, memsize); - if (error) - return (error); - - sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res); + sc->mem_start = (caddr_t) isa_dev->id_maddr; sc->mem_size = memsize; sc->mem_end = sc->mem_start + memsize; @@ -986,7 +966,7 @@ ed_probe_3Com(dev) * we optimize for linear transfers of same-size packets.) */ if (isa16bit) { - if (flags & ED_FLAGS_NO_MULTI_BUFFERING) + if (isa_dev->id_flags & ED_FLAGS_NO_MULTI_BUFFERING) sc->txb_cnt = 1; else sc->txb_cnt = 2; @@ -1017,29 +997,23 @@ ed_probe_3Com(dev) /* * Set IRQ. 3c503 only allows a choice of irq 2-5. */ - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - &irq, &junk); - if (error) - return (error); - - switch (irq) { - case 2: + switch (isa_dev->id_irq) { + case IRQ2: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2); break; - case 3: + case IRQ3: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3); break; - case 4: + case IRQ4: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4); break; - case 5: + case IRQ5: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5); break; default: - device_printf(dev, "Invalid irq configuration (%ld) must be 3-5,9 for 3c503\n", - irq); - return (ENXIO); + printf("ed%d: Invalid irq configuration (%d) must be 3-5,9 for 3c503\n", + isa_dev->id_unit, ffs(isa_dev->id_irq) - 1); + return (0); } /* @@ -1066,35 +1040,31 @@ ed_probe_3Com(dev) for (i = 0; i < memsize; ++i) if (sc->mem_start[i]) { - device_printf(dev, "failed to clear shared memory at %lx - check configuration\n", - kvtop(sc->mem_start + i)); - return (ENXIO); + printf("ed%d: failed to clear shared memory at %lx - check configuration\n", + isa_dev->id_unit, kvtop(sc->mem_start + i)); + return (0); } - return (0); + isa_dev->id_msize = memsize; + return (ED_3COM_IO_PORTS); } /* * Probe and vendor-specific initialization routine for NE1000/2000 boards */ static int -ed_probe_Novell_generic(dev, port_rid, flags) - device_t dev; - int port_rid; +ed_probe_Novell_generic(sc, port, unit, flags) + struct ed_softc *sc; + int port; + int unit; int flags; { - struct ed_softc *sc = device_get_softc(dev); u_int memsize, n; u_char romdata[16], tmp; static char test_pattern[32] = "THIS is A memory TEST pattern"; char test_buffer[32]; - int error; - error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS); - if (error) - return (error); - - sc->asic_addr = rman_get_start(sc->port_res) + ED_NOVELL_ASIC_OFFSET; - sc->nic_addr = rman_get_start(sc->port_res) + ED_NOVELL_NIC_OFFSET; + sc->asic_addr = port + ED_NOVELL_ASIC_OFFSET; + sc->nic_addr = port + ED_NOVELL_NIC_OFFSET; /* XXX - do Novell-specific probe here */ @@ -1128,7 +1098,7 @@ ed_probe_Novell_generic(dev, port_rid, flags) /* Make sure that we really have an 8390 based board */ if (!ed_probe_generic8390(sc)) - return (ENXIO); + return (0); sc->vendor = ED_VENDOR_NOVELL; sc->mem_shared = 0; @@ -1178,7 +1148,7 @@ ed_probe_Novell_generic(dev, port_rid, flags) ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern)); if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) - return (ENXIO); /* not an NE2000 either */ + return (0); /* not an NE2000 either */ sc->type = ED_TYPE_NE2000; sc->type_str = "NE2000"; @@ -1233,8 +1203,8 @@ ed_probe_Novell_generic(dev, port_rid, flags) } if (mstart == 0) { - device_printf(dev, "Cannot find start of RAM.\n"); - return (ENXIO); + printf("ed%d: Cannot find start of RAM.\n", unit); + return 0; } /* Search for the start of RAM. */ for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) { @@ -1255,10 +1225,10 @@ ed_probe_Novell_generic(dev, port_rid, flags) } if (msize == 0) { - device_printf(dev, "Cannot find any RAM, start : %d, x = %d.\n", mstart, x); - return (ENXIO); + printf("ed%d: Cannot find any RAM, start : %d, x = %d.\n", unit, mstart, x); + return 0; } - device_printf(dev, "RAM start at %d, size : %d.\n", mstart, msize); + printf("ed%d: RAM start at %d, size : %d.\n", unit, mstart, msize); sc->mem_size = msize; sc->mem_start = (char *) mstart; @@ -1294,17 +1264,25 @@ ed_probe_Novell_generic(dev, port_rid, flags) /* clear any pending interrupts that might have occurred above */ outb(sc->nic_addr + ED_P0_ISR, 0xff); - return (0); + return (ED_NOVELL_IO_PORTS); } static int -ed_probe_Novell(dev) - device_t dev; +ed_probe_Novell(isa_dev) + struct isa_device *isa_dev; { - return ed_probe_Novell_generic(dev, 0, device_get_flags(dev)); + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; + int nports; + + nports = ed_probe_Novell_generic(sc, isa_dev->id_iobase, + isa_dev->id_unit, isa_dev->id_flags); + if (nports) + isa_dev->id_maddr = 0; + + return (nports); } -#if NCARDxx > 0 +#if NCARD > 0 /* * Probe framework for pccards. Replicates the standard framework, * minus the pccard driver registration and ignores the ether address @@ -1355,26 +1333,21 @@ ed_probe_pccard(isa_dev, ether) * command line. */ static int -ed_probe_HP_pclanp(dev) - device_t dev; +ed_probe_HP_pclanp(isa_dev) + struct isa_device *isa_dev; { - struct ed_softc *sc = device_get_softc(dev); - int error; + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; int n; /* temp var */ int memsize; /* mem on board */ u_char checksum; /* checksum of board address */ u_char irq; /* board configured IRQ */ char test_pattern[ED_HPP_TEST_SIZE]; /* read/write areas for */ char test_buffer[ED_HPP_TEST_SIZE]; /* probing card */ - u_long conf_maddr, conf_msize, conf_irq, junk; - error = ed_alloc_port(dev, 0, ED_HPP_IO_PORTS); - if (error) - return (error); /* Fill in basic information */ - sc->asic_addr = rman_get_start(sc->port_res) + ED_HPP_ASIC_OFFSET; - sc->nic_addr = rman_get_start(sc->port_res) + ED_HPP_NIC_OFFSET; + sc->asic_addr = isa_dev->id_iobase + ED_HPP_ASIC_OFFSET; + sc->nic_addr = isa_dev->id_iobase + ED_HPP_NIC_OFFSET; sc->is790 = 0; sc->isa16bit = 0; /* the 8390 core needs to be in byte mode */ @@ -1386,7 +1359,7 @@ ed_probe_HP_pclanp(dev) (inb(sc->asic_addr + ED_HPP_ID + 1) != 0x48) || ((inb(sc->asic_addr + ED_HPP_ID + 2) & 0xF0) != 0) || (inb(sc->asic_addr + ED_HPP_ID + 3) != 0x53)) - return ENXIO; + return 0; /* * Read the MAC address and verify checksum on the address. @@ -1400,7 +1373,7 @@ ed_probe_HP_pclanp(dev) checksum += inb(sc->asic_addr + ED_HPP_MAC_ADDR + ETHER_ADDR_LEN); if (checksum != 0xFF) - return ENXIO; + return 0; /* * Verify that the software model number is 0. @@ -1409,7 +1382,7 @@ ed_probe_HP_pclanp(dev) outw(sc->asic_addr + ED_HPP_PAGING, ED_HPP_PAGE_ID); if (((sc->hpp_id = inw(sc->asic_addr + ED_HPP_PAGE_4)) & ED_HPP_ID_SOFT_MODEL_MASK) != 0x0000) - return ENXIO; + return 0; /* * Read in and save the current options configured on card. @@ -1440,7 +1413,7 @@ ed_probe_HP_pclanp(dev) DELAY(5000); if (!(inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RST)) - return ENXIO; /* reset did not complete */ + return 0; /* reset did not complete */ /* * Read out configuration information. @@ -1454,25 +1427,19 @@ ed_probe_HP_pclanp(dev) * Check for impossible IRQ. */ - if (irq >= (sizeof(ed_hpp_intr_val) / sizeof(ed_hpp_intr_val[0]))) - return ENXIO; + if (irq >= (sizeof(ed_hpp_intr_mask) / sizeof(ed_hpp_intr_mask[0]))) + return 0; /* * If the kernel IRQ was specified with a '?' use the cards idea * of the IRQ. If the kernel IRQ was explicitly specified, it * should match that of the hardware. */ - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - &conf_irq, &junk); - if (error) { - ISA_SET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, 0, - ed_hpp_intr_val[irq], 1); - } else { - if (conf_irq != ed_hpp_intr_val[irq]) - return (ENXIO); - } + + if (isa_dev->id_irq <= 0) + isa_dev->id_irq = ed_hpp_intr_mask[irq]; + else if (isa_dev->id_irq != ed_hpp_intr_mask[irq]) + return 0; /* * Fill in softconfig info. @@ -1487,13 +1454,6 @@ ed_probe_HP_pclanp(dev) sc->hpp_mem_start = NULL;/* no memory mapped I/O by default */ - /* - * The board has 32KB of memory. Is there a way to determine - * this programmatically? - */ - - memsize = 32768; - /* * Check if memory mapping of the I/O registers possible. */ @@ -1513,22 +1473,20 @@ ed_probe_HP_pclanp(dev) * Check that the kernel specified start of memory and * hardware's idea of it match. */ - error = ISA_GET_RESOURCE(device_get_parent(dev), dev, - SYS_RES_MEMORY, 0, - &conf_maddr, &conf_msize); - if (error) - return (error); - if (mem_addr != conf_maddr) - return ENXIO; + if (mem_addr != kvtop(isa_dev->id_maddr)) + return 0; - error = ed_alloc_memory(dev, 0, memsize); - if (error) - return (error); - - sc->hpp_mem_start = rman_get_virtual(sc->mem_res); + sc->hpp_mem_start = isa_dev->id_maddr; } + /* + * The board has 32KB of memory. Is there a way to determine + * this programmatically? + */ + + memsize = 32768; + /* * Fill in the rest of the soft config structure. */ @@ -1539,7 +1497,7 @@ ed_probe_HP_pclanp(dev) sc->tx_page_start = ED_HPP_TX_PAGE_OFFSET; - if (device_get_flags(dev) & ED_FLAGS_NO_MULTI_BUFFERING) + if (isa_dev->id_flags & ED_FLAGS_NO_MULTI_BUFFERING) sc->txb_cnt = 1; else sc->txb_cnt = 2; @@ -1608,7 +1566,7 @@ ed_probe_HP_pclanp(dev) if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) - return ENXIO; + return 0; } return (ED_HPP_IO_PORTS); @@ -1667,102 +1625,6 @@ ed_hpp_set_physical_link(struct ed_softc *sc) } -/* - * Allocate a port resource with the given resource id. - */ -static int -ed_alloc_port(dev, rid, size) - device_t dev; - int rid; - int size; -{ - struct ed_softc *sc = device_get_softc(dev); - struct resource *res; - - res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0ul, ~0ul, size, RF_ACTIVE); - if (res) { - sc->port_rid = rid; - sc->port_res = res; - sc->port_used = 1; - return (0); - } else { - return (ENOENT); - } -} - -/* - * Allocate a memory resource with the given resource id. - */ -static int -ed_alloc_memory(dev, rid, size) - device_t dev; - int rid; - int size; -{ - struct ed_softc *sc = device_get_softc(dev); - struct resource *res; - - res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0ul, ~0ul, size, RF_ACTIVE); - if (res) { - sc->mem_rid = rid; - sc->mem_res = res; - sc->mem_used = 1; - return (0); - } else { - return (ENOENT); - } -} - -/* - * Allocate an irq resource with the given resource id. - */ -static int -ed_alloc_irq(dev, rid, flags) - device_t dev; - int rid; - int flags; -{ - struct ed_softc *sc = device_get_softc(dev); - struct resource *res; - - res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, - 0ul, ~0ul, 1, (RF_ACTIVE | flags)); - if (res) { - sc->irq_rid = rid; - sc->irq_res = res; - return (0); - } else { - return (ENOENT); - } -} - -/* - * Release all resources - */ -static void -ed_release_resources(dev) - device_t dev; -{ - struct ed_softc *sc = device_get_softc(dev); - - if (sc->port_res) { - bus_release_resource(dev, SYS_RES_IOPORT, - sc->port_rid, sc->port_res); - sc->port_res = 0; - } - if (sc->mem_res) { - bus_release_resource(dev, SYS_RES_MEMORY, - sc->mem_rid, sc->mem_res); - sc->mem_res = 0; - } - if (sc->irq_res) { - bus_release_resource(dev, SYS_RES_IRQ, - sc->irq_rid, sc->irq_res); - sc->irq_res = 0; - } -} /* * Install interface into kernel networking data structures @@ -1856,61 +1718,40 @@ ed_attach(sc, unit, flags) #if NBPF > 0 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif - return (0); + return 1; } static int -ed_isa_attach(dev) - device_t dev; +ed_attach_isa(isa_dev) + struct isa_device *isa_dev; { - struct ed_softc *sc = device_get_softc(dev); - int flags = device_get_flags(dev); - int error; + int unit = isa_dev->id_unit; + struct ed_softc *sc = &ed_softc[unit]; + int flags = isa_dev->id_flags; - if (sc->port_used > 0) - ed_alloc_port(dev, sc->port_rid, 1); - if (sc->mem_used) - ed_alloc_memory(dev, sc->mem_rid, 1); - ed_alloc_irq(dev, sc->irq_rid, 0); - - error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, - edintr, sc, &sc->irq_handle); - if (error) { - ed_release_resources(dev); - return (error); - } - - return ed_attach(sc, device_get_unit(dev), flags); + isa_dev->id_ointr = edintr; + return ed_attach(sc, unit, flags); } #if NPCI > 0 -int -ed_attach_NE2000_pci(dev, port_rid) - device_t dev; - int port_rid; +void * +ed_attach_NE2000_pci(unit, port) + int unit; + int port; { - struct ed_softc *sc = device_get_softc(dev); - int flags = 0; - int error; + struct ed_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); + int isa_flags = 0; - error = ed_probe_Novell_generic(dev, port_rid, flags); - if (error) - return (error); + if (!sc) + return sc; - error = ed_alloc_irq(dev, 0, RF_SHAREABLE); - if (error) { - ed_release_resources(dev); - return (error); + bzero(sc, sizeof *sc); + if (ed_probe_Novell_generic(sc, port, unit, isa_flags) == 0 + || ed_attach(sc, unit, isa_flags) == 0) { + free(sc, M_DEVBUF); + return NULL; } - - error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, - edintr, sc, &sc->irq_handle); - if (error) { - ed_release_resources(dev); - return (error); - } - - return ed_attach(sc, device_get_unit(dev), flags); + return sc; } #endif @@ -2482,11 +2323,10 @@ ed_rint(sc) /* * Ethernet interface interrupt processor */ -static void -edintr(arg) - void *arg; +void +edintr_sc(sc) + struct ed_softc *sc; { - struct ed_softc *sc = (struct ed_softc*) arg; struct ifnet *ifp = (struct ifnet *)sc; u_char isr; @@ -2725,6 +2565,13 @@ edintr(arg) } } +static void +edintr(unit) + int unit; +{ + edintr_sc (&ed_softc[unit]); +} + /* * Process an ioctl request. This code needs some work - it looks * pretty ugly. @@ -3582,20 +3429,87 @@ ds_getmcaf(sc, mcaf) } } -static device_method_t ed_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ed_isa_probe), - DEVMETHOD(device_attach, ed_isa_attach), +/* + * support PnP cards if we are using 'em + */ - { 0, 0 } +#if NPNP > 0 + +static pnpid_t edpnp_ids[] = { + { 0xd680d041, "NE2000"}, + { 0 } }; -static driver_t ed_isa_driver = { - "ed", - ed_isa_methods, - sizeof(struct ed_softc) +static char *edpnp_probe(u_long csn, u_long vend_id); +static void edpnp_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); +static u_long nedpnp = NED; + +static struct pnp_device edpnp = { + "edpnp", + edpnp_probe, + edpnp_attach, + &nedpnp, + &net_imask }; +DATA_SET (pnpdevice_set, edpnp); -static devclass_t ed_isa_devclass; +static char * +edpnp_probe(u_long csn, u_long vend_id) +{ + pnpid_t *id; + char *s = NULL; -DRIVER_MODULE(ed, isa, ed_isa_driver, ed_isa_devclass, 0, 0); + for(id = edpnp_ids; id->vend_id != 0; id++) { + if (vend_id == id->vend_id) { + s = id->id_str; + break; + } + } + + if (s) { + struct pnp_cinfo d; + read_pnp_parms(&d, 0); + if (d.enable == 0 || d.flags & 1) { + printf("CSN %lu is disabled.\n", csn); + return (NULL); + } + + } + + return (s); +} + +static void +edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) +{ + struct pnp_cinfo d; + + if (dev->id_unit >= NED) + return; + + if (read_pnp_parms(&d, 0) == 0) { + printf("failed to read pnp parms\n"); + return; + } + + write_pnp_parms(&d, 0); + + enable_pnp_card(); + + dev->id_iobase = d.port[0]; + dev->id_irq = (1 << d.irq[0]); + dev->id_ointr = edintr; + dev->id_drq = -1; + + if (dev->id_driver == NULL) { + dev->id_driver = &eddriver; + dev->id_id = isa_compat_nextid(); + } + + if ((dev->id_alive = ed_probe(dev)) != 0) + ed_attach_isa(dev); + else + printf("ed%d: probe failed\n", dev->id_unit); +} +#endif