summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-09-19 07:24:07 +0000
committerobrien <obrien@FreeBSD.org>1999-09-19 07:24:07 +0000
commit899c0fd4e9223191a98defdbb9ab72a9af1cd503 (patch)
treef0554fc21be29cd4c07eced0a8ab1c3a20f839fc /sys
parentbeba2c930cbfe78cec732754669e47738f9929b5 (diff)
downloadFreeBSD-src-899c0fd4e9223191a98defdbb9ab72a9af1cd503.zip
FreeBSD-src-899c0fd4e9223191a98defdbb9ab72a9af1cd503.tar.gz
Make `ed' PC-Cards work again. It has been over two weeks that laptop
users have suffered from this breakage, w/o commitment from someone that they would fix the problems. This effectively backs out revs 1.{157-160}. It does however fix the build problem that caused 1.157 to be committed. If the changes from rev 1.156-1.160 can't be fully tested by the committer, may I offer posting a diff in the freebsd-current mailing list for broader testing before inflicting this breakage again.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/if_ed.c854
1 files changed, 384 insertions, 470 deletions
diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c
index 42537ab..ec48735 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 <sys/param.h>
@@ -72,43 +73,90 @@
#include <machine/clock.h>
#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/icu.h>
#include <i386/isa/if_edreg.h>
-#include <i386/isa/if_edvar.h>
-#include <isa/isavar.h>
-#include <isa/pnpvar.h>
+/*
+ * ed_softc: per line info and status
+ */
+struct ed_softc {
+ struct arpcom arpcom; /* ethernet common */
+
+ 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 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));
+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 <sys/select.h>
#include <sys/module.h>
#include <pccard/cardinfo.h>
@@ -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 */
-
- 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);
+ nports = ed_probe_HP_pclanp(isa_dev);
+ if (nports)
+ return (nports);
+
+ 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.
@@ -1488,13 +1455,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,23 +1473,21 @@ 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;
-
- error = ed_alloc_memory(dev, 0, memsize);
- if (error)
- return (error);
+ if (mem_addr != kvtop(isa_dev->id_maddr))
+ return 0;
- 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;
-
- 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);
- }
+ int unit = isa_dev->id_unit;
+ struct ed_softc *sc = &ed_softc[unit];
+ int flags = isa_dev->id_flags;
- 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;
-
- error = ed_probe_Novell_generic(dev, port_rid, flags);
- if (error)
- return (error);
-
- error = ed_alloc_irq(dev, 0, RF_SHAREABLE);
- if (error) {
- ed_release_resources(dev);
- return (error);
- }
+ struct ed_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
+ int isa_flags = 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);
+ if (!sc)
+ return sc;
+
+ 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;
}
-
- 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
+ */
+
+#if NPNP > 0
- { 0, 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
OpenPOWER on IntegriCloud