summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/files.alpha4
-rw-r--r--sys/conf/files.i3864
-rw-r--r--sys/conf/files.pc981
-rw-r--r--sys/conf/options3
-rw-r--r--sys/dev/ed/if_ed.c1745
-rw-r--r--sys/dev/ed/if_ed_3c503.c341
-rw-r--r--sys/dev/ed/if_ed_hpp.c663
-rw-r--r--sys/dev/ed/if_ed_isa.c10
-rw-r--r--sys/dev/ed/if_ed_novell.c288
-rw-r--r--sys/dev/ed/if_ed_sic.c159
-rw-r--r--sys/dev/ed/if_ed_wd80x3.c468
-rw-r--r--sys/dev/ed/if_edvar.h6
-rw-r--r--sys/i386/conf/NOTES3
-rw-r--r--sys/modules/ed/Makefile4
15 files changed, 1976 insertions, 1724 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 97eee33..cc2d33d 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -469,6 +469,7 @@ dev/drm/sis_ds.c optional sisdrm
dev/drm/sis_mm.c optional sisdrm
dev/drm/tdfx_drv.c optional tdfxdrm
dev/ed/if_ed.c optional ed
+dev/ed/if_ed_novell.c optional ed
dev/ed/if_ed_pccard.c optional ed pccard
dev/ed/if_ed_pci.c optional ed pci
dev/eisa/eisa_if.m standard
diff --git a/sys/conf/files.alpha b/sys/conf/files.alpha
index c3b03be..b256fd4 100644
--- a/sys/conf/files.alpha
+++ b/sys/conf/files.alpha
@@ -169,7 +169,11 @@ dev/advansys/adv_isa.c optional adv isa
dev/aic/aic_isa.c optional aic isa
dev/dec/mcclock.c optional mcclock
dev/dec/mcclock_if.m optional mcclock
+dev/ed/if_ed_3c503.c optional ed isa ed_3c503
dev/ed/if_ed_isa.c optional ed isa
+dev/ed/if_ed_wd80x3.c optional ed isa
+dev/ed/if_ed_hpp.c optional ed isa ed_hpp
+dev/ed/if_ed_sic.c optional ed isa ed_sic
dev/fb/fb.c optional fb
dev/fb/fb.c optional vga
dev/fb/splash.c optional splash
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 03ac732..7af1fbb 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -143,7 +143,11 @@ dev/ctau/if_ct.c optional ctau
dev/cx/csigma.c optional cx
dev/cx/cxddk.c optional cx
dev/cx/if_cx.c optional cx
+dev/ed/if_ed_3c503.c optional ed isa ed_3c503
dev/ed/if_ed_isa.c optional ed isa
+dev/ed/if_ed_wd80x3.c optional ed isa
+dev/ed/if_ed_hpp.c optional ed isa ed_hpp
+dev/ed/if_ed_sic.c optional ed isa ed_sic
dev/fb/fb.c optional fb
dev/fb/fb.c optional vga
dev/fb/splash.c optional splash
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 6d365cd..24e95a5 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -108,6 +108,7 @@ dev/ct/bshw_machdep.c optional ct
dev/ct/ct.c optional ct
dev/ct/ct_isa.c optional ct isa
dev/ed/if_ed_cbus.c optional ed isa
+dev/ed/wd80x3.c optional ed isa
dev/ed/if_ed_pccard.c optional ed card
dev/ep/if_ep_pccard.c optional ep card
dev/ex/if_ex_pccard.c optional ex card
diff --git a/sys/conf/options b/sys/conf/options
index e5b0a0d..f104f94 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -616,6 +616,9 @@ EISA_SLOTS opt_eisa.h
# ed driver
ED_NO_MIIBUS opt_ed.h
+ED_HPP opt_ed.h
+ED_3C503 opt_ed.h
+ED_SIC opt_ed.h
# wi driver
WI_SYMBOL_FIRMWARE opt_wi.h
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 22f9704..4a349e5 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -68,8 +68,6 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
-#include <machine/md_var.h>
-
#include <dev/ed/if_edreg.h>
#include <dev/ed/if_edvar.h>
@@ -91,68 +89,11 @@ static void ed_get_packet(struct ed_softc *, char *, u_short);
static __inline void ed_rint(struct ed_softc *);
static __inline void ed_xmit(struct ed_softc *);
static __inline char *ed_ring_copy(struct ed_softc *, char *, char *, u_short);
-static void ed_hpp_set_physical_link(struct ed_softc *);
-static void ed_hpp_readmem(struct ed_softc *, long, uint8_t *, uint16_t);
-static void ed_hpp_writemem(struct ed_softc *, uint8_t *, uint16_t,
- uint16_t);
-static u_short ed_hpp_write_mbufs(struct ed_softc *, struct mbuf *, int);
-
static u_short ed_pio_write_mbufs(struct ed_softc *, struct mbuf *, long);
static void ed_setrcr(struct ed_softc *);
/*
- * Interrupt conversion table for WD/SMC ASIC/83C584
- */
-static uint16_t ed_intr_val[] = {
- 9,
- 3,
- 5,
- 7,
- 10,
- 11,
- 15,
- 4
-};
-
-/*
- * Interrupt conversion table for 83C790
- */
-static uint16_t ed_790_intr_val[] = {
- 0,
- 9,
- 3,
- 5,
- 7,
- 10,
- 11,
- 15
-};
-
-/*
- * Interrupt conversion table for the HP PC LAN+
- */
-
-static uint16_t ed_hpp_intr_val[] = {
- 0, /* 0 */
- 0, /* 1 */
- 0, /* 2 */
- 3, /* 3 */
- 4, /* 4 */
- 5, /* 5 */
- 6, /* 6 */
- 7, /* 7 */
- 0, /* 8 */
- 9, /* 9 */
- 10, /* 10 */
- 11, /* 11 */
- 12, /* 12 */
- 0, /* 13 */
- 0, /* 14 */
- 15 /* 15 */
-};
-
-/*
* Generic probe routine for testing for the existance of a DS8390.
* Must be called after the NIC has just been reset. This routine
* works by looking at certain register values that are guaranteed
@@ -189,1387 +130,6 @@ ed_probe_generic8390(struct ed_softc *sc)
}
/*
- * Probe and vendor-specific initialization routine for SMC/WD80x3 boards
- */
-int
-ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
- int i;
- u_int memsize, maddr;
- u_char iptr, isa16bit, sum, totalsum;
- u_long conf_maddr, conf_msize, irq, junk;
-
- sc->chip_type = ED_CHIP_TYPE_DP8390;
-
- if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
- totalsum = ED_WD_ROM_CHECKSUM_TOTAL_TOSH_ETHER;
- ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_POW);
- DELAY(10000);
- }
- else
- totalsum = ED_WD_ROM_CHECKSUM_TOTAL;
-
- /*
- * Attempt to do a checksum over the station address PROM. If it
- * fails, it's probably not a SMC/WD board. There is a problem with
- * this, though: some clone WD boards don't pass the checksum test.
- * Danpex boards for one.
- */
- for (sum = 0, i = 0; i < 8; ++i)
- sum += ed_asic_inb(sc, ED_WD_PROM + i);
-
- if (sum != totalsum) {
-
- /*
- * Checksum is invalid. This often happens with cheap WD8003E
- * clones. In this case, the checksum byte (the eighth byte)
- * seems to always be zero.
- */
- if (ed_asic_inb(sc, ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
- ed_asic_inb(sc, ED_WD_PROM + 7) != 0)
- return (ENXIO);
- }
- /* reset card to force it into a known state. */
- if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER)
- ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
- else
- ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST);
-
- DELAY(100);
- ed_asic_outb(sc, ED_WD_MSR, ed_asic_inb(sc, ED_WD_MSR) & ~ED_WD_MSR_RST);
- /* wait in the case this card is reading its EEROM */
- DELAY(5000);
-
- sc->vendor = ED_VENDOR_WD_SMC;
- sc->type = ed_asic_inb(sc, ED_WD_CARD_ID);
-
- /*
- * Set initial values for width/size.
- */
- memsize = 8192;
- isa16bit = 0;
- switch (sc->type) {
- case ED_TYPE_WD8003S:
- sc->type_str = "WD8003S";
- break;
- case ED_TYPE_WD8003E:
- sc->type_str = "WD8003E";
- break;
- case ED_TYPE_WD8003EB:
- sc->type_str = "WD8003EB";
- break;
- case ED_TYPE_WD8003W:
- sc->type_str = "WD8003W";
- break;
- case ED_TYPE_WD8013EBT:
- sc->type_str = "WD8013EBT";
- memsize = 16384;
- isa16bit = 1;
- break;
- case ED_TYPE_WD8013W:
- sc->type_str = "WD8013W";
- memsize = 16384;
- isa16bit = 1;
- break;
- case ED_TYPE_WD8013EP: /* also WD8003EP */
- if (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) {
- isa16bit = 1;
- memsize = 16384;
- sc->type_str = "WD8013EP";
- } else {
- sc->type_str = "WD8003EP";
- }
- break;
- case ED_TYPE_WD8013WC:
- sc->type_str = "WD8013WC";
- memsize = 16384;
- isa16bit = 1;
- break;
- case ED_TYPE_WD8013EBP:
- sc->type_str = "WD8013EBP";
- memsize = 16384;
- isa16bit = 1;
- break;
- case ED_TYPE_WD8013EPC:
- sc->type_str = "WD8013EPC";
- memsize = 16384;
- isa16bit = 1;
- break;
- case ED_TYPE_SMC8216C: /* 8216 has 16K shared mem -- 8416 has 8K */
- case ED_TYPE_SMC8216T:
- if (sc->type == ED_TYPE_SMC8216C) {
- sc->type_str = "SMC8216/SMC8216C";
- } else {
- sc->type_str = "SMC8216T";
- }
-
- ed_asic_outb(sc, ED_WD790_HWR,
- ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
- switch (ed_asic_inb(sc, ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
- case ED_WD790_RAR_SZ64:
- memsize = 65536;
- break;
- case ED_WD790_RAR_SZ32:
- memsize = 32768;
- break;
- case ED_WD790_RAR_SZ16:
- memsize = 16384;
- break;
- case ED_WD790_RAR_SZ8:
- /* 8216 has 16K shared mem -- 8416 has 8K */
- if (sc->type == ED_TYPE_SMC8216C) {
- sc->type_str = "SMC8416C/SMC8416BT";
- } else {
- sc->type_str = "SMC8416T";
- }
- memsize = 8192;
- break;
- }
- ed_asic_outb(sc, ED_WD790_HWR,
- ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
-
- isa16bit = 1;
- sc->chip_type = ED_CHIP_TYPE_WD790;
- break;
- case ED_TYPE_TOSHIBA1:
- sc->type_str = "Toshiba1";
- memsize = 32768;
- isa16bit = 1;
- break;
- case ED_TYPE_TOSHIBA4:
- sc->type_str = "Toshiba4";
- memsize = 32768;
- isa16bit = 1;
- break;
- default:
- sc->type_str = "";
- break;
- }
-
- /*
- * Make some adjustments to initial values depending on what is found
- * in the ICR.
- */
- if (isa16bit && (sc->type != ED_TYPE_WD8013EBT)
- && (sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4)
- && ((ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
- isa16bit = 0;
- memsize = 8192;
- }
-
- error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
- &conf_maddr, &conf_msize);
- if (error)
- return (error);
-
-#ifdef ED_DEBUG
- printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%lu\n",
- sc->type, sc->type_str, isa16bit, memsize, conf_msize);
- for (i = 0; i < 8; i++)
- printf("%x -> %x\n", i, ed_asic_inb(sc, i));
-#endif
-
- /*
- * Allow the user to override the autoconfiguration
- */
- if (conf_msize > 1)
- memsize = conf_msize;
-
- maddr = conf_maddr;
- 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);
- }
-
- /*
- * (note that if the user specifies both of the following flags that
- * '8bit' mode intentionally has precedence)
- */
- if (flags & ED_FLAGS_FORCE_16BIT_MODE)
- isa16bit = 1;
- if (flags & ED_FLAGS_FORCE_8BIT_MODE)
- isa16bit = 0;
-
- /*
- * If possible, get the assigned interrupt number from the card and
- * use it.
- */
- if ((sc->type & ED_WD_SOFTCONFIG) &&
- (sc->chip_type != ED_CHIP_TYPE_WD790)) {
-
- /*
- * Assemble together the encoded interrupt number.
- */
- iptr = (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_IR2) |
- ((ed_asic_inb(sc, ED_WD_IRR) &
- (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
-
- /*
- * If no interrupt specified (or "?"), use what the board tells us.
- */
- error = bus_get_resource(dev, SYS_RES_IRQ, 0,
- &irq, &junk);
- if (error && intr_vals[0] != NULL) {
- error = bus_set_resource(dev, SYS_RES_IRQ, 0,
- intr_vals[0][iptr], 1);
- }
- if (error)
- return (error);
-
- /*
- * Enable the interrupt.
- */
- ed_asic_outb(sc, ED_WD_IRR,
- ed_asic_inb(sc, ED_WD_IRR) | ED_WD_IRR_IEN);
- }
- if (sc->chip_type == ED_CHIP_TYPE_WD790) {
- ed_asic_outb(sc, ED_WD790_HWR,
- ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
- iptr = (((ed_asic_inb(sc, ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) |
- (ed_asic_inb(sc, ED_WD790_GCR) &
- (ED_WD790_GCR_IR1 | ED_WD790_GCR_IR0)) >> 2);
- ed_asic_outb(sc, ED_WD790_HWR,
- ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
-
- /*
- * If no interrupt specified (or "?"), use what the board tells us.
- */
- error = bus_get_resource(dev, SYS_RES_IRQ, 0,
- &irq, &junk);
- if (error && intr_vals[1] != NULL) {
- error = bus_set_resource(dev, SYS_RES_IRQ, 0,
- intr_vals[1][iptr], 1);
- }
- if (error)
- return (error);
-
- /*
- * Enable interrupts.
- */
- ed_asic_outb(sc, ED_WD790_ICR,
- ed_asic_inb(sc, ED_WD790_ICR) | ED_WD790_ICR_EIL);
- }
- error = bus_get_resource(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);
- }
- sc->isa16bit = isa16bit;
- sc->mem_shared = 1;
-
- error = ed_alloc_memory(dev, 0, memsize);
- if (error) {
- printf("*** ed_alloc_memory() failed! (%d)\n", error);
- return (error);
- }
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
-
- /*
- * allocate one xmit buffer if < 16k, two buffers otherwise
- */
- if ((memsize < 16384) ||
- (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
- sc->txb_cnt = 1;
- } else {
- sc->txb_cnt = 2;
- }
- sc->tx_page_start = ED_WD_PAGE_OFFSET;
- sc->rec_page_start = ED_WD_PAGE_OFFSET + ED_TXBUF_SIZE * sc->txb_cnt;
- sc->rec_page_stop = ED_WD_PAGE_OFFSET + memsize / ED_PAGE_SIZE;
- sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * sc->rec_page_start);
- sc->mem_size = memsize;
- sc->mem_end = sc->mem_start + memsize;
-
- /*
- * Get station address from on-board ROM
- */
- for (i = 0; i < ETHER_ADDR_LEN; ++i)
- sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, ED_WD_PROM + i);
-
- /*
- * Set upper address bits and 8/16 bit access to shared memory.
- */
- if (isa16bit) {
- if (sc->chip_type == ED_CHIP_TYPE_WD790) {
- sc->wd_laar_proto = ed_asic_inb(sc, ED_WD_LAAR);
- } else {
- sc->wd_laar_proto = ED_WD_LAAR_L16EN |
- ((kvtop(sc->mem_start) >> 19) & ED_WD_LAAR_ADDRHI);
- }
- /*
- * Enable 16bit access
- */
- ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto |
- ED_WD_LAAR_M16EN);
- } else {
- if (((sc->type & ED_WD_SOFTCONFIG) ||
- (sc->type == ED_TYPE_TOSHIBA1) ||
- (sc->type == ED_TYPE_TOSHIBA4) ||
- (sc->type == ED_TYPE_WD8013EBT)) &&
- (sc->chip_type != ED_CHIP_TYPE_WD790)) {
- sc->wd_laar_proto = (kvtop(sc->mem_start) >> 19) &
- ED_WD_LAAR_ADDRHI;
- ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto);
- }
- }
-
- /*
- * Set address and enable interface shared memory.
- */
- if (sc->chip_type != ED_CHIP_TYPE_WD790) {
- if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
- ed_asic_outb(sc, ED_WD_MSR + 1,
- ((kvtop(sc->mem_start) >> 8) & 0xe0) | 4);
- ed_asic_outb(sc, ED_WD_MSR + 2,
- ((kvtop(sc->mem_start) >> 16) & 0x0f));
- ed_asic_outb(sc, ED_WD_MSR,
- ED_WD_MSR_MENB | ED_WD_MSR_POW);
- } else {
- ed_asic_outb(sc, ED_WD_MSR,
- ((kvtop(sc->mem_start) >> 13) &
- ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
- }
- sc->cr_proto = ED_CR_RD2;
- } else {
- ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_MENB);
- ed_asic_outb(sc, ED_WD790_HWR, (ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH));
- ed_asic_outb(sc, ED_WD790_RAR, ((kvtop(sc->mem_start) >> 13) & 0x0f) |
- ((kvtop(sc->mem_start) >> 11) & 0x40) |
- (ed_asic_inb(sc, ED_WD790_RAR) & 0xb0));
- ed_asic_outb(sc, ED_WD790_HWR, (ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH));
- sc->cr_proto = 0;
- }
-
-#if 0
- printf("starting memory performance test at 0x%x, size %d...\n",
- sc->mem_start, memsize*16384);
- for (i = 0; i < 16384; i++)
- bzero(sc->mem_start, memsize);
- printf("***DONE***\n");
-#endif
-
- /*
- * Now zero memory and verify that it is clear
- */
- bzero(sc->mem_start, memsize);
-
- for (i = 0; i < memsize; ++i) {
- if (sc->mem_start[i]) {
- device_printf(dev, "failed to clear shared memory at %jx - check configuration\n",
- (uintmax_t)kvtop(sc->mem_start + i));
-
- /*
- * Disable 16 bit access to shared memory
- */
- if (isa16bit) {
- if (sc->chip_type == ED_CHIP_TYPE_WD790) {
- ed_asic_outb(sc, ED_WD_MSR, 0x00);
- }
- ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto &
- ~ED_WD_LAAR_M16EN);
- }
- return (ENXIO);
- }
- }
-
- /*
- * Disable 16bit access to shared memory - we leave it
- * disabled so that 1) machines reboot properly when the board
- * is set 16 bit mode and there are conflicting 8bit
- * devices/ROMS in the same 128k address space as this boards
- * shared memory. and 2) so that other 8 bit devices with
- * shared memory can be used in this 128k region, too.
- */
- if (isa16bit) {
- if (sc->chip_type == ED_CHIP_TYPE_WD790) {
- ed_asic_outb(sc, ED_WD_MSR, 0x00);
- }
- ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto &
- ~ED_WD_LAAR_M16EN);
- }
- return (0);
-}
-
-int
-ed_probe_WD80x3(device_t dev, int port_rid, int flags)
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
- static uint16_t *intr_vals[] = {ed_intr_val, ed_790_intr_val};
-
- error = ed_alloc_port(dev, port_rid, ED_WD_IO_PORTS);
- if (error)
- return (error);
-
- sc->asic_offset = ED_WD_ASIC_OFFSET;
- sc->nic_offset = ED_WD_NIC_OFFSET;
-
- return ed_probe_WD80x3_generic(dev, flags, intr_vals);
-}
-
-/*
- * Probe and vendor-specific initialization routine for 3Com 3c503 boards
- */
-int
-ed_probe_3Com(device_t dev, int port_rid, int flags)
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
- int i;
- 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_offset = ED_3COM_ASIC_OFFSET;
- sc->nic_offset = ED_3COM_NIC_OFFSET;
-
- /*
- * Verify that the kernel configured I/O address matches the board
- * configured address
- */
- switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
- case ED_3COM_BCFR_300:
- if (rman_get_start(sc->port_res) != 0x300)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_310:
- if (rman_get_start(sc->port_res) != 0x310)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_330:
- if (rman_get_start(sc->port_res) != 0x330)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_350:
- if (rman_get_start(sc->port_res) != 0x350)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_250:
- if (rman_get_start(sc->port_res) != 0x250)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_280:
- if (rman_get_start(sc->port_res) != 0x280)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_2A0:
- if (rman_get_start(sc->port_res) != 0x2a0)
- return (ENXIO);
- break;
- case ED_3COM_BCFR_2E0:
- if (rman_get_start(sc->port_res) != 0x2e0)
- return (ENXIO);
- break;
- default:
- return (ENXIO);
- }
-
- error = bus_get_resource(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 (ed_asic_inb(sc, ED_3COM_PCFR)) {
- case ED_3COM_PCFR_DC000:
- if (conf_maddr != 0xdc000)
- return (ENXIO);
- break;
- case ED_3COM_PCFR_D8000:
- if (conf_maddr != 0xd8000)
- return (ENXIO);
- break;
- case ED_3COM_PCFR_CC000:
- if (conf_maddr != 0xcc000)
- return (ENXIO);
- break;
- case ED_3COM_PCFR_C8000:
- if (conf_maddr != 0xc8000)
- return (ENXIO);
- break;
- default:
- return (ENXIO);
- }
-
-
- /*
- * Reset NIC and ASIC. Enable on-board transceiver throughout reset
- * sequence because it'll lock up if the cable isn't connected if we
- * don't.
- */
- ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
-
- /*
- * Wait for a while, then un-reset it
- */
- DELAY(50);
-
- /*
- * The 3Com ASIC defaults to rather strange settings for the CR after
- * a reset - it's important to set it again after the following outb
- * (this is done when we map the PROM below).
- */
- ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
-
- /*
- * Wait a bit for the NIC to recover from the reset
- */
- DELAY(5000);
-
- sc->vendor = ED_VENDOR_3COM;
- sc->type_str = "3c503";
- sc->mem_shared = 1;
- sc->cr_proto = ED_CR_RD2;
-
- /*
- * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
- * to it.
- */
- memsize = 8192;
-
- /*
- * Get station address from on-board ROM
- */
-
- /*
- * First, map ethernet address PROM over the top of where the NIC
- * registers normally appear.
- */
- ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
-
- for (i = 0; i < ETHER_ADDR_LEN; ++i)
- sc->arpcom.ac_enaddr[i] = ed_nic_inb(sc, i);
-
- /*
- * Unmap PROM - select NIC registers. The proper setting of the
- * tranceiver is set in ed_init so that the attach code is given a
- * chance to set the default based on a compile-time config option
- */
- ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
-
- /*
- * Determine if this is an 8bit or 16bit board
- */
-
- /*
- * select page 0 registers
- */
- ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
-
- /*
- * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
- * board.
- */
- ed_nic_outb(sc, ED_P0_DCR, 0);
-
- /*
- * select page 2 registers
- */
- ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);
-
- /*
- * The 3c503 forces the WTS bit to a one if this is a 16bit board
- */
- if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
- isa16bit = 1;
- else
- isa16bit = 0;
-
- /*
- * select page 0 registers
- */
- ed_nic_outb(sc, 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_size = memsize;
- sc->mem_end = sc->mem_start + memsize;
-
- /*
- * We have an entire 8k window to put the transmit buffers on the
- * 16bit boards. But since the 16bit 3c503's shared memory is only
- * fast enough to overlap the loading of one full-size packet, trying
- * to load more than 2 buffers can actually leave the transmitter idle
- * during the load. So 2 seems the best value. (Although a mix of
- * variable-sized packets might change this assumption. Nonetheless,
- * we optimize for linear transfers of same-size packets.)
- */
- if (isa16bit) {
- if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
- sc->txb_cnt = 1;
- else
- sc->txb_cnt = 2;
-
- sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
- sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
- sc->rec_page_stop = memsize / ED_PAGE_SIZE +
- ED_3COM_RX_PAGE_OFFSET_16BIT;
- sc->mem_ring = sc->mem_start;
- } else {
- sc->txb_cnt = 1;
- sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
- sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
- sc->rec_page_stop = memsize / ED_PAGE_SIZE +
- ED_3COM_TX_PAGE_OFFSET_8BIT;
- sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
- }
-
- sc->isa16bit = isa16bit;
-
- /*
- * Initialize GA page start/stop registers. Probably only needed if
- * doing DMA, but what the hell.
- */
- ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
- ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
-
- /*
- * Set IRQ. 3c503 only allows a choice of irq 2-5.
- */
- error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
- if (error)
- return (error);
-
- switch (irq) {
- case 2:
- case 9:
- ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
- break;
- case 3:
- ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
- break;
- case 4:
- ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
- break;
- case 5:
- ed_asic_outb(sc, 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);
- }
-
- /*
- * Initialize GA configuration register. Set bank and enable shared
- * mem.
- */
- ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
- ED_3COM_GACFR_MBS0);
-
- /*
- * Initialize "Vector Pointer" registers. These gawd-awful things are
- * compared to 20 bits of the address on ISA, and if they match, the
- * shared memory is disabled. We set them to 0xffff0...allegedly the
- * reset vector.
- */
- ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
- ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
- ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);
-
- /*
- * Zero memory and verify that it is clear
- */
- bzero(sc->mem_start, memsize);
-
- for (i = 0; i < memsize; ++i)
- if (sc->mem_start[i]) {
- device_printf(dev, "failed to clear shared memory at %jx - check configuration\n",
- (uintmax_t)kvtop(sc->mem_start + i));
- return (ENXIO);
- }
- return (0);
-}
-
-/*
- * Probe and vendor-specific initialization routine for SIC boards
- */
-int
-ed_probe_SIC(device_t dev, int port_rid, int flags)
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
- int i;
- u_int memsize;
- u_long conf_maddr, conf_msize;
- u_char sum;
-
- error = ed_alloc_port(dev, 0, ED_SIC_IO_PORTS);
- if (error)
- return (error);
-
- sc->asic_offset = ED_SIC_ASIC_OFFSET;
- sc->nic_offset = ED_SIC_NIC_OFFSET;
-
- error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
- &conf_maddr, &conf_msize);
- if (error)
- return (error);
-
- memsize = 16384;
- if (conf_msize > 1)
- memsize = conf_msize;
-
- error = ed_alloc_memory(dev, 0, memsize);
- if (error)
- return (error);
-
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
- sc->mem_size = memsize;
-
- /* Reset card to force it into a known state. */
- ed_asic_outb(sc, 0, 0x00);
- DELAY(100);
-
- /*
- * Here we check the card ROM, if the checksum passes, and the
- * type code and ethernet address check out, then we know we have
- * an SIC card.
- */
- ed_asic_outb(sc, 0, 0x81);
- DELAY(100);
-
- sum = sc->mem_start[6];
- for (i = 0; i < ETHER_ADDR_LEN; i++) {
- sum ^= (sc->arpcom.ac_enaddr[i] = sc->mem_start[i]);
- }
-#ifdef ED_DEBUG
- device_printf(dev, "ed_probe_sic: got address %6D\n",
- sc->arpcom.ac_enaddr, ":");
-#endif
- if (sum != 0) {
- return (ENXIO);
- }
- if ((sc->arpcom.ac_enaddr[0] | sc->arpcom.ac_enaddr[1] |
- sc->arpcom.ac_enaddr[2]) == 0) {
- return (ENXIO);
- }
-
- sc->vendor = ED_VENDOR_SIC;
- sc->type_str = "SIC";
- sc->isa16bit = 0;
- sc->cr_proto = 0;
-
- /*
- * SIC RAM page 0x0000-0x3fff(or 0x7fff)
- */
- ed_asic_outb(sc, 0, 0x80);
- DELAY(100);
-
- /*
- * Now zero memory and verify that it is clear
- */
- bzero(sc->mem_start, sc->mem_size);
-
- for (i = 0; i < sc->mem_size; i++) {
- if (sc->mem_start[i]) {
- device_printf(dev, "failed to clear shared memory "
- "at %jx - check configuration\n",
- (uintmax_t)kvtop(sc->mem_start + i));
-
- return (ENXIO);
- }
- }
-
- sc->mem_shared = 1;
- sc->mem_end = sc->mem_start + sc->mem_size;
-
- /*
- * allocate one xmit buffer if < 16k, two buffers otherwise
- */
- if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
- sc->txb_cnt = 1;
- } else {
- sc->txb_cnt = 2;
- }
- sc->tx_page_start = 0;
-
- sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
- sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
-
- sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
-
- return (0);
-}
-
-/*
- * Probe and vendor-specific initialization routine for NE1000/2000 boards
- */
-int
-ed_probe_Novell_generic(device_t dev, 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];
-
- /* XXX - do Novell-specific probe here */
-
- /* Reset the board */
- if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
- ed_asic_outb(sc, ED_NOVELL_RESET, 0);
- DELAY(200);
- }
- tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
-
- /*
- * I don't know if this is necessary; probably cruft leftover from
- * Clarkson packet driver code. Doesn't do a thing on the boards I've
- * tested. -DG [note that an outb(0x84, 0) seems to work here, and is
- * non-invasive...but some boards don't seem to reset and I don't have
- * complete documentation on what the 'right' thing to do is...so we
- * do the invasive thing for now. Yuck.]
- */
- ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
- DELAY(5000);
-
- /*
- * This is needed because some NE clones apparently don't reset the
- * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
- * - this makes the probe invasive! ...Done against my better
- * judgement. -DLG
- */
- ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
-
- DELAY(5000);
-
- /* Make sure that we really have an 8390 based board */
- if (!ed_probe_generic8390(sc))
- return (ENXIO);
-
- sc->vendor = ED_VENDOR_NOVELL;
- sc->mem_shared = 0;
- sc->cr_proto = ED_CR_RD2;
-
- /*
- * Test the ability to read and write to the NIC memory. This has the
- * side affect of determining if this is an NE1000 or an NE2000.
- */
-
- /*
- * This prevents packets from being stored in the NIC memory when the
- * readmem routine turns on the start bit in the CR.
- */
- ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
-
- /* Temporarily initialize DCR for byte operations */
- ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
-
- ed_nic_outb(sc, ED_P0_PSTART, 8192 / ED_PAGE_SIZE);
- ed_nic_outb(sc, ED_P0_PSTOP, 16384 / ED_PAGE_SIZE);
-
- sc->isa16bit = 0;
-
- /*
- * Write a test pattern in byte mode. If this fails, then there
- * probably isn't any memory at 8k - which likely means that the board
- * is an NE2000.
- */
- ed_pio_writemem(sc, test_pattern, 8192, sizeof(test_pattern));
- ed_pio_readmem(sc, 8192, test_buffer, sizeof(test_pattern));
-
- if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
- sc->type = ED_TYPE_NE1000;
- sc->type_str = "NE1000";
- } else {
-
- /* neither an NE1000 nor a Linksys - try NE2000 */
- ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
- ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
- ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
-
- sc->isa16bit = 1;
-
- /*
- * Write a test pattern in word mode. If this also fails, then
- * we don't know what this board is.
- */
- ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
- ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
- if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
- sc->type = ED_TYPE_NE2000;
- sc->type_str = "NE2000";
- } else {
- return (ENXIO);
- }
- }
-
-
- /* 8k of memory plus an additional 8k if 16bit */
- memsize = 8192 + sc->isa16bit * 8192;
-
-#if 0 /* probably not useful - NE boards only come two ways */
- /* allow kernel config file overrides */
- if (isa_dev->id_msize)
- memsize = isa_dev->id_msize;
-#endif
-
- sc->mem_size = memsize;
-
- /* NIC memory doesn't start at zero on an NE board */
- /* The start address is tied to the bus width */
- sc->mem_start = (char *) 8192 + sc->isa16bit * 8192;
- sc->mem_end = sc->mem_start + memsize;
- sc->tx_page_start = memsize / ED_PAGE_SIZE;
-
- if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
- int x, i, msize = 0;
- long mstart = 0;
- char pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE], tbuf[ED_PAGE_SIZE];
-
- for (i = 0; i < ED_PAGE_SIZE; i++)
- pbuf0[i] = 0;
-
- /* Clear all the memory. */
- for (x = 1; x < 256; x++)
- ed_pio_writemem(sc, pbuf0, x * 256, ED_PAGE_SIZE);
-
- /* Search for the start of RAM. */
- for (x = 1; x < 256; x++) {
- ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
- if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
- for (i = 0; i < ED_PAGE_SIZE; i++)
- pbuf[i] = 255 - x;
- ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
- ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
- if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) {
- mstart = x * ED_PAGE_SIZE;
- msize = ED_PAGE_SIZE;
- break;
- }
- }
- }
-
- if (mstart == 0) {
- device_printf(dev, "Cannot find start of RAM.\n");
- return (ENXIO);
- }
- /* Search for the start of RAM. */
- for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) {
- ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
- if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
- for (i = 0; i < ED_PAGE_SIZE; i++)
- pbuf[i] = 255 - x;
- ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
- ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
- if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0)
- msize += ED_PAGE_SIZE;
- else {
- break;
- }
- } else {
- break;
- }
- }
-
- if (msize == 0) {
- device_printf(dev, "Cannot find any RAM, start : %ld, x = %d.\n", mstart, x);
- return (ENXIO);
- }
- device_printf(dev, "RAM start at %ld, size : %d.\n", mstart, msize);
-
- sc->mem_size = msize;
- sc->mem_start = (caddr_t)(uintptr_t) mstart;
- sc->mem_end = (caddr_t)(uintptr_t) (msize + mstart);
- sc->tx_page_start = mstart / ED_PAGE_SIZE;
- }
-
- /*
- * Use one xmit buffer if < 16k, two buffers otherwise (if not told
- * otherwise).
- */
- if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
- sc->txb_cnt = 1;
- else
- sc->txb_cnt = 2;
-
- sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
- sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
-
- sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
-
- ed_pio_readmem(sc, 0, romdata, 16);
- for (n = 0; n < ETHER_ADDR_LEN; n++)
- sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)];
-
- if ((ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) &&
- (sc->arpcom.ac_enaddr[2] == 0x86)) {
- sc->type_str = "Gateway AT";
- }
-
- /* clear any pending interrupts that might have occurred above */
- ed_nic_outb(sc, ED_P0_ISR, 0xff);
-
- return (0);
-}
-
-int
-ed_probe_Novell(device_t dev, int port_rid, int flags)
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
-
- error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS);
- if (error)
- return (error);
-
- sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
- sc->nic_offset = ED_NOVELL_NIC_OFFSET;
-
- return ed_probe_Novell_generic(dev, flags);
-}
-
-#define ED_HPP_TEST_SIZE 16
-
-/*
- * Probe and vendor specific initialization for the HP PC Lan+ Cards.
- * (HP Part nos: 27247B and 27252A).
- *
- * The card has an asic wrapper around a DS8390 core. The asic handles
- * host accesses and offers both standard register IO and memory mapped
- * IO. Memory mapped I/O allows better performance at the expense of greater
- * chance of an incompatibility with existing ISA cards.
- *
- * The card has a few caveats: it isn't tolerant of byte wide accesses, only
- * short (16 bit) or word (32 bit) accesses are allowed. Some card revisions
- * don't allow 32 bit accesses; these are indicated by a bit in the software
- * ID register (see if_edreg.h).
- *
- * Other caveats are: we should read the MAC address only when the card
- * is inactive.
- *
- * For more information; please consult the CRYNWR packet driver.
- *
- * The AUI port is turned on using the "link2" option on the ifconfig
- * command line.
- */
-int
-ed_probe_HP_pclanp(device_t dev, int port_rid, int flags)
-{
- struct ed_softc *sc = device_get_softc(dev);
- int error;
- int n; /* temp var */
- int memsize; /* mem on board */
- u_char checksum; /* checksum of board address */
- u_char irq; /* board configured IRQ */
- uint8_t test_pattern[ED_HPP_TEST_SIZE]; /* read/write areas for */
- uint8_t 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_offset = ED_HPP_ASIC_OFFSET;
- sc->nic_offset = ED_HPP_NIC_OFFSET;
-
- sc->chip_type = ED_CHIP_TYPE_DP8390;
- sc->isa16bit = 0; /* the 8390 core needs to be in byte mode */
-
- /*
- * Look for the HP PCLAN+ signature: "0x50,0x48,0x00,0x53"
- */
-
- if ((ed_asic_inb(sc, ED_HPP_ID) != 0x50) ||
- (ed_asic_inb(sc, ED_HPP_ID + 1) != 0x48) ||
- ((ed_asic_inb(sc, ED_HPP_ID + 2) & 0xF0) != 0) ||
- (ed_asic_inb(sc, ED_HPP_ID + 3) != 0x53))
- return ENXIO;
-
- /*
- * Read the MAC address and verify checksum on the address.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_MAC);
- for (n = 0, checksum = 0; n < ETHER_ADDR_LEN; n++)
- checksum += (sc->arpcom.ac_enaddr[n] =
- ed_asic_inb(sc, ED_HPP_MAC_ADDR + n));
-
- checksum += ed_asic_inb(sc, ED_HPP_MAC_ADDR + ETHER_ADDR_LEN);
-
- if (checksum != 0xFF)
- return ENXIO;
-
- /*
- * Verify that the software model number is 0.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_ID);
- if (((sc->hpp_id = ed_asic_inw(sc, ED_HPP_PAGE_4)) &
- ED_HPP_ID_SOFT_MODEL_MASK) != 0x0000)
- return ENXIO;
-
- /*
- * Read in and save the current options configured on card.
- */
-
- sc->hpp_options = ed_asic_inw(sc, ED_HPP_OPTION);
-
- sc->hpp_options |= (ED_HPP_OPTION_NIC_RESET |
- ED_HPP_OPTION_CHIP_RESET |
- ED_HPP_OPTION_ENABLE_IRQ);
-
- /*
- * Reset the chip. This requires writing to the option register
- * so take care to preserve the other bits.
- */
-
- ed_asic_outw(sc, ED_HPP_OPTION,
- (sc->hpp_options & ~(ED_HPP_OPTION_NIC_RESET |
- ED_HPP_OPTION_CHIP_RESET)));
-
- DELAY(5000); /* wait for chip reset to complete */
-
- ed_asic_outw(sc, ED_HPP_OPTION,
- (sc->hpp_options | (ED_HPP_OPTION_NIC_RESET |
- ED_HPP_OPTION_CHIP_RESET |
- ED_HPP_OPTION_ENABLE_IRQ)));
-
- DELAY(5000);
-
- if (!(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST))
- return ENXIO; /* reset did not complete */
-
- /*
- * Read out configuration information.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
-
- irq = ed_asic_inb(sc, ED_HPP_HW_IRQ);
-
- /*
- * Check for impossible IRQ.
- */
-
- if (irq >= (sizeof(ed_hpp_intr_val) / sizeof(ed_hpp_intr_val[0])))
- return ENXIO;
-
- /*
- * 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 = bus_get_resource(dev, SYS_RES_IRQ, 0,
- &conf_irq, &junk);
- if (error) {
- bus_set_resource(dev, SYS_RES_IRQ, 0,
- ed_hpp_intr_val[irq], 1);
- } else {
- if (conf_irq != ed_hpp_intr_val[irq])
- return (ENXIO);
- }
-
- /*
- * Fill in softconfig info.
- */
-
- sc->vendor = ED_VENDOR_HP;
- sc->type = ED_TYPE_HP_PCLANPLUS;
- sc->type_str = "HP-PCLAN+";
-
- sc->mem_shared = 0; /* we DON'T have dual ported RAM */
- sc->mem_start = 0; /* we use offsets inside the card RAM */
-
- 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.
- */
-
- if (sc->hpp_options & ED_HPP_OPTION_MEM_ENABLE)
- {
- u_long mem_addr;
-
- /*
- * determine the memory address from the board.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
- mem_addr = (ed_asic_inw(sc, ED_HPP_HW_MEM_MAP) << 8);
-
- /*
- * Check that the kernel specified start of memory and
- * hardware's idea of it match.
- */
- error = bus_get_resource(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);
-
- sc->hpp_mem_start = rman_get_virtual(sc->mem_res);
- }
-
- /*
- * Fill in the rest of the soft config structure.
- */
-
- /*
- * The transmit page index.
- */
-
- sc->tx_page_start = ED_HPP_TX_PAGE_OFFSET;
-
- if (device_get_flags(dev) & ED_FLAGS_NO_MULTI_BUFFERING)
- sc->txb_cnt = 1;
- else
- sc->txb_cnt = 2;
-
- /*
- * Memory description
- */
-
- sc->mem_size = memsize;
- sc->mem_ring = sc->mem_start +
- (sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE);
- sc->mem_end = sc->mem_start + sc->mem_size;
-
- /*
- * Receive area starts after the transmit area and
- * continues till the end of memory.
- */
-
- sc->rec_page_start = sc->tx_page_start +
- (sc->txb_cnt * ED_TXBUF_SIZE);
- sc->rec_page_stop = (sc->mem_size / ED_PAGE_SIZE);
-
-
- sc->cr_proto = 0; /* value works */
-
- /*
- * Set the wrap registers for string I/O reads.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
- ed_asic_outw(sc, ED_HPP_HW_WRAP,
- ((sc->rec_page_start / ED_PAGE_SIZE) |
- (((sc->rec_page_stop / ED_PAGE_SIZE) - 1) << 8)));
-
- /*
- * Reset the register page to normal operation.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_PERF);
-
- /*
- * Verify that we can read/write from adapter memory.
- * Create test pattern.
- */
-
- for (n = 0; n < ED_HPP_TEST_SIZE; n++)
- {
- test_pattern[n] = (n*n) ^ ~n;
- }
-
-#undef ED_HPP_TEST_SIZE
-
- /*
- * Check that the memory is accessible thru the I/O ports.
- * Write out the contents of "test_pattern", read back
- * into "test_buffer" and compare the two for any
- * mismatch.
- */
-
- for (n = 0; n < (32768 / ED_PAGE_SIZE); n ++) {
-
- ed_hpp_writemem(sc, test_pattern, (n * ED_PAGE_SIZE),
- sizeof(test_pattern));
- ed_hpp_readmem(sc, (n * ED_PAGE_SIZE),
- test_buffer, sizeof(test_pattern));
-
- if (bcmp(test_pattern, test_buffer,
- sizeof(test_pattern)))
- return ENXIO;
- }
-
- return (0);
-
-}
-
-/*
- * HP PC Lan+ : Set the physical link to use AUI or TP/TL.
- */
-
-static void
-ed_hpp_set_physical_link(struct ed_softc *sc)
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int lan_page;
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
- lan_page = ed_asic_inw(sc, ED_HPP_PAGE_0);
-
- if (ifp->if_flags & IFF_ALTPHYS) {
-
- /*
- * Use the AUI port.
- */
-
- lan_page |= ED_HPP_LAN_AUI;
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
- ed_asic_outw(sc, ED_HPP_PAGE_0, lan_page);
-
-
- } else {
-
- /*
- * Use the ThinLan interface
- */
-
- lan_page &= ~ED_HPP_LAN_AUI;
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
- ed_asic_outw(sc, ED_HPP_PAGE_0, lan_page);
-
- }
-
- /*
- * Wait for the lan card to re-initialize itself
- */
-
- DELAY(150000); /* wait 150 ms */
-
- /*
- * Restore normal pages.
- */
-
- ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_PERF);
-
-}
-
-/*
* Allocate a port resource with the given resource id.
*/
int
@@ -1579,7 +139,7 @@ ed_alloc_port(device_t dev, int rid, int size)
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- 0ul, ~0ul, size, RF_ACTIVE);
+ 0ul, ~0ul, size, RF_ACTIVE);
if (res) {
sc->port_rid = rid;
sc->port_res = res;
@@ -1600,7 +160,7 @@ ed_alloc_memory(device_t dev, int rid, int size)
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
- 0ul, ~0ul, size, RF_ACTIVE);
+ 0ul, ~0ul, size, RF_ACTIVE);
if (res) {
sc->mem_rid = rid;
sc->mem_res = res;
@@ -1620,8 +180,7 @@ ed_alloc_irq(device_t dev, int rid, int flags)
struct ed_softc *sc = device_get_softc(dev);
struct resource *res;
- res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- (RF_ACTIVE | flags));
+ res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | flags);
if (res) {
sc->irq_rid = rid;
sc->irq_res = res;
@@ -1728,12 +287,14 @@ ed_attach(device_t dev)
else
device_printf(dev, "type unknown (0x%x) ", sc->type);
+#ifdef ED_HPP
if (sc->vendor == ED_VENDOR_HP)
printf("(%s %s IO)",
(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS) ?
"16-bit" : "32-bit",
sc->hpp_mem_start ? "memory mapped" : "regular");
else
+#endif
printf("%s ", sc->isa16bit ? "(16 bit)" : "(8 bit)");
printf("%s\n", (((sc->vendor == ED_VENDOR_3COM) ||
@@ -2672,8 +1233,11 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
} else {
ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
}
- } else if (sc->vendor == ED_VENDOR_HP)
+ }
+#ifdef ED_HPP
+ else if (sc->vendor == ED_VENDOR_HP)
ed_hpp_set_physical_link(sc);
+#endif
break;
case SIOCADDMULTI:
@@ -2803,11 +1367,13 @@ ed_get_packet(struct ed_softc *sc, char *buf, u_short len)
void
ed_pio_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
{
+#ifdef ED_HPP
/* HP PC Lan+ cards need special handling */
if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) {
ed_hpp_readmem(sc, src, dst, amount);
return;
}
+#endif
/* Regular Novell cards */
/* select page 0 registers */
@@ -2889,10 +1455,11 @@ ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, long dst)
struct mbuf *mp;
int maxwait = 200; /* about 240us */
+#ifdef ED_HPP
/* HP PC Lan+ cards need special handling */
- if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) {
+ if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS)
return ed_hpp_write_mbufs(sc, m, dst);
- }
+#endif
/* Regular Novell cards */
/* First, count up the total number of bytes to copy */
@@ -2995,279 +1562,6 @@ ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, long dst)
return (total_len);
}
-/*
- * Support routines to handle the HP PC Lan+ card.
- */
-
-/*
- * HP PC Lan+: Read from NIC memory, using either PIO or memory mapped
- * IO.
- */
-
-static void
-ed_hpp_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
-{
-
- int use_32bit_access = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS);
-
-
- /* Program the source address in RAM */
- ed_asic_outw(sc, ED_HPP_PAGE_2, src);
-
- /*
- * The HP PC Lan+ card supports word reads as well as
- * a memory mapped i/o port that is aliased to every
- * even address on the board.
- */
-
- if (sc->hpp_mem_start) {
-
- /* Enable memory mapped access. */
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
- ~(ED_HPP_OPTION_MEM_DISABLE |
- ED_HPP_OPTION_BOOT_ROM_ENB));
-
- if (use_32bit_access && (amount > 3)) {
- uint32_t *dl = (uint32_t *) dst;
- volatile uint32_t *const sl =
- (uint32_t *) sc->hpp_mem_start;
- uint32_t *const fence = dl + (amount >> 2);
-
- /* Copy out NIC data. We could probably write this
- as a `movsl'. The currently generated code is lousy.
- */
-
- while (dl < fence)
- *dl++ = *sl;
-
- dst += (amount & ~3);
- amount &= 3;
-
- }
-
- /* Finish off any words left, as a series of short reads */
- if (amount > 1) {
- u_short *d = (u_short *) dst;
- volatile u_short *const s =
- (u_short *) sc->hpp_mem_start;
- u_short *const fence = d + (amount >> 1);
-
- /* Copy out NIC data. */
-
- while (d < fence)
- *d++ = *s;
-
- dst += (amount & ~1);
- amount &= 1;
- }
-
- /*
- * read in a byte; however we need to always read 16 bits
- * at a time or the hardware gets into a funny state
- */
-
- if (amount == 1) {
- /* need to read in a short and copy LSB */
- volatile u_short *const s =
- (volatile u_short *) sc->hpp_mem_start;
-
- *dst = (*s) & 0xFF;
- }
-
- /* Restore Boot ROM access. */
-
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
-
-
- } else {
- /* Read in data using the I/O port */
- if (use_32bit_access && (amount > 3)) {
- ed_asic_insl(sc, ED_HPP_PAGE_4, dst, amount >> 2);
- dst += (amount & ~3);
- amount &= 3;
- }
- if (amount > 1) {
- ed_asic_insw(sc, ED_HPP_PAGE_4, dst, amount >> 1);
- dst += (amount & ~1);
- amount &= 1;
- }
- if (amount == 1) { /* read in a short and keep the LSB */
- *dst = ed_asic_inw(sc, ED_HPP_PAGE_4) & 0xFF;
- }
- }
-}
-
-/*
- * HP PC Lan+: Write to NIC memory, using either PIO or memory mapped
- * IO.
- * Only used in the probe routine to test the memory. 'len' must
- * be even.
- */
-static void
-ed_hpp_writemem(struct ed_softc *sc, uint8_t *src, uint16_t dst, uint16_t len)
-{
- /* reset remote DMA complete flag */
- ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);
-
- /* program the write address in RAM */
- ed_asic_outw(sc, ED_HPP_PAGE_0, dst);
-
- if (sc->hpp_mem_start) {
- u_short *s = (u_short *) src;
- volatile u_short *d = (u_short *) sc->hpp_mem_start;
- u_short *const fence = s + (len >> 1);
-
- /*
- * Enable memory mapped access.
- */
-
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
- ~(ED_HPP_OPTION_MEM_DISABLE |
- ED_HPP_OPTION_BOOT_ROM_ENB));
-
- /*
- * Copy to NIC memory.
- */
-
- while (s < fence)
- *d = *s++;
-
- /*
- * Restore Boot ROM access.
- */
-
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
-
- } else {
- /* write data using I/O writes */
- ed_asic_outsw(sc, ED_HPP_PAGE_4, src, len / 2);
- }
-}
-
-/*
- * Write to HP PC Lan+ NIC memory. Access to the NIC can be by using
- * outsw() or via the memory mapped interface to the same register.
- * Writes have to be in word units; byte accesses won't work and may cause
- * the NIC to behave weirdly. Long word accesses are permitted if the ASIC
- * allows it.
- */
-
-static u_short
-ed_hpp_write_mbufs(struct ed_softc *sc, struct mbuf *m, int dst)
-{
- int len, wantbyte;
- unsigned short total_len;
- unsigned char savebyte[2];
- volatile u_short * const d =
- (volatile u_short *) sc->hpp_mem_start;
- int use_32bit_accesses = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS);
-
- /* select page 0 registers */
- ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
-
- /* reset remote DMA complete flag */
- ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);
-
- /* program the write address in RAM */
- ed_asic_outw(sc, ED_HPP_PAGE_0, dst);
-
- if (sc->hpp_mem_start) /* enable memory mapped I/O */
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
- ~(ED_HPP_OPTION_MEM_DISABLE |
- ED_HPP_OPTION_BOOT_ROM_ENB));
-
- wantbyte = 0;
- total_len = 0;
-
- if (sc->hpp_mem_start) { /* Memory mapped I/O port */
- while (m) {
- total_len += (len = m->m_len);
- if (len) {
- caddr_t data = mtod(m, caddr_t);
- /* finish the last word of the previous mbuf */
- if (wantbyte) {
- savebyte[1] = *data;
- *d = *((u_short *) savebyte);
- data++; len--; wantbyte = 0;
- }
- /* output contiguous words */
- if ((len > 3) && (use_32bit_accesses)) {
- volatile uint32_t *const dl =
- (volatile uint32_t *) d;
- uint32_t *sl = (uint32_t *) data;
- uint32_t *fence = sl + (len >> 2);
-
- while (sl < fence)
- *dl = *sl++;
-
- data += (len & ~3);
- len &= 3;
- }
- /* finish off remain 16 bit writes */
- if (len > 1) {
- u_short *s = (u_short *) data;
- u_short *fence = s + (len >> 1);
-
- while (s < fence)
- *d = *s++;
-
- data += (len & ~1);
- len &= 1;
- }
- /* save last byte if needed */
- if ((wantbyte = (len == 1)) != 0)
- savebyte[0] = *data;
- }
- m = m->m_next; /* to next mbuf */
- }
- if (wantbyte) /* write last byte */
- *d = *((u_short *) savebyte);
- } else {
- /* use programmed I/O */
- while (m) {
- total_len += (len = m->m_len);
- if (len) {
- caddr_t data = mtod(m, caddr_t);
- /* finish the last word of the previous mbuf */
- if (wantbyte) {
- savebyte[1] = *data;
- ed_asic_outw(sc, ED_HPP_PAGE_4,
- *((u_short *)savebyte));
- data++;
- len--;
- wantbyte = 0;
- }
- /* output contiguous words */
- if ((len > 3) && use_32bit_accesses) {
- ed_asic_outsl(sc, ED_HPP_PAGE_4,
- data, len >> 2);
- data += (len & ~3);
- len &= 3;
- }
- /* finish off remaining 16 bit accesses */
- if (len > 1) {
- ed_asic_outsw(sc, ED_HPP_PAGE_4,
- data, len >> 1);
- data += (len & ~1);
- len &= 1;
- }
- if ((wantbyte = (len == 1)) != 0)
- savebyte[0] = *data;
-
- } /* if len != 0 */
- m = m->m_next;
- }
- if (wantbyte) /* spit last byte */
- ed_asic_outw(sc, ED_HPP_PAGE_4, *(u_short *)savebyte);
-
- }
-
- if (sc->hpp_mem_start) /* turn off memory mapped i/o */
- ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
-
- return (total_len);
-}
-
#ifndef ED_NO_MIIBUS
/*
* MII bus support routines.
@@ -3465,6 +1759,17 @@ ed_ds_getmcaf(struct ed_softc *sc, uint32_t *mcaf)
}
int
+ed_isa_mem_ok(device_t dev, u_long pmem, u_int memsize)
+{
+ if (pmem < 0xa0000 || pmem + memsize > 0x1000000) {
+ device_printf(dev, "Invalid ISA memory address range "
+ "configured: 0x%lx - 0x%lx\n", pmem, pmem + memsize);
+ return (ENXIO);
+ }
+ return (0);
+}
+
+int
ed_clear_memory(device_t dev)
{
struct ed_softc *sc = device_get_softc(dev);
diff --git a/sys/dev/ed/if_ed_3c503.c b/sys/dev/ed/if_ed_3c503.c
new file mode 100644
index 0000000..b46e107
--- /dev/null
+++ b/sys/dev/ed/if_ed_3c503.c
@@ -0,0 +1,341 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ed.h"
+
+#ifdef ED_3C503
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_edvar.h>
+
+/*
+ * Probe and vendor-specific initialization routine for 3Com 3c503 boards
+ */
+int
+ed_probe_3Com(device_t dev, int port_rid, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int i;
+ u_int memsize;
+ u_char isa16bit;
+ u_long conf_maddr, conf_msize, irq, junk, pmem;
+
+ error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
+ if (error)
+ return (error);
+
+ sc->asic_offset = ED_3COM_ASIC_OFFSET;
+ sc->nic_offset = ED_3COM_NIC_OFFSET;
+
+ /*
+ * Verify that the kernel configured I/O address matches the board
+ * configured address
+ */
+ switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
+ case ED_3COM_BCFR_300:
+ if (rman_get_start(sc->port_res) != 0x300)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_310:
+ if (rman_get_start(sc->port_res) != 0x310)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_330:
+ if (rman_get_start(sc->port_res) != 0x330)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_350:
+ if (rman_get_start(sc->port_res) != 0x350)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_250:
+ if (rman_get_start(sc->port_res) != 0x250)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_280:
+ if (rman_get_start(sc->port_res) != 0x280)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_2A0:
+ if (rman_get_start(sc->port_res) != 0x2a0)
+ return (ENXIO);
+ break;
+ case ED_3COM_BCFR_2E0:
+ if (rman_get_start(sc->port_res) != 0x2e0)
+ return (ENXIO);
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ error = bus_get_resource(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 (ed_asic_inb(sc, ED_3COM_PCFR)) {
+ case ED_3COM_PCFR_DC000:
+ if (conf_maddr != 0xdc000)
+ return (ENXIO);
+ break;
+ case ED_3COM_PCFR_D8000:
+ if (conf_maddr != 0xd8000)
+ return (ENXIO);
+ break;
+ case ED_3COM_PCFR_CC000:
+ if (conf_maddr != 0xcc000)
+ return (ENXIO);
+ break;
+ case ED_3COM_PCFR_C8000:
+ if (conf_maddr != 0xc8000)
+ return (ENXIO);
+ break;
+ default:
+ return (ENXIO);
+ }
+
+
+ /*
+ * Reset NIC and ASIC. Enable on-board transceiver throughout reset
+ * sequence because it'll lock up if the cable isn't connected if we
+ * don't.
+ */
+ ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
+
+ /*
+ * Wait for a while, then un-reset it
+ */
+ DELAY(50);
+
+ /*
+ * The 3Com ASIC defaults to rather strange settings for the CR after
+ * a reset - it's important to set it again after the following outb
+ * (this is done when we map the PROM below).
+ */
+ ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
+
+ /*
+ * Wait a bit for the NIC to recover from the reset
+ */
+ DELAY(5000);
+
+ sc->vendor = ED_VENDOR_3COM;
+ sc->type_str = "3c503";
+ sc->mem_shared = 1;
+ sc->cr_proto = ED_CR_RD2;
+
+ /*
+ * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
+ * to it.
+ */
+ memsize = 8192;
+
+ /*
+ * Get station address from on-board ROM
+ */
+
+ /*
+ * First, map ethernet address PROM over the top of where the NIC
+ * registers normally appear.
+ */
+ ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
+
+ for (i = 0; i < ETHER_ADDR_LEN; ++i)
+ sc->arpcom.ac_enaddr[i] = ed_nic_inb(sc, i);
+
+ /*
+ * Unmap PROM - select NIC registers. The proper setting of the
+ * tranceiver is set in ed_init so that the attach code is given a
+ * chance to set the default based on a compile-time config option
+ */
+ ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
+
+ /*
+ * Determine if this is an 8bit or 16bit board
+ */
+
+ /*
+ * select page 0 registers
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+
+ /*
+ * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
+ * board.
+ */
+ ed_nic_outb(sc, ED_P0_DCR, 0);
+
+ /*
+ * select page 2 registers
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);
+
+ /*
+ * The 3c503 forces the WTS bit to a one if this is a 16bit board
+ */
+ if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
+ isa16bit = 1;
+ else
+ isa16bit = 0;
+
+ /*
+ * select page 0 registers
+ */
+ ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);
+
+ error = ed_alloc_memory(dev, 0, memsize);
+ if (error)
+ return (error);
+
+ pmem = rman_get_start(sc->mem_res);
+ error = ed_isa_mem_ok(dev, pmem, memsize);
+ if (error)
+ return (error);
+
+ sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_size = memsize;
+ sc->mem_end = sc->mem_start + memsize;
+
+ /*
+ * We have an entire 8k window to put the transmit buffers on the
+ * 16bit boards. But since the 16bit 3c503's shared memory is only
+ * fast enough to overlap the loading of one full-size packet, trying
+ * to load more than 2 buffers can actually leave the transmitter idle
+ * during the load. So 2 seems the best value. (Although a mix of
+ * variable-sized packets might change this assumption. Nonetheless,
+ * we optimize for linear transfers of same-size packets.)
+ */
+ if (isa16bit) {
+ if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
+ sc->txb_cnt = 1;
+ else
+ sc->txb_cnt = 2;
+
+ sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
+ sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
+ sc->rec_page_stop = memsize / ED_PAGE_SIZE +
+ ED_3COM_RX_PAGE_OFFSET_16BIT;
+ sc->mem_ring = sc->mem_start;
+ } else {
+ sc->txb_cnt = 1;
+ sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
+ sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
+ sc->rec_page_stop = memsize / ED_PAGE_SIZE +
+ ED_3COM_TX_PAGE_OFFSET_8BIT;
+ sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
+ }
+
+ sc->isa16bit = isa16bit;
+
+ /*
+ * Initialize GA page start/stop registers. Probably only needed if
+ * doing DMA, but what the hell.
+ */
+ ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
+ ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
+
+ /*
+ * Set IRQ. 3c503 only allows a choice of irq 2-5.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
+ if (error)
+ return (error);
+
+ switch (irq) {
+ case 2:
+ case 9:
+ ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
+ break;
+ case 3:
+ ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
+ break;
+ case 4:
+ ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
+ break;
+ case 5:
+ ed_asic_outb(sc, 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);
+ }
+
+ /*
+ * Initialize GA configuration register. Set bank and enable shared
+ * mem.
+ */
+ ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
+ ED_3COM_GACFR_MBS0);
+
+ /*
+ * Initialize "Vector Pointer" registers. These gawd-awful things are
+ * compared to 20 bits of the address on ISA, and if they match, the
+ * shared memory is disabled. We set them to 0xffff0...allegedly the
+ * reset vector.
+ */
+ ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
+ ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
+ ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);
+
+ return (ed_clear_memory(dev));
+}
+
+#endif /* ED_3C503 */
diff --git a/sys/dev/ed/if_ed_hpp.c b/sys/dev/ed/if_ed_hpp.c
new file mode 100644
index 0000000..c993cc1
--- /dev/null
+++ b/sys/dev/ed/if_ed_hpp.c
@@ -0,0 +1,663 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ed.h"
+
+#ifdef ED_HPP
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_edvar.h>
+
+static void ed_hpp_writemem(struct ed_softc *, uint8_t *, uint16_t,
+ uint16_t);
+
+/*
+ * Interrupt conversion table for the HP PC LAN+
+ */
+static uint16_t ed_hpp_intr_val[] = {
+ 0, /* 0 */
+ 0, /* 1 */
+ 0, /* 2 */
+ 3, /* 3 */
+ 4, /* 4 */
+ 5, /* 5 */
+ 6, /* 6 */
+ 7, /* 7 */
+ 0, /* 8 */
+ 9, /* 9 */
+ 10, /* 10 */
+ 11, /* 11 */
+ 12, /* 12 */
+ 0, /* 13 */
+ 0, /* 14 */
+ 15 /* 15 */
+};
+
+#define ED_HPP_TEST_SIZE 16
+
+/*
+ * Probe and vendor specific initialization for the HP PC Lan+ Cards.
+ * (HP Part nos: 27247B and 27252A).
+ *
+ * The card has an asic wrapper around a DS8390 core. The asic handles
+ * host accesses and offers both standard register IO and memory mapped
+ * IO. Memory mapped I/O allows better performance at the expense of greater
+ * chance of an incompatibility with existing ISA cards.
+ *
+ * The card has a few caveats: it isn't tolerant of byte wide accesses, only
+ * short (16 bit) or word (32 bit) accesses are allowed. Some card revisions
+ * don't allow 32 bit accesses; these are indicated by a bit in the software
+ * ID register (see if_edreg.h).
+ *
+ * Other caveats are: we should read the MAC address only when the card
+ * is inactive.
+ *
+ * For more information; please consult the CRYNWR packet driver.
+ *
+ * The AUI port is turned on using the "link2" option on the ifconfig
+ * command line.
+ */
+int
+ed_probe_HP_pclanp(device_t dev, int port_rid, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int n; /* temp var */
+ int memsize; /* mem on board */
+ u_char checksum; /* checksum of board address */
+ u_char irq; /* board configured IRQ */
+ uint8_t test_pattern[ED_HPP_TEST_SIZE]; /* read/write areas for */
+ uint8_t 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_offset = ED_HPP_ASIC_OFFSET;
+ sc->nic_offset = ED_HPP_NIC_OFFSET;
+
+ sc->chip_type = ED_CHIP_TYPE_DP8390;
+ sc->isa16bit = 0; /* the 8390 core needs to be in byte mode */
+
+ /*
+ * Look for the HP PCLAN+ signature: "0x50,0x48,0x00,0x53"
+ */
+
+ if ((ed_asic_inb(sc, ED_HPP_ID) != 0x50) ||
+ (ed_asic_inb(sc, ED_HPP_ID + 1) != 0x48) ||
+ ((ed_asic_inb(sc, ED_HPP_ID + 2) & 0xF0) != 0) ||
+ (ed_asic_inb(sc, ED_HPP_ID + 3) != 0x53))
+ return ENXIO;
+
+ /*
+ * Read the MAC address and verify checksum on the address.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_MAC);
+ for (n = 0, checksum = 0; n < ETHER_ADDR_LEN; n++)
+ checksum += (sc->arpcom.ac_enaddr[n] =
+ ed_asic_inb(sc, ED_HPP_MAC_ADDR + n));
+
+ checksum += ed_asic_inb(sc, ED_HPP_MAC_ADDR + ETHER_ADDR_LEN);
+
+ if (checksum != 0xFF)
+ return ENXIO;
+
+ /*
+ * Verify that the software model number is 0.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_ID);
+ if (((sc->hpp_id = ed_asic_inw(sc, ED_HPP_PAGE_4)) &
+ ED_HPP_ID_SOFT_MODEL_MASK) != 0x0000)
+ return ENXIO;
+
+ /*
+ * Read in and save the current options configured on card.
+ */
+
+ sc->hpp_options = ed_asic_inw(sc, ED_HPP_OPTION);
+
+ sc->hpp_options |= (ED_HPP_OPTION_NIC_RESET |
+ ED_HPP_OPTION_CHIP_RESET | ED_HPP_OPTION_ENABLE_IRQ);
+
+ /*
+ * Reset the chip. This requires writing to the option register
+ * so take care to preserve the other bits.
+ */
+
+ ed_asic_outw(sc, ED_HPP_OPTION,
+ (sc->hpp_options & ~(ED_HPP_OPTION_NIC_RESET |
+ ED_HPP_OPTION_CHIP_RESET)));
+
+ DELAY(5000); /* wait for chip reset to complete */
+
+ ed_asic_outw(sc, ED_HPP_OPTION,
+ (sc->hpp_options | (ED_HPP_OPTION_NIC_RESET |
+ ED_HPP_OPTION_CHIP_RESET |
+ ED_HPP_OPTION_ENABLE_IRQ)));
+
+ DELAY(5000);
+
+ if (!(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST))
+ return ENXIO; /* reset did not complete */
+
+ /*
+ * Read out configuration information.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
+
+ irq = ed_asic_inb(sc, ED_HPP_HW_IRQ);
+
+ /*
+ * Check for impossible IRQ.
+ */
+
+ if (irq >= (sizeof(ed_hpp_intr_val) / sizeof(ed_hpp_intr_val[0])))
+ return ENXIO;
+
+ /*
+ * 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 = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk);
+ if (error)
+ bus_set_resource(dev, SYS_RES_IRQ, 0, ed_hpp_intr_val[irq], 1);
+ else {
+ if (conf_irq != ed_hpp_intr_val[irq])
+ return (ENXIO);
+ }
+
+ /*
+ * Fill in softconfig info.
+ */
+
+ sc->vendor = ED_VENDOR_HP;
+ sc->type = ED_TYPE_HP_PCLANPLUS;
+ sc->type_str = "HP-PCLAN+";
+
+ sc->mem_shared = 0; /* we DON'T have dual ported RAM */
+ sc->mem_start = 0; /* we use offsets inside the card RAM */
+
+ 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.
+ */
+ if (sc->hpp_options & ED_HPP_OPTION_MEM_ENABLE) {
+ u_long mem_addr;
+
+ /*
+ * determine the memory address from the board.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
+ mem_addr = (ed_asic_inw(sc, ED_HPP_HW_MEM_MAP) << 8);
+
+ /*
+ * Check that the kernel specified start of memory and
+ * hardware's idea of it match.
+ */
+ error = bus_get_resource(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);
+
+ sc->hpp_mem_start = rman_get_virtual(sc->mem_res);
+ }
+
+ /*
+ * Fill in the rest of the soft config structure.
+ */
+
+ /*
+ * The transmit page index.
+ */
+
+ sc->tx_page_start = ED_HPP_TX_PAGE_OFFSET;
+
+ if (device_get_flags(dev) & ED_FLAGS_NO_MULTI_BUFFERING)
+ sc->txb_cnt = 1;
+ else
+ sc->txb_cnt = 2;
+
+ /*
+ * Memory description
+ */
+
+ sc->mem_size = memsize;
+ sc->mem_ring = sc->mem_start +
+ (sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE);
+ sc->mem_end = sc->mem_start + sc->mem_size;
+
+ /*
+ * Receive area starts after the transmit area and
+ * continues till the end of memory.
+ */
+
+ sc->rec_page_start = sc->tx_page_start +
+ (sc->txb_cnt * ED_TXBUF_SIZE);
+ sc->rec_page_stop = (sc->mem_size / ED_PAGE_SIZE);
+
+
+ sc->cr_proto = 0; /* value works */
+
+ /*
+ * Set the wrap registers for string I/O reads.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
+ ed_asic_outw(sc, ED_HPP_HW_WRAP,
+ ((sc->rec_page_start / ED_PAGE_SIZE) |
+ (((sc->rec_page_stop / ED_PAGE_SIZE) - 1) << 8)));
+
+ /*
+ * Reset the register page to normal operation.
+ */
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_PERF);
+
+ /*
+ * Verify that we can read/write from adapter memory.
+ * Create test pattern.
+ */
+
+ for (n = 0; n < ED_HPP_TEST_SIZE; n++)
+ test_pattern[n] = (n*n) ^ ~n;
+
+#undef ED_HPP_TEST_SIZE
+
+ /*
+ * Check that the memory is accessible thru the I/O ports.
+ * Write out the contents of "test_pattern", read back
+ * into "test_buffer" and compare the two for any
+ * mismatch.
+ */
+
+ for (n = 0; n < (32768 / ED_PAGE_SIZE); n ++) {
+ ed_hpp_writemem(sc, test_pattern, (n * ED_PAGE_SIZE),
+ sizeof(test_pattern));
+ ed_hpp_readmem(sc, (n * ED_PAGE_SIZE),
+ test_buffer, sizeof(test_pattern));
+
+ if (bcmp(test_pattern, test_buffer,
+ sizeof(test_pattern)))
+ return ENXIO;
+ }
+
+ return (0);
+}
+
+/*
+ * HP PC Lan+ : Set the physical link to use AUI or TP/TL.
+ */
+
+void
+ed_hpp_set_physical_link(struct ed_softc *sc)
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ int lan_page;
+
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
+ lan_page = ed_asic_inw(sc, ED_HPP_PAGE_0);
+
+ if (ifp->if_flags & IFF_ALTPHYS) {
+ /*
+ * Use the AUI port.
+ */
+
+ lan_page |= ED_HPP_LAN_AUI;
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
+ ed_asic_outw(sc, ED_HPP_PAGE_0, lan_page);
+ } else {
+ /*
+ * Use the ThinLan interface
+ */
+
+ lan_page &= ~ED_HPP_LAN_AUI;
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_LAN);
+ ed_asic_outw(sc, ED_HPP_PAGE_0, lan_page);
+ }
+
+ /*
+ * Wait for the lan card to re-initialize itself
+ */
+ DELAY(150000); /* wait 150 ms */
+
+ /*
+ * Restore normal pages.
+ */
+ ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_PERF);
+}
+
+/*
+ * Support routines to handle the HP PC Lan+ card.
+ */
+
+/*
+ * HP PC Lan+: Read from NIC memory, using either PIO or memory mapped
+ * IO.
+ */
+
+void
+ed_hpp_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
+{
+ int use_32bit_access = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS);
+
+ /* Program the source address in RAM */
+ ed_asic_outw(sc, ED_HPP_PAGE_2, src);
+
+ /*
+ * The HP PC Lan+ card supports word reads as well as
+ * a memory mapped i/o port that is aliased to every
+ * even address on the board.
+ */
+ if (sc->hpp_mem_start) {
+ /* Enable memory mapped access. */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
+ ~(ED_HPP_OPTION_MEM_DISABLE |
+ ED_HPP_OPTION_BOOT_ROM_ENB));
+
+ if (use_32bit_access && (amount > 3)) {
+ uint32_t *dl = (uint32_t *) dst;
+ volatile uint32_t *const sl =
+ (uint32_t *) sc->hpp_mem_start;
+ uint32_t *const fence = dl + (amount >> 2);
+
+ /* Copy out NIC data. We could probably write this
+ as a `movsl'. The currently generated code is lousy.
+ */
+
+ while (dl < fence)
+ *dl++ = *sl;
+
+ dst += (amount & ~3);
+ amount &= 3;
+
+ }
+
+ /* Finish off any words left, as a series of short reads */
+ if (amount > 1) {
+ u_short *d = (u_short *) dst;
+ volatile u_short *const s =
+ (u_short *) sc->hpp_mem_start;
+ u_short *const fence = d + (amount >> 1);
+
+ /* Copy out NIC data. */
+ while (d < fence)
+ *d++ = *s;
+
+ dst += (amount & ~1);
+ amount &= 1;
+ }
+
+ /*
+ * read in a byte; however we need to always read 16 bits
+ * at a time or the hardware gets into a funny state
+ */
+
+ if (amount == 1) {
+ /* need to read in a short and copy LSB */
+ volatile u_short *const s =
+ (volatile u_short *) sc->hpp_mem_start;
+ *dst = (*s) & 0xFF;
+ }
+
+ /* Restore Boot ROM access. */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
+ } else {
+ /* Read in data using the I/O port */
+ if (use_32bit_access && (amount > 3)) {
+ ed_asic_insl(sc, ED_HPP_PAGE_4, dst, amount >> 2);
+ dst += (amount & ~3);
+ amount &= 3;
+ }
+ if (amount > 1) {
+ ed_asic_insw(sc, ED_HPP_PAGE_4, dst, amount >> 1);
+ dst += (amount & ~1);
+ amount &= 1;
+ }
+ if (amount == 1) { /* read in a short and keep the LSB */
+ *dst = ed_asic_inw(sc, ED_HPP_PAGE_4) & 0xFF;
+ }
+ }
+}
+
+/*
+ * HP PC Lan+: Write to NIC memory, using either PIO or memory mapped
+ * IO.
+ * Only used in the probe routine to test the memory. 'len' must
+ * be even.
+ */
+static void
+ed_hpp_writemem(struct ed_softc *sc, uint8_t *src, uint16_t dst, uint16_t len)
+{
+ /* reset remote DMA complete flag */
+ ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);
+
+ /* program the write address in RAM */
+ ed_asic_outw(sc, ED_HPP_PAGE_0, dst);
+
+ if (sc->hpp_mem_start) {
+ u_short *s = (u_short *) src;
+ volatile u_short *d = (u_short *) sc->hpp_mem_start;
+ u_short *const fence = s + (len >> 1);
+
+ /*
+ * Enable memory mapped access.
+ */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
+ ~(ED_HPP_OPTION_MEM_DISABLE |
+ ED_HPP_OPTION_BOOT_ROM_ENB));
+
+ /*
+ * Copy to NIC memory.
+ */
+ while (s < fence)
+ *d = *s++;
+
+ /*
+ * Restore Boot ROM access.
+ */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
+ } else {
+ /* write data using I/O writes */
+ ed_asic_outsw(sc, ED_HPP_PAGE_4, src, len / 2);
+ }
+}
+
+/*
+ * Write to HP PC Lan+ NIC memory. Access to the NIC can be by using
+ * outsw() or via the memory mapped interface to the same register.
+ * Writes have to be in word units; byte accesses won't work and may cause
+ * the NIC to behave weirdly. Long word accesses are permitted if the ASIC
+ * allows it.
+ */
+
+u_short
+ed_hpp_write_mbufs(struct ed_softc *sc, struct mbuf *m, int dst)
+{
+ int len, wantbyte;
+ unsigned short total_len;
+ unsigned char savebyte[2];
+ volatile u_short * const d =
+ (volatile u_short *) sc->hpp_mem_start;
+ int use_32bit_accesses = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS);
+
+ /* select page 0 registers */
+ ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
+
+ /* reset remote DMA complete flag */
+ ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);
+
+ /* program the write address in RAM */
+ ed_asic_outw(sc, ED_HPP_PAGE_0, dst);
+
+ if (sc->hpp_mem_start) /* enable memory mapped I/O */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options &
+ ~(ED_HPP_OPTION_MEM_DISABLE |
+ ED_HPP_OPTION_BOOT_ROM_ENB));
+
+ wantbyte = 0;
+ total_len = 0;
+
+ if (sc->hpp_mem_start) { /* Memory mapped I/O port */
+ while (m) {
+ total_len += (len = m->m_len);
+ if (len) {
+ caddr_t data = mtod(m, caddr_t);
+ /* finish the last word of the previous mbuf */
+ if (wantbyte) {
+ savebyte[1] = *data;
+ *d = *((u_short *) savebyte);
+ data++; len--; wantbyte = 0;
+ }
+ /* output contiguous words */
+ if ((len > 3) && (use_32bit_accesses)) {
+ volatile uint32_t *const dl =
+ (volatile uint32_t *) d;
+ uint32_t *sl = (uint32_t *) data;
+ uint32_t *fence = sl + (len >> 2);
+
+ while (sl < fence)
+ *dl = *sl++;
+
+ data += (len & ~3);
+ len &= 3;
+ }
+ /* finish off remain 16 bit writes */
+ if (len > 1) {
+ u_short *s = (u_short *) data;
+ u_short *fence = s + (len >> 1);
+
+ while (s < fence)
+ *d = *s++;
+
+ data += (len & ~1);
+ len &= 1;
+ }
+ /* save last byte if needed */
+ if ((wantbyte = (len == 1)) != 0)
+ savebyte[0] = *data;
+ }
+ m = m->m_next; /* to next mbuf */
+ }
+ if (wantbyte) /* write last byte */
+ *d = *((u_short *) savebyte);
+ } else {
+ /* use programmed I/O */
+ while (m) {
+ total_len += (len = m->m_len);
+ if (len) {
+ caddr_t data = mtod(m, caddr_t);
+ /* finish the last word of the previous mbuf */
+ if (wantbyte) {
+ savebyte[1] = *data;
+ ed_asic_outw(sc, ED_HPP_PAGE_4,
+ *((u_short *)savebyte));
+ data++;
+ len--;
+ wantbyte = 0;
+ }
+ /* output contiguous words */
+ if ((len > 3) && use_32bit_accesses) {
+ ed_asic_outsl(sc, ED_HPP_PAGE_4,
+ data, len >> 2);
+ data += (len & ~3);
+ len &= 3;
+ }
+ /* finish off remaining 16 bit accesses */
+ if (len > 1) {
+ ed_asic_outsw(sc, ED_HPP_PAGE_4,
+ data, len >> 1);
+ data += (len & ~1);
+ len &= 1;
+ }
+ if ((wantbyte = (len == 1)) != 0)
+ savebyte[0] = *data;
+
+ } /* if len != 0 */
+ m = m->m_next;
+ }
+ if (wantbyte) /* spit last byte */
+ ed_asic_outw(sc, ED_HPP_PAGE_4, *(u_short *)savebyte);
+
+ }
+
+ if (sc->hpp_mem_start) /* turn off memory mapped i/o */
+ ed_asic_outw(sc, ED_HPP_OPTION, sc->hpp_options);
+
+ return (total_len);
+}
+
+#endif /* ED_HPP */
diff --git a/sys/dev/ed/if_ed_isa.c b/sys/dev/ed/if_ed_isa.c
index 2b963d1..742789c 100644
--- a/sys/dev/ed/if_ed_isa.c
+++ b/sys/dev/ed/if_ed_isa.c
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ed.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
@@ -89,26 +91,30 @@ ed_isa_probe(dev)
goto end;
ed_release_resources(dev);
+#ifdef ED_3C503
error = ed_probe_3Com(dev, 0, flags);
if (error == 0)
goto end;
ed_release_resources(dev);
+#endif
+#ifdef ED_SIC
error = ed_probe_SIC(dev, 0, flags);
if (error == 0)
goto end;
ed_release_resources(dev);
-
+#endif
error = ed_probe_Novell(dev, 0, flags);
if (error == 0)
goto end;
ed_release_resources(dev);
+#ifdef ED_HPP
error = ed_probe_HP_pclanp(dev, 0, flags);
if (error == 0)
goto end;
ed_release_resources(dev);
-
+#endif
end:
if (error == 0)
error = ed_alloc_irq(dev, 0, 0);
diff --git a/sys/dev/ed/if_ed_novell.c b/sys/dev/ed/if_ed_novell.c
new file mode 100644
index 0000000..235dee6
--- /dev/null
+++ b/sys/dev/ed/if_ed_novell.c
@@ -0,0 +1,288 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ed.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_edvar.h>
+
+/*
+ * Probe and vendor-specific initialization routine for NE1000/2000 boards
+ */
+int
+ed_probe_Novell_generic(device_t dev, 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];
+
+ /* XXX - do Novell-specific probe here */
+
+ /* Reset the board */
+ if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
+ ed_asic_outb(sc, ED_NOVELL_RESET, 0);
+ DELAY(200);
+ }
+ tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
+
+ /*
+ * I don't know if this is necessary; probably cruft leftover from
+ * Clarkson packet driver code. Doesn't do a thing on the boards I've
+ * tested. -DG [note that an outb(0x84, 0) seems to work here, and is
+ * non-invasive...but some boards don't seem to reset and I don't have
+ * complete documentation on what the 'right' thing to do is...so we
+ * do the invasive thing for now. Yuck.]
+ */
+ ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
+ DELAY(5000);
+
+ /*
+ * This is needed because some NE clones apparently don't reset the
+ * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ * - this makes the probe invasive! ...Done against my better
+ * judgement. -DLG
+ */
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+
+ DELAY(5000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed_probe_generic8390(sc))
+ return (ENXIO);
+
+ sc->vendor = ED_VENDOR_NOVELL;
+ sc->mem_shared = 0;
+ sc->cr_proto = ED_CR_RD2;
+
+ /*
+ * Test the ability to read and write to the NIC memory. This has the
+ * side affect of determining if this is an NE1000 or an NE2000.
+ */
+
+ /*
+ * This prevents packets from being stored in the NIC memory when the
+ * readmem routine turns on the start bit in the CR.
+ */
+ ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
+
+ /* Temporarily initialize DCR for byte operations */
+ ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+
+ ed_nic_outb(sc, ED_P0_PSTART, 8192 / ED_PAGE_SIZE);
+ ed_nic_outb(sc, ED_P0_PSTOP, 16384 / ED_PAGE_SIZE);
+
+ sc->isa16bit = 0;
+
+ /*
+ * Write a test pattern in byte mode. If this fails, then there
+ * probably isn't any memory at 8k - which likely means that the board
+ * is an NE2000.
+ */
+ ed_pio_writemem(sc, test_pattern, 8192, sizeof(test_pattern));
+ ed_pio_readmem(sc, 8192, test_buffer, sizeof(test_pattern));
+
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
+ sc->type = ED_TYPE_NE1000;
+ sc->type_str = "NE1000";
+ } else {
+
+ /* neither an NE1000 nor a Linksys - try NE2000 */
+ ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
+ ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
+ ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
+
+ sc->isa16bit = 1;
+
+ /*
+ * Write a test pattern in word mode. If this also fails, then
+ * we don't know what this board is.
+ */
+ ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
+ ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
+ sc->type = ED_TYPE_NE2000;
+ sc->type_str = "NE2000";
+ } else {
+ return (ENXIO);
+ }
+ }
+
+
+ /* 8k of memory plus an additional 8k if 16bit */
+ memsize = 8192 + sc->isa16bit * 8192;
+
+#if 0 /* probably not useful - NE boards only come two ways */
+ /* allow kernel config file overrides */
+ if (isa_dev->id_msize)
+ memsize = isa_dev->id_msize;
+#endif
+
+ sc->mem_size = memsize;
+
+ /* NIC memory doesn't start at zero on an NE board */
+ /* The start address is tied to the bus width */
+ sc->mem_start = (char *) 8192 + sc->isa16bit * 8192;
+ sc->mem_end = sc->mem_start + memsize;
+ sc->tx_page_start = memsize / ED_PAGE_SIZE;
+
+ if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
+ int x, i, msize = 0;
+ long mstart = 0;
+ char pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE], tbuf[ED_PAGE_SIZE];
+
+ for (i = 0; i < ED_PAGE_SIZE; i++)
+ pbuf0[i] = 0;
+
+ /* Clear all the memory. */
+ for (x = 1; x < 256; x++)
+ ed_pio_writemem(sc, pbuf0, x * 256, ED_PAGE_SIZE);
+
+ /* Search for the start of RAM. */
+ for (x = 1; x < 256; x++) {
+ ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
+ if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
+ for (i = 0; i < ED_PAGE_SIZE; i++)
+ pbuf[i] = 255 - x;
+ ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
+ ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
+ if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) {
+ mstart = x * ED_PAGE_SIZE;
+ msize = ED_PAGE_SIZE;
+ break;
+ }
+ }
+ }
+
+ if (mstart == 0) {
+ device_printf(dev, "Cannot find start of RAM.\n");
+ return (ENXIO);
+ }
+ /* Search for the start of RAM. */
+ for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) {
+ ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
+ if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
+ for (i = 0; i < ED_PAGE_SIZE; i++)
+ pbuf[i] = 255 - x;
+ ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
+ ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
+ if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0)
+ msize += ED_PAGE_SIZE;
+ else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (msize == 0) {
+ device_printf(dev, "Cannot find any RAM, start : %ld, x = %d.\n", mstart, x);
+ return (ENXIO);
+ }
+ device_printf(dev, "RAM start at %ld, size : %d.\n", mstart, msize);
+
+ sc->mem_size = msize;
+ sc->mem_start = (caddr_t)(uintptr_t) mstart;
+ sc->mem_end = (caddr_t)(uintptr_t) (msize + mstart);
+ sc->tx_page_start = mstart / ED_PAGE_SIZE;
+ }
+
+ /*
+ * Use one xmit buffer if < 16k, two buffers otherwise (if not told
+ * otherwise).
+ */
+ if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
+ sc->txb_cnt = 1;
+ else
+ sc->txb_cnt = 2;
+
+ sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
+ sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ ed_pio_readmem(sc, 0, romdata, 16);
+ for (n = 0; n < ETHER_ADDR_LEN; n++)
+ sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)];
+
+ if ((ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) &&
+ (sc->arpcom.ac_enaddr[2] == 0x86)) {
+ sc->type_str = "Gateway AT";
+ }
+
+ /* clear any pending interrupts that might have occurred above */
+ ed_nic_outb(sc, ED_P0_ISR, 0xff);
+
+ return (0);
+}
+
+int
+ed_probe_Novell(device_t dev, int port_rid, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+
+ error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS);
+ if (error)
+ return (error);
+
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+
+ return ed_probe_Novell_generic(dev, flags);
+}
diff --git a/sys/dev/ed/if_ed_sic.c b/sys/dev/ed/if_ed_sic.c
new file mode 100644
index 0000000..802f842
--- /dev/null
+++ b/sys/dev/ed/if_ed_sic.c
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ed.h"
+
+#ifdef ED_SIC
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_edvar.h>
+
+/*
+ * Probe and vendor-specific initialization routine for SIC boards
+ */
+int
+ed_probe_SIC(device_t dev, int port_rid, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int i;
+ u_int memsize;
+ u_long pmem;
+ u_char sum;
+
+ error = ed_alloc_port(dev, 0, ED_SIC_IO_PORTS);
+ if (error)
+ return (error);
+
+ sc->asic_offset = ED_SIC_ASIC_OFFSET;
+ sc->nic_offset = ED_SIC_NIC_OFFSET;
+
+ memsize = 16384;
+ /* XXX Needs to allow different msize */
+ error = ed_alloc_memory(dev, 0, memsize);
+ if (error)
+ return (error);
+
+ sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_size = memsize;
+
+ pmem = rman_get_start(sc->mem_res);
+ error = ed_isa_mem_ok(dev, pmem, memsize);
+ if (error)
+ return (error);
+
+ /* Reset card to force it into a known state. */
+ ed_asic_outb(sc, 0, 0x00);
+ DELAY(100);
+
+ /*
+ * Here we check the card ROM, if the checksum passes, and the
+ * type code and ethernet address check out, then we know we have
+ * an SIC card.
+ */
+ ed_asic_outb(sc, 0, 0x81);
+ DELAY(100);
+
+ sum = sc->mem_start[6];
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ sum ^= (sc->arpcom.ac_enaddr[i] = sc->mem_start[i]);
+ }
+#ifdef ED_DEBUG
+ device_printf(dev, "ed_probe_sic: got address %6D\n",
+ sc->arpcom.ac_enaddr, ":");
+#endif
+ if (sum != 0) {
+ return (ENXIO);
+ }
+ if ((sc->arpcom.ac_enaddr[0] | sc->arpcom.ac_enaddr[1] |
+ sc->arpcom.ac_enaddr[2]) == 0) {
+ return (ENXIO);
+ }
+
+ sc->vendor = ED_VENDOR_SIC;
+ sc->type_str = "SIC";
+ sc->isa16bit = 0;
+ sc->cr_proto = 0;
+
+ /*
+ * SIC RAM page 0x0000-0x3fff(or 0x7fff)
+ */
+ ed_asic_outb(sc, 0, 0x80);
+ DELAY(100);
+
+ error = ed_clear_memory(dev);
+ if (error)
+ return (error);
+
+ sc->mem_shared = 1;
+ sc->mem_end = sc->mem_start + sc->mem_size;
+
+ /*
+ * allocate one xmit buffer if < 16k, two buffers otherwise
+ */
+ if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
+ sc->txb_cnt = 1;
+ else
+ sc->txb_cnt = 2;
+ sc->tx_page_start = 0;
+
+ sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
+ sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ return (0);
+}
+
+#endif /* ED_SIL */
diff --git a/sys/dev/ed/if_ed_wd80x3.c b/sys/dev/ed/if_ed_wd80x3.c
new file mode 100644
index 0000000..2ecbbb0
--- /dev/null
+++ b/sys/dev/ed/if_ed_wd80x3.c
@@ -0,0 +1,468 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ed.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <dev/ed/if_edreg.h>
+#include <dev/ed/if_edvar.h>
+
+/*
+ * Interrupt conversion table for WD/SMC ASIC/83C584
+ */
+static uint16_t ed_intr_val[] = {
+ 9,
+ 3,
+ 5,
+ 7,
+ 10,
+ 11,
+ 15,
+ 4
+};
+
+/*
+ * Interrupt conversion table for 83C790
+ */
+static uint16_t ed_790_intr_val[] = {
+ 0,
+ 9,
+ 3,
+ 5,
+ 7,
+ 10,
+ 11,
+ 15
+};
+
+static void
+ed_disable_16bit_access(struct ed_softc *sc)
+{
+ /*
+ * Disable 16 bit access to shared memory
+ */
+ if (sc->isa16bit) {
+ if (sc->chip_type == ED_CHIP_TYPE_WD790)
+ ed_asic_outb(sc, ED_WD_MSR, 0x00);
+ ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto &
+ ~ED_WD_LAAR_M16EN);
+ }
+}
+
+/*
+ * Probe and vendor-specific initialization routine for SMC/WD80x3 boards
+ */
+int
+ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ int i;
+ u_int memsize;
+ u_char iptr, isa16bit, sum, totalsum;
+ u_long irq, junk, pmem;
+
+ sc->chip_type = ED_CHIP_TYPE_DP8390;
+
+ if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
+ totalsum = ED_WD_ROM_CHECKSUM_TOTAL_TOSH_ETHER;
+ ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_POW);
+ DELAY(10000);
+ }
+ else
+ totalsum = ED_WD_ROM_CHECKSUM_TOTAL;
+
+ /*
+ * Attempt to do a checksum over the station address PROM. If it
+ * fails, it's probably not a SMC/WD board. There is a problem with
+ * this, though: some clone WD boards don't pass the checksum test.
+ * Danpex boards for one.
+ */
+ for (sum = 0, i = 0; i < 8; ++i)
+ sum += ed_asic_inb(sc, ED_WD_PROM + i);
+
+ if (sum != totalsum) {
+
+ /*
+ * Checksum is invalid. This often happens with cheap WD8003E
+ * clones. In this case, the checksum byte (the eighth byte)
+ * seems to always be zero.
+ */
+ if (ed_asic_inb(sc, ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
+ ed_asic_inb(sc, ED_WD_PROM + 7) != 0)
+ return (ENXIO);
+ }
+ /* reset card to force it into a known state. */
+ if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER)
+ ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
+ else
+ ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST);
+
+ DELAY(100);
+ ed_asic_outb(sc, ED_WD_MSR, ed_asic_inb(sc, ED_WD_MSR) & ~ED_WD_MSR_RST);
+ /* wait in the case this card is reading its EEROM */
+ DELAY(5000);
+
+ sc->vendor = ED_VENDOR_WD_SMC;
+ sc->type = ed_asic_inb(sc, ED_WD_CARD_ID);
+
+ /*
+ * Set initial values for width/size.
+ */
+ memsize = 8192;
+ isa16bit = 0;
+ switch (sc->type) {
+ case ED_TYPE_WD8003S:
+ sc->type_str = "WD8003S";
+ break;
+ case ED_TYPE_WD8003E:
+ sc->type_str = "WD8003E";
+ break;
+ case ED_TYPE_WD8003EB:
+ sc->type_str = "WD8003EB";
+ break;
+ case ED_TYPE_WD8003W:
+ sc->type_str = "WD8003W";
+ break;
+ case ED_TYPE_WD8013EBT:
+ sc->type_str = "WD8013EBT";
+ memsize = 16384;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_WD8013W:
+ sc->type_str = "WD8013W";
+ memsize = 16384;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_WD8013EP: /* also WD8003EP */
+ if (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) {
+ isa16bit = 1;
+ memsize = 16384;
+ sc->type_str = "WD8013EP";
+ } else
+ sc->type_str = "WD8003EP";
+ break;
+ case ED_TYPE_WD8013WC:
+ sc->type_str = "WD8013WC";
+ memsize = 16384;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_WD8013EBP:
+ sc->type_str = "WD8013EBP";
+ memsize = 16384;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_WD8013EPC:
+ sc->type_str = "WD8013EPC";
+ memsize = 16384;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_SMC8216C: /* 8216 has 16K shared mem -- 8416 has 8K */
+ case ED_TYPE_SMC8216T:
+ if (sc->type == ED_TYPE_SMC8216C)
+ sc->type_str = "SMC8216/SMC8216C";
+ else
+ sc->type_str = "SMC8216T";
+
+ ed_asic_outb(sc, ED_WD790_HWR,
+ ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
+ switch (ed_asic_inb(sc, ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
+ case ED_WD790_RAR_SZ64:
+ memsize = 65536;
+ break;
+ case ED_WD790_RAR_SZ32:
+ memsize = 32768;
+ break;
+ case ED_WD790_RAR_SZ16:
+ memsize = 16384;
+ break;
+ case ED_WD790_RAR_SZ8:
+ /* 8216 has 16K shared mem -- 8416 has 8K */
+ if (sc->type == ED_TYPE_SMC8216C)
+ sc->type_str = "SMC8416C/SMC8416BT";
+ else
+ sc->type_str = "SMC8416T";
+ memsize = 8192;
+ break;
+ }
+ ed_asic_outb(sc, ED_WD790_HWR,
+ ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+
+ isa16bit = 1;
+ sc->chip_type = ED_CHIP_TYPE_WD790;
+ break;
+ case ED_TYPE_TOSHIBA1:
+ sc->type_str = "Toshiba1";
+ memsize = 32768;
+ isa16bit = 1;
+ break;
+ case ED_TYPE_TOSHIBA4:
+ sc->type_str = "Toshiba4";
+ memsize = 32768;
+ isa16bit = 1;
+ break;
+ default:
+ sc->type_str = "";
+ break;
+ }
+
+ /*
+ * Make some adjustments to initial values depending on what is found
+ * in the ICR.
+ */
+ if (isa16bit && (sc->type != ED_TYPE_WD8013EBT)
+ && (sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4)
+ && ((ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
+ isa16bit = 0;
+ memsize = 8192;
+ }
+
+ /* Override memsize? XXX */
+ error = ed_alloc_memory(dev, 0, memsize);
+ if (error)
+ return (error);
+ sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+
+#ifdef ED_DEBUG
+ printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%lu\n",
+ sc->type, sc->type_str, isa16bit, memsize,
+ rman_get_size(sc->mem_res));
+ for (i = 0; i < 8; i++)
+ printf("%x -> %x\n", i, ed_asic_inb(sc, i));
+#endif
+ pmem = rman_get_start(sc->mem_res);
+ error = ed_isa_mem_ok(dev, pmem, memsize);
+ if (error)
+ return (error);
+
+ /*
+ * (note that if the user specifies both of the following flags that
+ * '8bit' mode intentionally has precedence)
+ */
+ if (flags & ED_FLAGS_FORCE_16BIT_MODE)
+ isa16bit = 1;
+ if (flags & ED_FLAGS_FORCE_8BIT_MODE)
+ isa16bit = 0;
+
+ /*
+ * If possible, get the assigned interrupt number from the card and
+ * use it.
+ */
+ if ((sc->type & ED_WD_SOFTCONFIG) &&
+ (sc->chip_type != ED_CHIP_TYPE_WD790)) {
+
+ /*
+ * Assemble together the encoded interrupt number.
+ */
+ iptr = (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_IR2) |
+ ((ed_asic_inb(sc, ED_WD_IRR) &
+ (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
+
+ /*
+ * If no interrupt specified (or "?"), use what the board tells us.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
+ if (error && intr_vals[0] != NULL)
+ error = bus_set_resource(dev, SYS_RES_IRQ, 0,
+ intr_vals[0][iptr], 1);
+ if (error)
+ return (error);
+
+ /*
+ * Enable the interrupt.
+ */
+ ed_asic_outb(sc, ED_WD_IRR,
+ ed_asic_inb(sc, ED_WD_IRR) | ED_WD_IRR_IEN);
+ }
+ if (sc->chip_type == ED_CHIP_TYPE_WD790) {
+ ed_asic_outb(sc, ED_WD790_HWR,
+ ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
+ iptr = (((ed_asic_inb(sc, ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) |
+ (ed_asic_inb(sc, ED_WD790_GCR) &
+ (ED_WD790_GCR_IR1 | ED_WD790_GCR_IR0)) >> 2);
+ ed_asic_outb(sc, ED_WD790_HWR,
+ ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+
+ /*
+ * If no interrupt specified (or "?"), use what the board tells us.
+ */
+ error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
+ if (error && intr_vals[1] != NULL)
+ error = bus_set_resource(dev, SYS_RES_IRQ, 0,
+ intr_vals[1][iptr], 1);
+ if (error)
+ return (error);
+
+ /*
+ * Enable interrupts.
+ */
+ ed_asic_outb(sc, ED_WD790_ICR,
+ ed_asic_inb(sc, ED_WD790_ICR) | ED_WD790_ICR_EIL);
+ }
+ error = bus_get_resource(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);
+ }
+ sc->isa16bit = isa16bit;
+ sc->mem_shared = 1;
+
+ /*
+ * allocate one xmit buffer if < 16k, two buffers otherwise
+ */
+ if (memsize < 16384 || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
+ sc->txb_cnt = 1;
+ else
+ sc->txb_cnt = 2;
+ sc->tx_page_start = ED_WD_PAGE_OFFSET;
+ sc->rec_page_start = ED_WD_PAGE_OFFSET + ED_TXBUF_SIZE * sc->txb_cnt;
+ sc->rec_page_stop = ED_WD_PAGE_OFFSET + memsize / ED_PAGE_SIZE;
+ sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * sc->rec_page_start);
+ sc->mem_size = memsize;
+ sc->mem_end = sc->mem_start + memsize;
+
+ /*
+ * Get station address from on-board ROM
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; ++i)
+ sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, ED_WD_PROM + i);
+
+ /*
+ * Set upper address bits and 8/16 bit access to shared memory.
+ */
+ if (isa16bit) {
+ if (sc->chip_type == ED_CHIP_TYPE_WD790)
+ sc->wd_laar_proto = ed_asic_inb(sc, ED_WD_LAAR);
+ else
+ sc->wd_laar_proto = ED_WD_LAAR_L16EN |
+ ((pmem >> 19) & ED_WD_LAAR_ADDRHI);
+ /*
+ * Enable 16bit access
+ */
+ ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto |
+ ED_WD_LAAR_M16EN);
+ } else {
+ if (((sc->type & ED_WD_SOFTCONFIG) ||
+ (sc->type == ED_TYPE_TOSHIBA1) ||
+ (sc->type == ED_TYPE_TOSHIBA4) ||
+ (sc->type == ED_TYPE_WD8013EBT)) &&
+ (sc->chip_type != ED_CHIP_TYPE_WD790)) {
+ sc->wd_laar_proto = (pmem >> 19) &
+ ED_WD_LAAR_ADDRHI;
+ ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto);
+ }
+ }
+
+ /*
+ * Set address and enable interface shared memory.
+ */
+ if (sc->chip_type != ED_CHIP_TYPE_WD790) {
+ if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
+ ed_asic_outb(sc, ED_WD_MSR + 1,
+ ((pmem >> 8) & 0xe0) | 4);
+ ed_asic_outb(sc, ED_WD_MSR + 2, ((pmem >> 16) & 0x0f));
+ ed_asic_outb(sc, ED_WD_MSR,
+ ED_WD_MSR_MENB | ED_WD_MSR_POW);
+ } else {
+ ed_asic_outb(sc, ED_WD_MSR, ((pmem >> 13) &
+ ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
+ }
+ sc->cr_proto = ED_CR_RD2;
+ } else {
+ ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_MENB);
+ ed_asic_outb(sc, ED_WD790_HWR,
+ (ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH));
+ ed_asic_outb(sc, ED_WD790_RAR,
+ ((pmem >> 13) & 0x0f) | ((pmem >> 11) & 0x40) |
+ (ed_asic_inb(sc, ED_WD790_RAR) & 0xb0));
+ ed_asic_outb(sc, ED_WD790_HWR,
+ (ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH));
+ sc->cr_proto = 0;
+ }
+
+ error = ed_clear_memory(dev);
+ if (error) {
+ ed_disable_16bit_access(sc);
+ return (error);
+ }
+
+ /*
+ * Disable 16bit access to shared memory - we leave it
+ * disabled so that 1) machines reboot properly when the board
+ * is set 16 bit mode and there are conflicting 8bit
+ * devices/ROMS in the same 128k address space as this boards
+ * shared memory. and 2) so that other 8 bit devices with
+ * shared memory can be used in this 128k region, too.
+ */
+ ed_disable_16bit_access(sc);
+ return (0);
+}
+
+int
+ed_probe_WD80x3(device_t dev, int port_rid, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ int error;
+ static uint16_t *intr_vals[] = {ed_intr_val, ed_790_intr_val};
+
+ error = ed_alloc_port(dev, port_rid, ED_WD_IO_PORTS);
+ if (error)
+ return (error);
+
+ sc->asic_offset = ED_WD_ASIC_OFFSET;
+ sc->nic_offset = ED_WD_NIC_OFFSET;
+
+ return ed_probe_WD80x3_generic(dev, flags, intr_vals);
+}
diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h
index 5020858..4707f35 100644
--- a/sys/dev/ed/if_edvar.h
+++ b/sys/dev/ed/if_edvar.h
@@ -207,6 +207,7 @@ int ed_probe_HP_pclanp(device_t, int, int);
int ed_attach(device_t);
int ed_detach(device_t);
int ed_clear_memory(device_t);
+int ed_isa_mem_ok(device_t, u_long, u_int); /* XXX isa specific */
void ed_stop(struct ed_softc *);
void ed_pio_readmem(struct ed_softc *, long, uint8_t *, uint16_t);
void ed_pio_writemem(struct ed_softc *, uint8_t *, uint16_t, uint16_t);
@@ -218,6 +219,11 @@ void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
void ed_child_detached(device_t, device_t);
#endif
+/* The following is unsatisfying XXX */
+void ed_hpp_set_physical_link(struct ed_softc *);
+void ed_hpp_readmem(struct ed_softc *, long, uint8_t *, uint16_t);
+u_short ed_hpp_write_mbufs(struct ed_softc *, struct mbuf *, int);
+
driver_intr_t edintr;
extern devclass_t ed_devclass;
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 70267c4..ba9a563 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -547,6 +547,9 @@ hint.cx.0.drq="7"
#options NETGRAPH_CRONYX # Enable NETGRAPH support for Cronyx adapter(s)
device ed
#options ED_NO_MIIBUS # Disable ed miibus support
+options ED_3C503
+options ED_HPP
+options ED_SIC
hint.ed.0.at="isa"
hint.ed.0.port="0x280"
hint.ed.0.irq="5"
diff --git a/sys/modules/ed/Makefile b/sys/modules/ed/Makefile
index dda16ed..7f15242 100644
--- a/sys/modules/ed/Makefile
+++ b/sys/modules/ed/Makefile
@@ -3,12 +3,12 @@
.PATH: ${.CURDIR}/../../dev/ed
KMOD= if_ed
-SRCS= if_ed.c if_ed_pccard.c if_ed_pci.c
+SRCS= if_ed.c if_ed_pccard.c if_ed_pci.c if_ed_novell.c if_ed_wd80x3.c
.if ${MACHINE} == "pc98"
SRCS+= if_ed_cbus.c
.else
-SRCS+= if_ed_isa.c
+SRCS+= if_ed_isa.c if_ed_3c503.c if_ed_hpp.c if_ed_sic.c
.endif
SRCS+= opt_ed.h opt_bdg.h bus_if.h card_if.h device_if.h isa_if.h pci_if.h \
OpenPOWER on IntegriCloud