Deleted Added
full compact
29c29
< __FBSDID("$FreeBSD: head/sys/dev/ed/if_ed.c 141548 2005-02-08 23:57:43Z imp $");
---
> __FBSDID("$FreeBSD: head/sys/dev/ed/if_ed.c 141586 2005-02-09 20:03:40Z imp $");
71,72d70
< #include <machine/md_var.h>
<
94,99d91
< 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);
<
105,155d96
< * 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 */
< };
<
< /*
192,1572d132
< * 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);
<
< }
<
< /*
1582c142
< 0ul, ~0ul, size, RF_ACTIVE);
---
> 0ul, ~0ul, size, RF_ACTIVE);
1603c163
< 0ul, ~0ul, size, RF_ACTIVE);
---
> 0ul, ~0ul, size, RF_ACTIVE);
1623,1624c183
< 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);
1730a290
> #ifdef ED_HPP
1736a297
> #endif
2675c1236,1238
< } else if (sc->vendor == ED_VENDOR_HP)
---
> }
> #ifdef ED_HPP
> else if (sc->vendor == ED_VENDOR_HP)
2676a1240
> #endif
2805a1370
> #ifdef ED_HPP
2810a1376
> #endif
2891a1458
> #ifdef ED_HPP
2893c1460
< if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) {
---
> if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS)
2895c1462
< }
---
> #endif
2998,3270d1564
< /*
< * 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);
< }
<
3467a1762,1772
> 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