diff options
author | Thomas Schwinge <tschwinge@gnu.org> | 2006-02-20 19:25:22 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-06-18 00:26:33 +0200 |
commit | c8075f5570ee013830075e74d2bc06bb52f88194 (patch) | |
tree | 7bae16b5cb515b8ef90f6c771c07a9fd87866a6f | |
parent | 5b16c90c49b899ae62674c352514077a0a6afa2b (diff) |
2006-02-20 Thomas Schwinge <tschwinge@gnu.org>
Remove unused and unsupported code. Consult the file
`DEVELOPMENT' for details. Partly based on suggestions by
Gianluca Guida <glguida@gmail.com>.
* i386/bogus/hpp.h: Remove file.
* i386/bogus/ul.h: Likewise.
* i386/bogus/wd.h: Likewise.
* i386/i386at/gpl/if_hpp.c: Likewise.
* i386/i386at/gpl/if_ns.c: Likewise.
* i386/i386at/gpl/if_nsreg.h: Likewise.
* i386/i386at/gpl/if_ul.c: Likewise.
* i386/i386at/gpl/if_wd.c: Likewise.
* i386/i386at/autoconf.c: Don't include <hpp.h>, <ul.h> and <wd.h>
anymore and adopt all users of NHPP, NUL and NWD as if they were always
defined to `0'.
* i386/i386at/conf.c: Likewise.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | i386/bogus/hpp.h | 1 | ||||
-rw-r--r-- | i386/bogus/ul.h | 1 | ||||
-rw-r--r-- | i386/bogus/wd.h | 1 | ||||
-rw-r--r-- | i386/i386at/autoconf.c | 33 | ||||
-rw-r--r-- | i386/i386at/conf.c | 42 | ||||
-rw-r--r-- | i386/i386at/gpl/if_hpp.c | 690 | ||||
-rw-r--r-- | i386/i386at/gpl/if_ns.c | 642 | ||||
-rw-r--r-- | i386/i386at/gpl/if_nsreg.h | 169 | ||||
-rw-r--r-- | i386/i386at/gpl/if_ul.c | 489 | ||||
-rw-r--r-- | i386/i386at/gpl/if_wd.c | 581 |
11 files changed, 13 insertions, 2649 deletions
@@ -4,6 +4,19 @@ `DEVELOPMENT' for details. Partly based on suggestions by Gianluca Guida <glguida@gmail.com>. + * i386/bogus/hpp.h: Remove file. + * i386/bogus/ul.h: Likewise. + * i386/bogus/wd.h: Likewise. + * i386/i386at/gpl/if_hpp.c: Likewise. + * i386/i386at/gpl/if_ns.c: Likewise. + * i386/i386at/gpl/if_nsreg.h: Likewise. + * i386/i386at/gpl/if_ul.c: Likewise. + * i386/i386at/gpl/if_wd.c: Likewise. + * i386/i386at/autoconf.c: Don't include <hpp.h>, <ul.h> and <wd.h> + anymore and adopt all users of NHPP, NUL and NWD as if they were always + defined to `0'. + * i386/i386at/conf.c: Likewise. + * i386/bogus/at3c501.h: Remove file. * i386/i386at/if_3c501.c: Likewise. * i386/i386at/if_3c501.h: Likewise. diff --git a/i386/bogus/hpp.h b/i386/bogus/hpp.h deleted file mode 100644 index b47b397..0000000 --- a/i386/bogus/hpp.h +++ /dev/null @@ -1 +0,0 @@ -#define NHPP 1 diff --git a/i386/bogus/ul.h b/i386/bogus/ul.h deleted file mode 100644 index 94f74ab..0000000 --- a/i386/bogus/ul.h +++ /dev/null @@ -1 +0,0 @@ -#define NUL 0 diff --git a/i386/bogus/wd.h b/i386/bogus/wd.h deleted file mode 100644 index 6c9b955..0000000 --- a/i386/bogus/wd.h +++ /dev/null @@ -1 +0,0 @@ -#define NWD 0 diff --git a/i386/i386at/autoconf.c b/i386/i386at/autoconf.c index 50a0e6f..caf4bd5 100644 --- a/i386/i386at/autoconf.c +++ b/i386/i386at/autoconf.c @@ -59,24 +59,6 @@ extern struct bus_driver eaha_driver; extern int eaha_intr(); #endif /* NEAHA */ -#include <ul.h> -#if NUL > 0 -extern struct bus_driver uldriver; -extern int ulintr(); -#endif - -#include <wd.h> -#if NWD > 0 -extern struct bus_driver wddriver; -extern int wdintr(); -#endif - -#include <hpp.h> -#if NHPP > 0 -extern struct bus_driver hppdriver; -extern int hppintr(); -#endif - #include <com.h> #if NCOM > 0 extern struct bus_driver comdriver; @@ -238,21 +220,6 @@ struct bus_device bus_device_init[] = { { &eaha_driver, "tz", 6, 0, 0x0,0, 0, '?', 0, 0, 6, 0, }, { &eaha_driver, "tz", 7, 0, 0x0,0, 0, '?', 0, 0, 7, 0, }, #endif /* NEAHA > 0*/ - -#if NUL > 0 - {&uldriver, "ul", 0, ulintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 0}, - {&uldriver, "ul", 1, ulintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 0}, -#endif - -#if NWD > 0 - {&wddriver, "wd", 0, wdintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 9}, - {&wddriver, "wd", 1, wdintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 15}, -#endif - -#if NHPP > 0 - {&hppdriver, "hpp", 0, hppintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 0}, - {&hppdriver, "hpp", 1, hppintr, 0, 0, 0, '?', 0, -1, -1, 0, 0, 0, SPL_SIX, 0}, -#endif #endif /* ! LINUX_DEV */ #if NCOM > 0 diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c index e718b7d..179c9db 100644 --- a/i386/i386at/conf.c +++ b/i386/i386at/conf.c @@ -54,27 +54,6 @@ extern int wtopen(), wtread(), wtwrite(), wtclose(); #define wtname "wt" #endif /* NWT > 0 */ -#include <ul.h> -#if NUL > 0 -extern int ulopen(), uloutput(), ulgetstat(), ulsetstat(), - ulsetinput(); -#define ulname "ul" -#endif /* NUL > 0 */ - -#include <wd.h> -#if NWD > 0 -extern int wdopen(), wdoutput(), wdgetstat(), wdsetstat(), - wdsetinput(); -#define wdname "wd" -#endif /* NWD > 0 */ - -#include <hpp.h> -#if NHPP > 0 -extern int hppopen(), hppoutput(), hppgetstat(), hppsetstat(), - hppsetinput(); -#define hppname "hpp" -#endif /* NHPP > 0 */ - #include <par.h> #if NPAR > 0 extern int paropen(), paroutput(), pargetstat(), parsetstat(), @@ -191,27 +170,6 @@ struct dev_ops dev_name_list[] = nodev }, #endif /* NWT > 0 */ -#if NUL > 0 - { ulname, ulopen, nulldev, nulldev, - uloutput, ulgetstat, ulsetstat, nulldev, - ulsetinput, nulldev, nulldev, 0, - nodev }, -#endif - -#if NWD > 0 - { wdname, wdopen, nulldev, nulldev, - wdoutput, wdgetstat, wdsetstat, nulldev, - wdsetinput, nulldev, nulldev, 0, - nodev }, -#endif - -#if NHPP > 0 - { hppname, hppopen, nulldev, nulldev, - hppoutput, hppgetstat, hppsetstat, nulldev, - hppsetinput, nulldev, nulldev, 0, - nodev }, -#endif - #if NPAR > 0 { parname, paropen, nulldev, nulldev, paroutput, pargetstat, parsetstat, nomap, diff --git a/i386/i386at/gpl/if_hpp.c b/i386/i386at/gpl/if_hpp.c deleted file mode 100644 index c177030..0000000 --- a/i386/i386at/gpl/if_hpp.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - Written 1994 by Donald Becker. - - This driver is for the Hewlett Packard PC LAN (27***) plus ethercards. - These cards are sold under several model numbers, usually 2724*. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - As is often the case, a great deal of credit is owed to Russ Nelson. - The Crynwr packet driver was my primary source of HP-specific - programming information. -*/ - -/* - * Ported to mach by Stephen Clawson, sclawson@cs.utah.edu - * University of Utah CSL. - * - * Derived from the Linux driver by Donald Becker. - * - * Also uses code Shantanu Goel adapted from Donald Becker - * for ns8930 support. - * - */ - -#include <hpp.h> -#if NHPP > 0 - -#include <sys/types.h> -#include "vm_param.h" -#include <kern/time_out.h> -#include <device/device_types.h> -#include <device/errno.h> -#include <device/io_req.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/net_status.h> -#include <device/net_io.h> -#include <chips/busses.h> -#include <i386/ipl.h> -#include <i386/pio.h> -#include <i386at/gpl/if_nsreg.h> - - -/* - * XXX - This is some gross glue garbage. The io instructions really - * should be integrated into pio.h... - */ -#define IO_DELAY __asm__ __volatile__("outb %al,$0x80") -#define outb_p(p, v) { outb(p, v); IO_DELAY; } -#define inb_p(p) ({ unsigned char _v; _v = inb(p); IO_DELAY; _v; }) - - -static __inline void -insw(u_short port, void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\tinsw" : - : "d" (port), "D" (addr), "c" (cnt) : "%edi", "%ecx"); -} - -static __inline void -outsw(u_short port, void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\toutsw" : - : "d" (port), "S" (addr), "c" (cnt) : "%esi", "%ecx"); -} - - -/* - The HP EtherTwist chip implementation is a fairly routine DP8390 - implementation. It allows both shared memory and programmed-I/O buffer - access, using a custom interface for both. The programmed-I/O mode is - entirely implemented in the HP EtherTwist chip, bypassing the problem - ridden built-in 8390 facilities used on NE2000 designs. The shared - memory mode is likewise special, with an offset register used to make - packets appear at the shared memory base. Both modes use a base and bounds - page register to hide the Rx ring buffer wrap -- a packet that spans the - end of physical buffer memory appears continuous to the driver. (c.f. the - 3c503 and Cabletron E2100) - - A special note: the internal buffer of the board is only 8 bits wide. - This lays several nasty traps for the unaware: - - the 8390 must be programmed for byte-wide operations - - all I/O and memory operations must work on whole words (the access - latches are serially preloaded and have no byte-swapping ability). - - This board is laid out in I/O space much like the earlier HP boards: - the first 16 locations are for the board registers, and the second 16 are - for the 8390. The board is easy to identify, with both a dedicated 16 bit - ID register and a constant 0x530* value in the upper bits of the paging - register. -*/ - -#define HP_ID 0x00 /* ID register, always 0x4850. */ -#define HP_PAGING 0x02 /* Registers visible @ 8-f, see PageName. */ -#define HPP_OPTION 0x04 /* Bitmapped options, see HP_Option.*/ -#define HPP_OUT_ADDR 0x08 /* I/O output location in Perf_Page.*/ -#define HPP_IN_ADDR 0x0A /* I/O input location in Perf_Page.*/ -#define HP_DATAPORT 0x0c /* I/O data transfer in Perf_Page.*/ -#define HPP_NIC_OFFSET 0x10 /* Offset to the 8390 registers.*/ -#define HP_IO_EXTENT 32 - -#define HP_START_PG 0x00 /* First page of TX buffer */ -#define HP_STOP_PG 0x80 /* Last page +1 of RX ring */ -/*#define HP_STOP_PG 0x1f - -/* The register set selected in HP_PAGING. */ -enum PageName { - Perf_Page = 0, /* Normal operation. */ - MAC_Page = 1, /* The ethernet address (+checksum). */ - HW_Page = 2, /* EEPROM-loaded hw parameters. */ - LAN_Page = 4, /* Transciever type, testing, etc. */ - ID_Page = 6 }; - -/* The bit definitions for the HPP_OPTION register. */ -enum HP_Option { - NICReset = 1, /* Active low, really UNreset. */ - ChipReset = 2, - EnableIRQ = 4, - FakeIntr = 8, - BootROMEnb = 0x10, - IOEnb = 0x20, - MemEnable = 0x40, - ZeroWait = 0x80, - MemDisable = 0x1000, }; - - -void hpp_reset_8390(struct nssoftc *ns); - -void hpp_mem_block_input(struct nssoftc *ns, int, char *, int); -int hpp_mem_block_output(struct nssoftc *ns, int, char *, int); -void hpp_io_block_input(struct nssoftc *ns, int, char *, int); -int hpp_io_block_output(struct nssoftc *ns, int,char *, int); - - -/* - * Watchdog timer. - */ -int hppwstart = 0; -void hppwatch(void); - - -/* - * Autoconfig structures. - */ -int hpp_std[] = { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0 }; -struct bus_device *hpp_info[NHPP]; -int hpp_probe(); -void hpp_attach(); -struct bus_driver hppdriver = { - hpp_probe, 0, hpp_attach, 0, hpp_std, "hpp", hpp_info, 0, 0, 0 -}; - - -/* - * ns8390 state. - */ -struct nssoftc hppnssoftc[NHPP]; - - -/* - * hpp state. - */ -struct hppsoftc { - unsigned long rmem_start; /* shmem "recv" start */ - unsigned long rmem_end; /* shmem "recv" end */ - unsigned long mem_start; /* shared mem start */ - unsigned long mem_end; /* shared mem end */ -} hppsoftc[NHPP]; - - -/* - * Probe a list of addresses for the card. - * - */ -int hpp_probe(port, dev) - int port; - struct bus_device *dev; -{ - int unit = dev->unit; - char *str = "hp-plus ethernet board %d out of range.\n"; - caddr_t base = (caddr_t) (dev ? dev->address : 0); - int i; - - if ((unit < 0) || (unit >= NHPP)) { - printf(str, unit); - return(0); - } - - /* Check a single specified location. */ - if (base > (caddr_t) 0x1ff) - return hpp_probe1(dev, base); - else if (base != 0) /* Don't probe at all. */ - return 0; - - for (i = 0; hpp_std[i]; i++) { - int ioaddr = hpp_std[i]; - - if ( ioaddr > 0 && hpp_probe1(dev, ioaddr) ) { - dev->address = ioaddr; - hpp_std[i] = -1; /* Mark address used */ - return(1); - } - } - - return 0; -} - - - -/* - * Do the interesting part of the probe at a single address. - * - */ -int hpp_probe1(dev, ioaddr) - struct bus_device *dev; - int ioaddr; -{ - int i; - u_char checksum = 0; - int mem_start; - - struct hppsoftc *hpp = &hppsoftc[dev->unit]; - struct nssoftc *ns = &hppnssoftc[dev->unit]; - struct ifnet *ifp = &ns->sc_if; - - /* Check for the HP+ signature, 50 48 0x 53. */ - if (inw(ioaddr + HP_ID) != 0x4850 - || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) - return 0; - - - printf("%s%d: HP PClan plus at %#3x,", dev->name, dev->unit, ioaddr); - /* Retrieve and checksum the station address. */ - outw(ioaddr + HP_PAGING, MAC_Page); - - printf("MAC_Page = %d, ioaddr = %x\n", MAC_Page, ioaddr); - - for(i = 0; i < ETHER_ADDR_LEN; i++) { - u_char inval = inb(ioaddr + 8 + i); - ns->sc_addr[i] = inval; - checksum += inval; - printf(" %2.2x", inval); - } - checksum += inb(ioaddr + 14); - - if (checksum != 0xff) { - printf(" bad checksum %2.2x.\n", checksum); - return 0; - } else { - /* Point at the Software Configuration Flags. */ - outw(ioaddr + HP_PAGING, ID_Page); - printf(" ID %4.4x", inw(ioaddr + 12)); - } - - - /* Read the IRQ line. */ - outw(ioaddr + HP_PAGING, HW_Page); - { - int irq = inb(ioaddr + 13) & 0x0f; - int option = inw(ioaddr + HPP_OPTION); - - dev->sysdep1 = irq; - take_dev_irq(dev); - - if (option & MemEnable) { - mem_start = inw(ioaddr + 9) << 8; - printf(", IRQ %d, memory address %#x.\n", irq, mem_start); - } else { - mem_start = 0; - printf(", IRQ %d, programmed-I/O mode.\n", irq); - } - } - - /* Set the wrap registers for string I/O reads. */ - outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8)); - - /* Set the base address to point to the NIC, not the "real" base! */ - ns->sc_port = ioaddr + HPP_NIC_OFFSET; - - ns->sc_name = dev->name; - ns->sc_unit = dev->unit; - ns->sc_pingpong = 0; /* turn off pingpong mode */ - ns->sc_word16 = 0; /* Agggghhhhh! Debug time: 2 days! */ - ns->sc_txstrtpg = HP_START_PG; - ns->sc_rxstrtpg = HP_START_PG + TX_2X_PAGES; - ns->sc_stoppg = HP_STOP_PG; - - - ns->sc_reset = hpp_reset_8390; - ns->sc_input = hpp_io_block_input; - ns->sc_output = hpp_io_block_output; - - /* Check if the memory_enable flag is set in the option register. */ - if (mem_start) { - ns->sc_input = hpp_mem_block_input; - ns->sc_output = hpp_mem_block_output; - hpp->mem_start = mem_start; - hpp->rmem_start = hpp->mem_start + TX_2X_PAGES * 256; - hpp->mem_end = hpp->rmem_end - = hpp->mem_start + (HP_STOP_PG - HP_START_PG) * 256; - } - - outw(ioaddr + HP_PAGING, Perf_Page); - - /* Leave the 8390 and HP chip reset. */ - outw( ioaddr + HPP_OPTION, inw(ioaddr + HPP_OPTION) & ~EnableIRQ ); - - /* - * Initialize interface header. - */ - ifp->if_unit = dev->unit; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST; - ifp->if_header_size = sizeof(struct ether_header); - ifp->if_header_format = HDR_ETHERNET; - ifp->if_address_size = ETHER_ADDR_LEN; - ifp->if_address = ns->sc_addr; - if_init_queues(ifp); - - return (1); -} - -/* - * XXX - * - * this routine really should do the invasive part of the setup. - */ -void -hpp_attach(dev) - struct bus_device *dev; -{ - /* NULL */ -} - - - -int -hppopen(dev, flag) - dev_t dev; - int flag; -{ - int s, unit = minor(dev); - struct bus_device *bd; - struct hppsoftc *hpp; - struct nssoftc *ns = &hppnssoftc[unit]; - - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - int option_reg; - - if (unit < 0 || unit >= NHPP || - (bd = hpp_info[unit]) == 0 || !(bd->alive)) - return ENXIO; - - /* - * Start watchdog. - */ - if (!hppwstart) { - hppwstart++; - timeout(hppwatch, 0, hz); - } - hpp = &hppsoftc[unit]; - ns->sc_if.if_flags |= IFF_UP; - - s = splimp(); - - /* Reset the 8390 and HP chip. */ - option_reg = inw(ioaddr + HPP_OPTION); - outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) ); - IO_DELAY; IO_DELAY; - - /* Unreset the board and enable interrupts. */ - outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset)); - - /* Set the wrap registers for programmed-I/O operation. */ - outw( ioaddr + HP_PAGING, HW_Page ); - outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8) ); - - /* Select the operational page. */ - outw( ioaddr + HP_PAGING, Perf_Page ); - nsinit(ns); - - splx(s); - - return (0); -} - -/* - * needs to be called at splimp()? - * - */ -void -hpp_reset_8390(ns) - struct nssoftc *ns; -{ - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) ); - /* Pause a few cycles for the hardware reset to take place. */ - IO_DELAY; - IO_DELAY; - ns->sc_txing = 0; - outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset) ); - - /* - * XXX - I'm not sure there needs to be this many IO_DELAY's... - */ - IO_DELAY; IO_DELAY; - IO_DELAY; IO_DELAY; - - if ((inb_p(ioaddr + HPP_NIC_OFFSET + EN0_ISR) & ENISR_RESET) == 0) - printf("%s: hp_reset_8390() did not complete.\n", ns->sc_name); - - return; -} - - -/* - * Block input and output, similar to the Crynwr packet driver. - * Note that transfer with the EtherTwist+ must be on word boundaries. - */ -void -hpp_io_block_input(ns, count, buf, ring_offset) - struct nssoftc *ns; - int count; - char *buf; - int ring_offset; -{ - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - - outw(ioaddr + HPP_IN_ADDR, ring_offset); - - insw(ioaddr + HP_DATAPORT, buf, count >> 1 ); - - if (count & 0x01) - buf[count-1] = (char) inw(ioaddr + HP_DATAPORT); - -} - -void -hpp_mem_block_input(ns, count, buf, ring_offset) - struct nssoftc *ns; - int count; - char *buf; - int ring_offset; -{ - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - char *mem_start = (char *)phystokv(hppsoftc[ns->sc_unit].mem_start); - - outw(ioaddr + HPP_IN_ADDR, ring_offset); - outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb)); - - /* copy as much as we can straight through */ - bcopy16(mem_start, buf, count & ~1); - - /* Now we copy that last byte. */ - if (count & 0x01) { - u_short savebyte[2]; - - bcopy16(mem_start + (count & ~1), savebyte, 2); - buf[count-1] = savebyte[0]; - } - - outw(ioaddr + HPP_OPTION, option_reg); -} - - -/* - * output data into NIC buffers. - * - * NOTE: All transfers must be on word boundaries. - */ -int -hpp_io_block_output(ns, count, buf, start_page) - struct nssoftc *ns; - int count; - char *buf; - int start_page; -{ - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - - outw(ioaddr + HPP_OUT_ADDR, start_page << 8) ; - - if (count > 1) { - outsw(ioaddr + HP_DATAPORT, buf, count >> 1); - } - - if ( (count & 1) == 1 ) { - u_char savebyte[2]; - - savebyte[1] = 0; - savebyte[0] = buf[count - 1]; - outw(ioaddr + HP_DATAPORT, *(u_short *)savebyte); - } - - if (count < (ETHERMIN + sizeof( struct ether_header ))) - count = ETHERMIN + sizeof( struct ether_header ); - - - return (count) ; -} - - -/* XXX - * - * I take great pains to not try and bcopy past the end of the buffer, - * does this matter? Are the io request buffers the exact byte size? - */ -int -hpp_mem_block_output(ns, count, buf, start_page ) - struct nssoftc *ns; - int count; - char *buf; - int start_page; -{ - int ioaddr = ns->sc_port - HPP_NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - struct hppsoftc *hpp = &hppsoftc[ns->sc_unit]; - char *shmem; - - outw(ioaddr + HPP_OUT_ADDR, start_page << 8); - outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb)); - - shmem = (char *)phystokv(hpp->mem_start); - bcopy16(buf, shmem, count & ~1); - - if ( (count & 1) == 1 ) { - u_char savebyte[2]; - - savebyte[1] = 0; - savebyte[0] = buf[count - 1]; - bcopy16(savebyte, shmem + (count & ~1), 2); - } - - while (count < ETHERMIN + sizeof(struct ether_header)) { - *(shmem + count) = 0; - count++; - } - - outw(ioaddr + HPP_OPTION, option_reg); - - return count; -} - - -int -hppintr(unit) - int unit; -{ - nsintr(&hppnssoftc[unit]); - - return(0); -} - -void -hppstart(unit) - int unit; -{ - nsstart(&hppnssoftc[unit]); -} - -int hppoutput(); - -int -hppoutput(dev, ior) - dev_t dev; - io_req_t ior; -{ - int unit = minor(dev); - struct bus_device *ui; - - if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_write(&hppnssoftc[unit].sc_if, hppstart, ior)); -} - - -int -hppsetinput(dev, receive_port, priority, filter, filter_count) - dev_t dev; - mach_port_t receive_port; - int priority; - filter_t *filter; - unsigned filter_count; -{ - int unit = minor(dev); - struct bus_device *ui; - - if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_set_filter(&hppnssoftc[unit].sc_if, receive_port, - priority, filter, filter_count)); -} - - -int -hppgetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned *count; -{ - int unit = minor(dev); - struct bus_device *ui; - - if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_getstat(&hppnssoftc[unit].sc_if, flavor, status, count)); -} - - -int -hppsetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned count; -{ - int unit = minor(dev), oflags, s; - struct bus_device *ui; - struct ifnet *ifp; - struct net_status *ns; - - if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - ifp = &hppnssoftc[unit].sc_if; - - switch (flavor) { - - case NET_STATUS: - if (count < NET_STATUS_COUNT) - return (D_INVALID_SIZE); - ns = (struct net_status *)status; - oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC); - if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) { - s = splimp(); - nsinit(&hppnssoftc[unit]); - splx(s); - } - break; - - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); -} - -/* - * Watchdog. - * Check for hung transmissions. - */ -void -hppwatch() -{ - int unit, s; - struct nssoftc *ns; - - timeout(hppwatch, 0, hz); - - s = splimp(); - for (unit = 0; unit < NHPP; unit++) { - if (hpp_info[unit] == 0 || hpp_info[unit]->alive == 0) - continue; - ns = &hppnssoftc[unit]; - if (ns->sc_timer && --ns->sc_timer == 0) { - printf("hpp%d: transmission timeout\n", unit); - (*ns->sc_reset)(ns); - nsinit(ns); - } - } - splx(s); -} - - -#endif /* NHPP > 0 */ - - diff --git a/i386/i386at/gpl/if_ns.c b/i386/i386at/gpl/if_ns.c deleted file mode 100644 index da629cb..0000000 --- a/i386/i386at/gpl/if_ns.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright (c) 1994 Shantanu Goel - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - */ - -/* - * Written 1992,1993 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. This software may be used and - * distributed according to the terms of the GNU Public License, - * incorporated herein by reference. - * - * The Author may be reached as becker@super.org or - * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - */ - -#include <ul.h> -#include <wd.h> -#include <hpp.h> -#if NUL > 0 || NWD > 0 || NHPP > 0 -/* - * Generic NS8390 routines. - * Derived from the Linux driver by Donald Becker. - * - * Shantanu Goel (goel@cs.columbia.edu) - */ -#include <sys/types.h> -#include <device/device_types.h> -#include <device/errno.h> -#include <device/io_req.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/net_status.h> -#include <device/net_io.h> -#include <chips/busses.h> -#include <i386/machspl.h> -#include <i386/pio.h> -#include <i386at/gpl/if_nsreg.h> - -#define IO_DELAY __asm__ __volatile__ ("outb %al,$0x80") -#define outb_p(p, v) { outb(p, v); IO_DELAY; } -#define inb_p(p) ({ unsigned char _v; _v = inb(p); IO_DELAY; _v; }) - -#define NSDEBUG -#ifdef NSDEBUG -int nsdebug = 0; -#define DEBUGF(stmt) { if (nsdebug) stmt; } -#else -#define DEBUGF(stmt) -#endif - -void nsxint(struct nssoftc *); -void nsrint(struct nssoftc *); -void nsxmit(struct nssoftc *, unsigned, int); -void nsrxoverrun(struct nssoftc *); - -/* - * Initialize the NIC. - * Must be called at splimp(). - */ -void -nsinit(sc) - struct nssoftc *sc; -{ - int port = sc->sc_port, i, rxconfig; - int endcfg = sc->sc_word16 ? (0x48 | ENDCFG_WTS) : 0x48; - struct ifnet *ifp = &sc->sc_if; - - /* - * Reset the board. - */ - (*sc->sc_reset)(sc); - - sc->sc_oactive = 0; - sc->sc_txing = 0; - sc->sc_timer = 0; - sc->sc_tx1 = sc->sc_tx2 = 0; - sc->sc_curpg = sc->sc_rxstrtpg; - - /* - * Follow National Semiconductor's recommendations for - * initializing the DP83902. - */ - outb_p(port, E8390_NODMA+E8390_PAGE0+E8390_STOP); /* 0x21 */ - outb_p(port + EN0_DCFG, endcfg); /* 0x48 or 0x49 */ - - /* - * Clear remote byte count registers. - */ - outb_p(port + EN0_RCNTLO, 0); - outb_p(port + EN0_RCNTHI, 0); - - /* - * Set to monitor and loopback mode -- this is vital! - */ - outb_p(port + EN0_RXCR, E8390_RXOFF); /* 0x20 */ - outb_p(port + EN0_TXCR, E8390_TXOFF); /* 0x02 */ - - /* - * Set transmit page and receive ring. - */ - outb_p(port + EN0_TPSR, sc->sc_txstrtpg); - outb_p(port + EN0_STARTPG, sc->sc_rxstrtpg); - outb_p(port + EN0_BOUNDARY, sc->sc_stoppg - 1); - outb_p(port + EN0_STOPPG, sc->sc_stoppg); - - /* - * Clear pending interrupts and mask. - */ - outb_p(port + EN0_ISR, 0xff); - - /* - * Enable the following interrupts: receive/transmit complete, - * receive/transmit error, and Receiver OverWrite. - * - * Counter overflow and Remote DMA complete are *not* enabled. - */ - outb_p(port + EN0_IMR, ENISR_RX | ENISR_TX | ENISR_RX_ERR | - ENISR_TX_ERR | ENISR_OVER ); - - /* - * Copy station address into 8390 registers. - */ - outb_p(port, E8390_NODMA + E8390_PAGE1 + E8390_STOP); /* 0x61 */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - outb_p(port + EN1_PHYS + i, sc->sc_addr[i]); - - /* - * Set up to accept all multicast packets. - */ - for (i = 0; i < 8; i++) - outb_p(port + EN1_MULT + i, 0xff); - - /* - * Initialize CURRent pointer - */ - outb_p(port + EN1_CURPAG, sc->sc_rxstrtpg); - - /* - * Program command register for page 0. - */ - outb_p(port, E8390_NODMA + E8390_PAGE0 + E8390_STOP); - -#if 0 - outb_p(port + EN0_ISR, 0xff); - outb_p(port + EN0_IMR, ENISR_ALL); -#endif - - outb_p(port + E8390_CMD, E8390_NODMA + E8390_PAGE0 + E8390_START); - outb_p(port + EN0_TXCR, E8390_TXCONFIG); /* xmit on */ - - /* 3c503 TechMan says rxconfig only after the NIC is started. */ - rxconfig = E8390_RXCONFIG; - if (ifp->if_flags & IFF_ALLMULTI) - rxconfig |= 0x08; - if (ifp->if_flags & IFF_PROMISC) - rxconfig |= 0x10; - outb_p(port + EN0_RXCR, rxconfig); /* rx on */ - - /* - * Mark interface as up and start output. - */ - ifp->if_flags |= IFF_RUNNING; - nsstart(sc); -} - -/* - * Start output on interface. - * Must be called at splimp(). - */ -void -nsstart(sc) - struct nssoftc *sc; -{ - io_req_t ior; - struct ifnet *ifp = &sc->sc_if; - - /* - * Drop packets if interface is down. - */ - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - while (1) { - IF_DEQUEUE(&ifp->if_snd, ior); - if (ior == 0) - return; - iodone(ior); - } - } - /* - * If transmitter is busy, bail out. - */ - if (sc->sc_oactive) - return; - - /* - * Dequeue a packet. - */ - IF_DEQUEUE(&ifp->if_snd, ior); - if (ior == 0) - return; - - /* Mask interrupts from the ethercard. */ - outb( sc->sc_port + EN0_IMR, 0x00); - - if (sc->sc_pingpong) { - int count, output_page; - - if (sc->sc_tx1 == 0) { - output_page = sc->sc_txstrtpg; - sc->sc_tx1 = count = (*sc->sc_output)(sc, - ior->io_count, - ior->io_data, - sc->sc_txstrtpg); - } else if (sc->sc_tx2 == 0) { - output_page = sc->sc_txstrtpg + 6; - sc->sc_tx2 = count = (*sc->sc_output)(sc, - ior->io_count, - ior->io_data, - output_page); - } else { - sc->sc_oactive = 1; - IF_PREPEND(&ifp->if_snd, ior); - return; - } - - DEBUGF({ - struct ether_header *eh; - - eh = (struct ether_header *)ior->io_data; - printf("send: %s%d: %x:%x:%x:%x:%x:%x, " - "olen %d, len %d\n", - sc->sc_name, sc->sc_unit, - eh->ether_dhost[0], eh->ether_dhost[1], - eh->ether_dhost[2], eh->ether_dhost[3], - eh->ether_dhost[4], eh->ether_dhost[5], - ior->io_count, count); - }); - - if (!sc->sc_txing) { - nsxmit(sc, count, output_page); - if (output_page == sc->sc_txstrtpg) - sc->sc_tx1 = -1, sc->sc_lasttx = -1; - else - sc->sc_tx2 = -1, sc->sc_lasttx = -2; - } - sc->sc_oactive = (sc->sc_tx1 && sc->sc_tx2); - } else { - int count; - - count = (*sc->sc_output)(sc, ior->io_count, - ior->io_data, sc->sc_txstrtpg); - - DEBUGF({ - struct ether_header *eh; - - eh = (struct ether_header *)ior->io_data; - printf("send: %s%d: %x:%x:%x:%x:%x:%x, " - "olen %d, len %d\n", - sc->sc_name, sc->sc_unit, - eh->ether_dhost[0], eh->ether_dhost[1], - eh->ether_dhost[2], eh->ether_dhost[3], - eh->ether_dhost[4], eh->ether_dhost[5], - ior->io_count, count); - }); - - nsxmit(sc, count, sc->sc_txstrtpg); - sc->sc_oactive = 1; - } - - /* reenable 8390 interrupts. */ - outb_p(sc->sc_port + EN0_IMR, ENISR_ALL); - - iodone(ior); -} - -/* - * Interrupt routine. - * Called by board level driver. - */ -void -nsintr(sc) - struct nssoftc *sc; -{ - int port = sc->sc_port; - int interrupts, boguscount = 0; - struct ifnet *ifp = &sc->sc_if; - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - DEBUGF(printf("nsintr: %s%d: interface down\n", - sc->sc_name, sc->sc_unit)); - return; - } - - /* - * Change to page 0 and read intr status reg. - */ - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0); - - while ((interrupts = inb_p(port + EN0_ISR)) != 0 && ++boguscount < 9) { - if (interrupts & ENISR_RDC) { - /* - * Ack meaningless DMA complete. - */ - outb_p(port + EN0_ISR, ENISR_RDC); - } - - if (interrupts & ENISR_OVER) - nsrxoverrun(sc); - else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { - nsrint(sc); - } - - if (interrupts & ENISR_TX) { - nsxint(sc); - } - else if (interrupts & ENISR_COUNTERS) { - /* - * XXX - We really should be storing statistics - * about the interface. For now we just drop them. - */ - - /* reading resets the counters! */ - (void) inb_p(port + EN0_COUNTER0); /* frame */ - (void) inb_p(port + EN0_COUNTER1); /* crc */ - (void) inb_p(port + EN0_COUNTER2); /* miss */ - - DEBUGF(printf("%s%d: acked counter interrupt.\n", - sc->sc_name, sc->sc_unit)); - - outb_p(port + EN0_ISR, ENISR_COUNTERS); /* ack intr */ - } - - if (interrupts & ENISR_TX_ERR) { - DEBUGF(printf("acking transmit error\n")); - outb_p(port + EN0_ISR, ENISR_TX_ERR); /* ack intr */ - } - - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START); - } - - DEBUGF({ - if (interrupts) { - printf("%s%d: unknown interrupt 0x%x", - sc->sc_name, sc->sc_unit, interrupts); - outb_p(port + E8390_CMD, - E8390_NODMA+E8390_PAGE0+E8390_START); - outb_p(port + EN0_ISR, 0xff); /* ack all intrs */ - } - }) -} - -/* - * Process a transmit interrupt. - */ -void -nsxint(sc) - struct nssoftc *sc; -{ - int port = sc->sc_port, status; - struct ifnet *ifp = &sc->sc_if; - - status = inb(port + EN0_TSR); - outb_p(port + EN0_ISR, ENISR_TX); /* ack intr */ - - sc->sc_txing = 0; - sc->sc_timer = 0; - sc->sc_oactive = 0; - - if (sc->sc_pingpong) { - if (sc->sc_tx1 < 0) { - if (sc->sc_lasttx != 1 && sc->sc_lasttx != -1) - printf("%s%d: bogus last_tx_buffer %d," - "tx1 = %d\n", - sc->sc_name, sc->sc_unit, - sc->sc_lasttx, sc->sc_tx1); - sc->sc_tx1 = 0; - if (sc->sc_tx2 > 0) { - nsxmit(sc, sc->sc_tx2, sc->sc_txstrtpg + 6); - sc->sc_tx2 = -1; - sc->sc_lasttx = 2; - } else - sc->sc_lasttx = 20; - } else if (sc->sc_tx2 < 0) { - if (sc->sc_lasttx != 2 && sc->sc_lasttx != -2) - printf("%s%d: bogus last_tx_buffer %d," - "tx2 = %d\n", - sc->sc_name, sc->sc_unit, - sc->sc_lasttx, sc->sc_tx2); - sc->sc_tx2 = 0; - if (sc->sc_tx1 > 0) { - nsxmit(sc, sc->sc_tx1, sc->sc_txstrtpg); - sc->sc_tx1 = -1; - sc->sc_lasttx = 1; - } else - sc->sc_lasttx = 10; - } else - printf("%s%d: unexpected TX-done interrupt, " - "lasttx = %d\n", - sc->sc_name, sc->sc_unit, sc->sc_lasttx); - } - /* - * Update stats. - */ - if (status & ENTSR_COL) { - if (status & ENTSR_ABT) - ifp->if_collisions += 16; - else - ifp->if_collisions += inb(port + EN0_NCR); - } - if (status & ENTSR_PTX) { - DEBUGF(printf("sent: %s%d\n", sc->sc_name, sc->sc_unit)); - ifp->if_opackets++; - } else - ifp->if_oerrors++; - - /* - * Start output on interface. - */ - nsstart(sc); -} - -/* - * Process a receive interrupt. - */ -void -nsrint(sc) - struct nssoftc *sc; -{ - int port = sc->sc_port; - int rxing_page, this_frame, next_frame, current_offset; - int rx_pkt_count = 0; - int num_rx_pages = sc->sc_stoppg - sc->sc_rxstrtpg; - struct nspkthdr rx_frame; - struct ifnet *ifp = &sc->sc_if; - - while (++rx_pkt_count < 10) { - int pkt_len; - - /* - * Get the rx page (incoming packet pointer). - */ - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE1); - rxing_page = inb_p(port + EN1_CURPAG); - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0); - - /* - * Remove one frame from the ring. - * Boundary is always a page behind. - */ - this_frame = inb_p(port + EN0_BOUNDARY) + 1; - if (this_frame >= sc->sc_stoppg) - this_frame = sc->sc_rxstrtpg; - - DEBUGF({ - if (this_frame != sc->sc_curpg) - printf("%s%d: mismatched read page pointers " - "%x vs %x\n", - sc->sc_name, sc->sc_unit, - this_frame, sc->sc_curpg); - }); - - if (this_frame == rxing_page) { - DEBUGF(printf("this_frame = rxing_page!\n")); - break; - } - - current_offset = this_frame << 8; - (*sc->sc_input)(sc, sizeof(rx_frame), (char *)&rx_frame, - current_offset); - - pkt_len = rx_frame.count - sizeof(rx_frame); - - next_frame = this_frame + 1 + ((pkt_len + 4) >> 8); - - if (rx_frame.next != next_frame - && rx_frame.next != next_frame + 1 - && rx_frame.next != next_frame - num_rx_pages - && rx_frame.next != next_frame + 1 - num_rx_pages) { - sc->sc_curpg = rxing_page; - outb(port + EN0_BOUNDARY, sc->sc_curpg - 1); - ifp->if_ierrors++; - DEBUGF(printf("INPUT ERROR?\n")); - continue; - } - if (pkt_len < 60 || pkt_len > 1518) { - ifp->if_ierrors++; - DEBUGF(printf("%s%d: bad packet length %d\n", - sc->sc_name, sc->sc_unit, pkt_len)); - } else if ((rx_frame.status & 0x0f) == ENRSR_RXOK) { - ipc_kmsg_t kmsg; - - kmsg = net_kmsg_get(); - if (kmsg == 0) { - DEBUGF(printf("%s%d: dropped packet\n", - sc->sc_name, sc->sc_unit)); - ifp->if_rcvdrops++; - } else { - int len, off; - struct ether_header *eh; - struct packet_header *pkt; - - ifp->if_ipackets++; - off = current_offset + sizeof(rx_frame); - eh = ((struct ether_header *) - (&net_kmsg(kmsg)->header[0])); - (*sc->sc_input)(sc, - sizeof(struct ether_header), - (char *)eh, off); - off += sizeof(struct ether_header); - len = pkt_len - sizeof(struct ether_header); - - DEBUGF(printf("rcv: %s%d: %x:%x:%x:%x:%x:%x, " - "len %d, type 0x%x\n", - sc->sc_name, sc->sc_unit, - eh->ether_shost[0], - eh->ether_shost[1], - eh->ether_shost[2], - eh->ether_shost[3], - eh->ether_shost[4], - eh->ether_shost[5], - len, eh->ether_type)); - - pkt = ((struct packet_header *) - (&net_kmsg(kmsg)->packet[0])); - (*sc->sc_input)(sc, len, (char *)(pkt+1), off); - pkt->type = eh->ether_type; - pkt->length = len+sizeof(struct packet_header); - net_packet(ifp, kmsg, pkt->length, - ethernet_priority(kmsg)); - } - } else { - DEBUGF(printf("%s%d: bogus packet: " - "status=0x%x nxpg=0x%x size=%d\n", - sc->sc_name, sc->sc_unit, - rx_frame.status, rx_frame.next, - rx_frame.count)); - ifp->if_ierrors++; - } - next_frame = rx_frame.next; - if (next_frame >= sc->sc_stoppg) { - DEBUGF(printf("%s%d: next frame inconsistency, 0x%x\n", - sc->sc_name, sc->sc_unit, next_frame)); - next_frame = sc->sc_rxstrtpg; - } - sc->sc_curpg = next_frame; - outb(port + EN0_BOUNDARY, next_frame - 1); - } - - /* - * Bug alert! Reset ENISR_OVER to avoid spurious overruns! - */ - outb_p(port + EN0_ISR, ENISR_RX+ENISR_RX_ERR+ENISR_OVER); -} - -/* - * Handle a receive overrun condition. - * - * XXX - this needs to be gone over in light of the NS documentation. - */ -void -nsrxoverrun(sc) - struct nssoftc *sc; -{ - int port = sc->sc_port, i; - extern unsigned delaycount; - - printf("%s%d: receive overrun\n", sc->sc_name, sc->sc_unit); - - /* - * We should already be stopped and in page0, but just to be sure... - */ - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_STOP); - - /* - * Clear remote byte counter registers. - */ - outb_p(port + EN0_RCNTLO, 0); - outb_p(port + EN0_RCNTHI, 0); - - /* - * Wait for reset to complete. - */ - for (i = delaycount*2; i && !(inb_p(port+EN0_ISR) & ENISR_RESET); i--) - ; - if (i == 0) { - printf("%s%d: reset did not complete at overrun\n", - sc->sc_name, sc->sc_unit); - nsinit(sc); - return; - } - /* - * Disable transmitter. - */ - outb_p(port + EN0_TXCR, E8390_TXOFF); - - /* - * Remove packets. - */ - nsrint(sc); - - outb_p(port + EN0_ISR, 0xff); - outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START); - outb_p(port + EN0_TXCR, E8390_TXCONFIG); -} - -/* - * Trigger a transmit start. - */ -void -nsxmit(sc, length, start_page) - struct nssoftc *sc; - unsigned length; - int start_page; -{ - int port = sc->sc_port; - - sc->sc_txing = 1; - outb_p(port, E8390_NODMA+E8390_PAGE0); - if (inb_p(port) & E8390_TRANS) { - printf("%s%d: nsxmit() called with the transmitter busy\n", - sc->sc_name, sc->sc_unit); - return; - } - outb_p(port + EN0_TCNTLO, length & 0xff); - outb_p(port + EN0_TCNTHI, (length >> 8) & 0xff); - outb_p(port + EN0_TPSR, start_page); - outb_p(port, E8390_NODMA+E8390_TRANS+E8390_START); - sc->sc_timer = 4; -} - -#endif /* NUL > 0 || NWD > 0 */ diff --git a/i386/i386at/gpl/if_nsreg.h b/i386/i386at/gpl/if_nsreg.h deleted file mode 100644 index 8944797..0000000 --- a/i386/i386at/gpl/if_nsreg.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 1994 Shantanu Goel - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - */ - -/* - * Written 1992,1993 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. This software may be used and - * distributed according to the terms of the GNU Public License, - * incorporated herein by reference. - * - * The Author may be reached as becker@super.org or - * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - */ - -/* - * Generic NS8390 definitions. - * Derived from the Linux driver by Donald Becker. - */ - -#define ETHER_ADDR_LEN 6 - -/* - * 8390 state. - */ -struct nssoftc { - struct ifnet sc_if; /* interface header */ - u_char sc_addr[ETHER_ADDR_LEN]; /* station address */ - /* - * The following are board specific. - * reset() - resets the NIC and board - * input() - read data into buffer from supplied offset - * output() - write data from buffer into supplied page - * the data is padded if necessary and the actual - * count is returned. - */ - void (*sc_reset)(struct nssoftc *); - void (*sc_input)(struct nssoftc *, int, char *, int); - int (*sc_output)(struct nssoftc *, int, char *, int); - int sc_word16:1; /* 16 bit (vs 8 bit) board */ - int sc_txing:1; /* transmit active */ - int sc_pingpong:1; /* using ping-pong driver */ - int sc_oactive:1; /* transmitter is active */ - u_char sc_txstrtpg; /* starting transmit page */ - u_char sc_rxstrtpg; /* starting receive page */ - u_char sc_stoppg; /* stop page */ - u_char sc_curpg; /* current page */ - short sc_tx1; /* packet lengths for ping-pong transmit */ - short sc_tx2; - short sc_lasttx; - u_char sc_timer; /* watchdog */ - int sc_port; /* I/O port of 8390 */ - char *sc_name; /* name of board */ - int sc_unit; /* unit in driver */ -}; - -#define TX_2X_PAGES 12 -#define TX_1X_PAGES 6 -#define TX_PAGES(ns) ((ns)->sc_pingpong ? TX_2X_PAGES : TX_1X_PAGES) - -/* Some generic ethernet register configurations. */ -#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ -#define E8390_RX_IRQ_MASK 0x5 -#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ -#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ -#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ -#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ - -/* Register accessed at EN_CMD, the 8390 base addr. */ -#define E8390_STOP 0x01 /* Stop and reset the chip */ -#define E8390_START 0x02 /* Start the chip, clear reset */ -#define E8390_TRANS 0x04 /* Transmit a frame */ -#define E8390_RREAD 0x08 /* Remote read */ -#define E8390_RWRITE 0x10 /* Remote write */ -#define E8390_NODMA 0x20 /* Remote DMA */ -#define E8390_PAGE0 0x00 /* Select page chip registers */ -#define E8390_PAGE1 0x40 /* using the two high-order bits */ -#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ - -#define E8390_CMD 0x00 /* The command register (for all pages) */ -/* Page 0 register offsets. */ -#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ -#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ -#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ -#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ -#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ -#define EN0_TSR 0x04 /* Transmit status reg RD */ -#define EN0_TPSR 0x04 /* Transmit starting page WR */ -#define EN0_NCR 0x05 /* Number of collision reg RD */ -#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ -#define EN0_FIFO 0x06 /* FIFO RD */ -#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ -#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ -#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ -#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ -#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ -#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ -#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ -#define EN0_RSR 0x0c /* rx status reg RD */ -#define EN0_RXCR 0x0c /* RX configuration reg WR */ -#define EN0_TXCR 0x0d /* TX configuration reg WR */ -#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ -#define EN0_DCFG 0x0e /* Data configuration reg WR */ -#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ -#define EN0_IMR 0x0f /* Interrupt mask reg WR */ -#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ - -/* Bits in EN0_ISR - Interrupt status register */ -#define ENISR_RX 0x01 /* Receiver, no error */ -#define ENISR_TX 0x02 /* Transmitter, no error */ -#define ENISR_RX_ERR 0x04 /* Receiver, with error */ -#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ -#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ -#define ENISR_COUNTERS 0x20 /* Counters need emptying */ -#define ENISR_RDC 0x40 /* remote dma complete */ -#define ENISR_RESET 0x80 /* Reset completed */ -#define ENISR_ALL 0x3f /* Interrupts we will enable */ - -/* Bits in EN0_DCFG - Data config register */ -#define ENDCFG_WTS 0x01 /* word transfer mode selection */ - -/* Page 1 register offsets. */ -#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ -#define EN1_CURPAG 0x07 /* Current memory page RD WR */ -#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ - -/* Bits in received packet status byte and EN0_RSR*/ -#define ENRSR_RXOK 0x01 /* Received a good packet */ -#define ENRSR_CRC 0x02 /* CRC error */ -#define ENRSR_FAE 0x04 /* frame alignment error */ -#define ENRSR_FO 0x08 /* FIFO overrun */ -#define ENRSR_MPA 0x10 /* missed pkt */ -#define ENRSR_PHY 0x20 /* physical/multicase address */ -#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ -#define ENRSR_DEF 0x80 /* deferring */ - -/* Transmitted packet status, EN0_TSR. */ -#define ENTSR_PTX 0x01 /* Packet transmitted without error */ -#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ -#define ENTSR_COL 0x04 /* The transmit collided at least once. */ -#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ -#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ -#define ENTSR_FU 0x20 /* A "FIFO underrun" occured during transmit. */ -#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ -#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ - -/* The per-packet-header format. */ -struct nspkthdr { - u_char status; /* status */ - u_char next; /* pointer to next packet. */ - u_short count; /* header + packet length in bytes */ -}; - -void nsinit(struct nssoftc *); -void nsstart(struct nssoftc *); -void nsintr(struct nssoftc *); diff --git a/i386/i386at/gpl/if_ul.c b/i386/i386at/gpl/if_ul.c deleted file mode 100644 index 59e74f5..0000000 --- a/i386/i386at/gpl/if_ul.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (c) 1994 Shantanu Goel - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - */ - -/* - * Written 1993 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. This software may be used and - * distributed according to the terms of the GNU Public License, - * incorporated herein by reference. - * - * The Author may be reached as becker@super.org or - * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - */ - -#include <wd.h> -#include <ul.h> -#if NUL > 0 -/* - * Driver for SMC Ultra ethernet adaptor. - * Derived from the Linux driver by Donald Becker. - * - * Shantanu Goel (goel@cs.columbia.edu) - */ -#include <mach/sa/sys/types.h> -#include "vm_param.h" -#include <kern/time_out.h> -#include <device/device_types.h> -#include <device/errno.h> -#include <device/io_req.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/net_status.h> -#include <device/net_io.h> -#include <chips/busses.h> -#include <i386/machspl.h> -#include <i386/pio.h> -#include <i386at/gpl/if_nsreg.h> - -#define START_PG 0x00 /* first page of TX buffer */ -#define ULTRA_CMDREG 0 /* offset of ASIC command register */ -#define ULTRA_RESET 0x80 /* board reset in ULTRA_CMDREG */ -#define ULTRA_MEMEN 0x40 /* enable shared memory */ -#define ULTRA_NIC_OFF 16 /* NIC register offset */ - -#define ulunit(dev) minor(dev) - -/* - * Autoconfiguration stuff. - */ -int ulprobe(); -void ulattach(); -int ulstd[] = { 0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0 }; -struct bus_device *ulinfo[NUL]; -struct bus_driver uldriver = { - ulprobe, 0, ulattach, 0, ulstd, "ul", ulinfo, 0, 0, 0 -}; - -/* - * NS8390 state. - */ -struct nssoftc ulnssoftc[NUL]; - -/* - * Ultra state. - */ -struct ulsoftc { - int sc_mstart; /* start of board's RAM */ - int sc_mend; /* end of board's RAM */ - int sc_rmstart; /* start of receive RAM */ - int sc_rmend; /* end of receive RAM */ -} ulsoftc[NUL]; - -void ulstart(int); -void ul_reset(struct nssoftc *sc); -void ul_input(struct nssoftc *sc, int, char *, int); -int ul_output(struct nssoftc *sc, int, char *, int); - -/* - * Watchdog. - */ -int ulwstart = 0; -void ulwatch(void); - -#define ULDEBUG -#ifdef ULDEBUG -int uldebug = 0; -#define DEBUGF(stmt) { if (uldebug) stmt; } -#else -#define DEBUGF(stmt) -#endif - -/* - * Probe for the Ultra. - * This looks like an 8013 with the station address PROM - * at I/O ports <base>+8 to <base>+13, with a checksum following. - */ -int -ulprobe(xxx, ui) - int xxx; - struct bus_device *ui; -{ - int *port; - - if (ui->unit >= NUL) { - printf("ul%d: not configured\n", ui->unit); - return (0); - } - for (port = ulstd; *port; port++) { - if (*port < 0) - continue; - /* - * Check chip ID nibble. - */ - if ((inb(*port + 7) & 0xf0) != 0x20) - continue; - if (ulprobe1(*port, ui)) { - ui->address = *port; - *port = -1; -#if NWD > 0 - /* - * XXX: The Western Digital/SMC driver can sometimes - * probe the Ultra incorrectly. Remove the Ultra's - * port from it's list to avoid the problem. - */ - { - int i; - extern int wdstd[]; - - for (i = 0; wdstd[i]; i++) { - if (wdstd[i] == ui->address) { - wdstd[i] = -1; - break; - } - } - } -#endif - return (1); - } - } - return (0); -} - -int -ulprobe1(port, ui) - int port; - struct bus_device *ui; -{ - u_char num_pages, irqreg, addr, reg4; - u_char irqmap[] = { 0, 9, 3, 5, 7, 10, 11, 15 }; - short num_pages_tbl[4] = { 0x20, 0x40, 0x80, 0xff }; - int i, irq, checksum = 0; - int addr_tbl[4] = { 0x0c0000, 0x0e0000, 0xfc0000, 0xfe0000 }; - struct ulsoftc *ul = &ulsoftc[ui->unit]; - struct nssoftc *ns = &ulnssoftc[ui->unit]; - struct ifnet *ifp = &ns->sc_if; - - /* - * Select the station address register set. - */ - reg4 = inb(port + 4) & 0x7f; - outb(port + 4, reg4); - - for (i = 0; i < 8; i++) - checksum += inb(port + 8 + i); - if ((checksum & 0xff) != 0xff) - return (0); - - /* - * Use 2 transmit buffers. - */ - ns->sc_pingpong = 1; - - printf("ul%d: SMC Ultra at 0x%03x, ", ui->unit, port); - for (i = 0; i < ETHER_ADDR_LEN; i++) { - if (i == 0) - printf("%02x", ns->sc_addr[i] = inb(port + 8 + i)); - else - printf(":%02x", ns->sc_addr[i] = inb(port + 8 + i)); - } - /* - * Switch from station address to alternate register set - * and read useful registers there. - */ - outb(port + 4, 0x80 | reg4); - - /* - * Enable FINE16 mode to avoid BIOS ROM width mismatches - * during reboot. - */ - outb(port + 0x0c, 0x80 | inb(port + 0x0c)); - irqreg = inb(port + 0x0d); - addr = inb(port + 0x0b); - - /* - * Switch back to station address register set so the MSDOG - * driver can find the card after a warm boot. - */ - outb(port + 4, reg4); - - /* - * Determine IRQ. The IRQ bits are split. - */ - irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)]; - if (irq == 0) { - printf(", failed to detect IRQ line.\n"); - return (0); - } - ui->sysdep1 = irq; - take_dev_irq(ui); - printf(", irq %d", irq); - - /* - * Determine board's RAM location. - */ - ul->sc_mstart = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3]; - num_pages = num_pages_tbl[(addr >> 4) & 3]; - ul->sc_rmstart = ul->sc_mstart + TX_PAGES(ns) * 256; - ul->sc_mend = ul->sc_rmend - = ul->sc_mstart + (num_pages - START_PG) * 256; - printf(", memory 0x%05x-0x%05x\n", ul->sc_mstart, ul->sc_mend); - - /* - * Initialize 8390 state. - */ - ns->sc_name = ui->name; - ns->sc_unit = ui->unit; - ns->sc_port = port + ULTRA_NIC_OFF; - ns->sc_word16 = 1; - ns->sc_txstrtpg = START_PG; - ns->sc_rxstrtpg = START_PG + TX_PAGES(ns); - ns->sc_stoppg = num_pages; - ns->sc_reset = ul_reset; - ns->sc_input = ul_input; - ns->sc_output = ul_output; - - DEBUGF(printf("ul%d: txstrtpg %d rxstrtpg %d num_pages %d\n", - ui->unit, ns->sc_txstrtpg, ns->sc_rxstrtpg, num_pages)); - - /* - * Initialize interface header. - */ - ifp->if_unit = ui->unit; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST; - ifp->if_header_size = sizeof(struct ether_header); - ifp->if_header_format = HDR_ETHERNET; - ifp->if_address_size = ETHER_ADDR_LEN; - ifp->if_address = ns->sc_addr; - if_init_queues(ifp); - - return (1); -} - -void -ulattach(ui) - struct bus_device *ui; -{ - /* - * void - */ -} - -int -ulopen(dev, flag) - dev_t dev; - int flag; -{ - int unit = ulunit(dev), s; - struct bus_device *ui; - - if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - /* - * Start watchdog. - */ - if (!ulwstart) { - ulwstart++; - timeout(ulwatch, 0, hz); - } - ulnssoftc[unit].sc_if.if_flags |= IFF_UP; - s = splimp(); - outb(ui->address, ULTRA_MEMEN); /* enable memory, 16 bit mode */ - outb(ui->address + 5, 0x80); - outb(ui->address + 6, 0x01); /* enable interrupts and memory */ - nsinit(&ulnssoftc[unit]); - splx(s); - return (0); -} - -int -uloutput(dev, ior) - dev_t dev; - io_req_t ior; -{ - int unit = ulunit(dev); - struct bus_device *ui; - - if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_write(&ulnssoftc[unit].sc_if, ulstart, ior)); -} - -int -ulsetinput(dev, receive_port, priority, filter, filter_count) - dev_t dev; - mach_port_t receive_port; - int priority; - filter_t *filter; - unsigned filter_count; -{ - int unit = ulunit(dev); - struct bus_device *ui; - - if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_set_filter(&ulnssoftc[unit].sc_if, receive_port, - priority, filter, filter_count)); -} - -int -ulgetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned *count; -{ - int unit = ulunit(dev); - struct bus_device *ui; - - if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_getstat(&ulnssoftc[unit].sc_if, flavor, status, count)); -} - -int -ulsetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned count; -{ - int unit = ulunit(dev), oflags, s; - struct bus_device *ui; - struct ifnet *ifp; - struct net_status *ns; - - if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - ifp = &ulnssoftc[unit].sc_if; - - switch (flavor) { - - case NET_STATUS: - if (count < NET_STATUS_COUNT) - return (D_INVALID_SIZE); - ns = (struct net_status *)status; - oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC); - if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) { - s = splimp(); - nsinit(&ulnssoftc[unit]); - splx(s); - } - break; - - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); -} - -void -ulintr(unit) - int unit; -{ - nsintr(&ulnssoftc[unit]); -} - -void -ulstart(unit) - int unit; -{ - nsstart(&ulnssoftc[unit]); -} - -void -ul_reset(ns) - struct nssoftc *ns; -{ - int port = ns->sc_port - ULTRA_NIC_OFF; /* ASIC base address */ - - outb(port, ULTRA_RESET); - outb(0x80, 0); /* I/O delay */ - outb(port, ULTRA_MEMEN); -} - -void -ul_input(ns, count, buf, ring_offset) - struct nssoftc *ns; - int count; - char *buf; - int ring_offset; -{ - int xfer_start; - struct ulsoftc *ul = &ulsoftc[ns->sc_unit]; - - DEBUGF(printf("ul%d: ring_offset = %d\n", ns->sc_unit, ring_offset)); - - xfer_start = ul->sc_mstart + ring_offset - (START_PG << 8); - if (xfer_start + count > ul->sc_rmend) { - int semi_count = ul->sc_rmend - xfer_start; - - /* - * Input move must be wrapped. - */ - bcopy((char *)phystokv(xfer_start), buf, semi_count); - count -= semi_count; - bcopy((char *)phystokv(ul->sc_rmstart), buf+semi_count, count); - } else - bcopy((char *)phystokv(xfer_start), buf, count); -} - -int -ul_output(ns, count, buf, start_page) - struct nssoftc *ns; - int count; - char *buf; - int start_page; -{ - char *shmem; - int i; - struct ulsoftc *ul = &ulsoftc[ns->sc_unit]; - - DEBUGF(printf("ul%d: start_page = %d\n", ns->sc_unit, start_page)); - - shmem = (char *)phystokv(ul->sc_mstart + ((start_page-START_PG) << 8)); - bcopy(buf, shmem, count); - while (count < ETHERMIN + sizeof(struct ether_header)) { - *(shmem + count) = 0; - count++; - } - return (count); -} - -/* - * Watchdog. - * Check for hung transmissions. - */ -void -ulwatch() -{ - int unit, s; - struct nssoftc *ns; - - timeout(ulwatch, 0, hz); - - s = splimp(); - for (unit = 0; unit < NUL; unit++) { - if (ulinfo[unit] == 0 || ulinfo[unit]->alive == 0) - continue; - ns = &ulnssoftc[unit]; - if (ns->sc_timer && --ns->sc_timer == 0) { - printf("ul%d: transmission timeout\n", unit); - nsinit(ns); - } - } - splx(s); -} - -#endif /* NUL > 0 */ diff --git a/i386/i386at/gpl/if_wd.c b/i386/i386at/gpl/if_wd.c deleted file mode 100644 index c569a3e..0000000 --- a/i386/i386at/gpl/if_wd.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (c) 1994 Shantanu Goel - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - */ - -/* - * Written 1993 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. This software may be used and - * distributed according to the terms of the GNU Public License, - * incorporated herein by reference. - * - * The Author may be reached as becker@super.org or - * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - */ - -#include <wd.h> -#if NWD > 0 -/* - * Driver for SMC/Western Digital Ethernet adaptors. - * Derived from the Linux driver by Donald Becker. - * - * Shantanu Goel (goel@cs.columbia.edu) - */ -#include <mach/sa/sys/types.h> -#include "vm_param.h" -#include <kern/time_out.h> -#include <device/device_types.h> -#include <device/errno.h> -#include <device/io_req.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/net_status.h> -#include <device/net_io.h> -#include <chips/busses.h> -#include <i386/machspl.h> -#include <i386/pio.h> -#include <i386at/gpl/if_nsreg.h> - -#define WD_START_PG 0x00 /* first page of TX buffer */ -#define WD03_STOP_PG 0x20 /* last page +1 of RX ring */ -#define WD13_STOP_PG 0x40 /* last page +1 of RX ring */ - -#define WD_CMDREG 0 /* offset of ASIC command register */ -#define WD_RESET 0x80 /* board reset in WDTRA_CMDREG */ -#define WD_MEMEN 0x40 /* enable shared memory */ -#define WD_CMDREG5 5 /* offset of 16-bit-only ASIC register 5 */ -#define ISA16 0x80 /* enable 16 bit access from the ISA bus */ -#define NIC16 0x40 /* enable 16 bit access from the 8390 */ -#define WD_NIC_OFF 16 /* NIC register offset */ - -#define wdunit(dev) minor(dev) - -/* - * Autoconfiguration stuff. - */ -int wdprobe(); -void wdattach(); -int wdstd[] = { 0x300, 0x280, 0x380, 0x240, 0 }; -struct bus_device *wdinfo[NWD]; -struct bus_driver wddriver = { - wdprobe, 0, wdattach, 0, wdstd, "wd", wdinfo, 0, 0, 0 -}; - -/* - * NS8390 state. - */ -struct nssoftc wdnssoftc[NWD]; - -/* - * Board state. - */ -struct wdsoftc { - int sc_mstart; /* start of board's RAM */ - int sc_mend; /* end of board's RAM */ - int sc_rmstart; /* start of receive RAM */ - int sc_rmend; /* end of receive RAM */ - int sc_reg0; /* copy of register 0 of ASIC */ - int sc_reg5; /* copy of register 5 of ASIC */ -} wdsoftc[NWD]; - -void wdstart(int); -void wd_reset(struct nssoftc *sc); -void wd_input(struct nssoftc *sc, int, char *, int); -int wd_output(struct nssoftc *sc, int, char *, int); - -/* - * Watchdog. - */ -int wdwstart = 0; -void wdwatch(void); - -#define WDDEBUG -#ifdef WDDEBUG -int wddebug = 0; -#define DEBUGF(stmt) { if (wddebug) stmt; } -#else -#define DEBUGF(stmt) -#endif - -/* - * Probe for the WD8003 and WD8013. - * These cards have the station address PROM at I/O ports <base>+8 - * to <base>+13, with a checksum following. A Soundblaster can have - * the same checksum as a WD ethercard, so we have an extra exclusionary - * check for it. - */ -int -wdprobe(xxx, ui) - int xxx; - struct bus_device *ui; -{ - int *port; - - if (ui->unit >= NWD) { - printf("wd%d: not configured\n", ui->unit); - return (0); - } - for (port = wdstd; *port; port++) { - if (*port < 0) - continue; - if (inb(*port + 8) != 0xff - && inb(*port + 9) != 0xff - && wdprobe1(*port, ui)) { - ui->address = *port; - *port = -1; - return (1); - } - } - return (0); -} - -int -wdprobe1(port, ui) - int port; - struct bus_device *ui; -{ - - int i, irq = 0, checksum = 0, ancient = 0, word16 = 0; - struct wdsoftc *wd = &wdsoftc[ui->unit]; - struct nssoftc *ns = &wdnssoftc[ui->unit]; - struct ifnet *ifp = &ns->sc_if; - - for (i = 0; i < 8; i++) - checksum += inb(port + 8 + i); - if ((checksum & 0xff) != 0xff) - return (0); - - printf("wd%d: WD80x3 at 0x%03x, ", ui->unit, port); - for (i = 0; i < ETHER_ADDR_LEN; i++) { - if (i == 0) - printf("%02x", ns->sc_addr[i] = inb(port + 8 + i)); - else - printf(":%02x", ns->sc_addr[i] = inb(port + 8 + i)); - } - /* - * Check for PureData. - */ - if (inb(port) == 'P' && inb(port + 1) == 'D') { - u_char reg5 = inb(port + 5); - - switch (inb(port + 2)) { - - case 0x03: - case 0x05: - word16 = 0; - break; - - case 0x0a: - word16 = 1; - break; - - default: - word16 = 0; - break; - } - wd->sc_mstart = ((reg5 & 0x1c) + 0xc0) << 12; - irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1; - } else { - /* - * Check for 8 bit vs 16 bit card. - */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - if (inb(port + i) != inb(port + 8 + i)) - break; - if (i >= ETHER_ADDR_LEN) { - ancient = 1; - word16 = 0; - } else { - int tmp = inb(port + 1); - - /* - * Attempt to clear 16bit bit. - */ - outb(port + 1, tmp ^ 0x01); - if (((inb(port + 1) & 0x01) == 0x01) /* 16 bit */ - && (tmp & 0x01) == 0x01) { /* in 16 bit slot */ - int asic_reg5 = inb(port + WD_CMDREG5); - - /* - * Magic to set ASIC to word-wide mode. - */ - outb(port+WD_CMDREG5, NIC16|(asic_reg5&0x1f)); - outb(port + 1, tmp); - word16 = 1; - } else - word16 = 0; - outb(port + 1, tmp); - } - if (!ancient && (inb(port + 1) & 0x01) != (word16 & 0x01)) - printf("\nwd%d: bus width conflict, " - "%d (probe) != %d (reg report)", ui->unit, - word16 ? 16 : 8, (inb(port+1) & 0x01) ? 16 : 8); - } - /* - * Determine board's RAM location. - */ - if (wd->sc_mstart == 0) { - int reg0 = inb(port); - - if (reg0 == 0xff || reg0 == 0) - wd->sc_mstart = 0xd0000; - else { - int high_addr_bits = inb(port + WD_CMDREG5) & 0x1f; - - if (high_addr_bits == 0x1f || word16 == 0) - high_addr_bits = 0x01; - wd->sc_mstart = ((reg0&0x3f)<<13)+(high_addr_bits<<19); - } - } - /* - * Determine irq. - */ - if (irq == 0) { - int irqmap[] = { 9, 3, 5, 7, 10, 11, 15, 4 }; - int reg1 = inb(port + 1); - int reg4 = inb(port + 4); - - /* - * For old card, irq must be supplied. - */ - if (ancient || reg1 == 0xff) { - if (ui->sysdep1 == 0) { - printf("\nwd%d: must specify IRQ for card\n", - ui->unit); - return (0); - } - irq = ui->sysdep1; - } else { - DEBUGF({ - int i = ((reg4 >> 5) & 0x03) + (reg1 & 0x04); - - printf("\nwd%d: irq index %d\n", ui->unit, i); - printf("wd%d:", ui->unit); - }) - irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)]; - } - } else if (irq == 2) - irq = 9; - ui->sysdep1 = irq; - take_dev_irq(ui); - printf(", irq %d", irq); - - /* - * Initialize 8390 state. - */ - ns->sc_name = ui->name; - ns->sc_unit = ui->unit; - ns->sc_port = port + WD_NIC_OFF; - ns->sc_reset = wd_reset; - ns->sc_input = wd_input; - ns->sc_output = wd_output; - ns->sc_pingpong = 1; - ns->sc_word16 = word16; - ns->sc_txstrtpg = WD_START_PG; - ns->sc_rxstrtpg = WD_START_PG + TX_PAGES(ns); - ns->sc_stoppg = word16 ? WD13_STOP_PG : WD03_STOP_PG; - - wd->sc_rmstart = wd->sc_mstart + TX_PAGES(ns) * 256; - wd->sc_mend = wd->sc_rmend - = wd->sc_mstart + (ns->sc_stoppg - WD_START_PG) * 256; - printf(", memory 0x%05x-0x%05x", wd->sc_mstart, wd->sc_mend); - - if (word16) - printf(", 16 bit"); - printf("\n"); - - DEBUGF(printf("wd%d: txstrtpg %d rxstrtpg %d num_pages %d\n", - ui->unit, ns->sc_txstrtpg, ns->sc_rxstrtpg, - (wd->sc_mend - wd->sc_mstart) / 256)); - - /* - * Initialize interface header. - */ - ifp->if_unit = ui->unit; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST; - ifp->if_header_size = sizeof(struct ether_header); - ifp->if_header_format = HDR_ETHERNET; - ifp->if_address_size = ETHER_ADDR_LEN; - ifp->if_address = ns->sc_addr; - if_init_queues(ifp); - - return (1); -} - -void -wdattach(ui) - struct bus_device *ui; -{ - /* - * void - */ -} - -int -wdopen(dev, flag) - dev_t dev; - int flag; -{ - int unit = wdunit(dev), s; - struct bus_device *ui; - struct wdsoftc *wd; - struct nssoftc *ns; - - if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - /* - * Start watchdog. - */ - if (!wdwstart) { - wdwstart++; - timeout(wdwatch, 0, hz); - } - wd = &wdsoftc[unit]; - ns = &wdnssoftc[unit]; - ns->sc_if.if_flags |= IFF_UP; - s = splimp(); - wd->sc_reg0 = ((wd->sc_mstart >> 13) & 0x3f) | WD_MEMEN; - wd->sc_reg5 = ((wd->sc_mstart >> 19) & 0x1f) | NIC16; - if (ns->sc_word16) - outb(ui->address + WD_CMDREG5, wd->sc_reg5); - outb(ui->address, wd->sc_reg0); - nsinit(ns); - splx(s); - return (0); -} - -int -wdoutput(dev, ior) - dev_t dev; - io_req_t ior; -{ - int unit = wdunit(dev); - struct bus_device *ui; - - if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_write(&wdnssoftc[unit].sc_if, wdstart, ior)); -} - -int -wdsetinput(dev, receive_port, priority, filter, filter_count) - dev_t dev; - mach_port_t receive_port; - int priority; - filter_t *filter; - unsigned filter_count; -{ - int unit = wdunit(dev); - struct bus_device *ui; - - if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_set_filter(&wdnssoftc[unit].sc_if, receive_port, - priority, filter, filter_count)); -} - -int -wdgetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned *count; -{ - int unit = wdunit(dev); - struct bus_device *ui; - - if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - return (net_getstat(&wdnssoftc[unit].sc_if, flavor, status, count)); -} - -int -wdsetstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned count; -{ - int unit = wdunit(dev), oflags, s; - struct bus_device *ui; - struct ifnet *ifp; - struct net_status *ns; - - if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0) - return (ENXIO); - - ifp = &wdnssoftc[unit].sc_if; - - switch (flavor) { - - case NET_STATUS: - if (count < NET_STATUS_COUNT) - return (D_INVALID_SIZE); - ns = (struct net_status *)status; - oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC); - ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC); - if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) { - s = splimp(); - nsinit(&wdnssoftc[unit]); - splx(s); - } - break; - - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); -} - -void -wdintr(unit) - int unit; -{ - nsintr(&wdnssoftc[unit]); -} - -void -wdstart(unit) - int unit; -{ - nsstart(&wdnssoftc[unit]); -} - -void -wd_reset(ns) - struct nssoftc *ns; -{ - int port = ns->sc_port - WD_NIC_OFF; /* ASIC base address */ - struct wdsoftc *wd = &wdsoftc[ns->sc_unit]; - - outb(port, WD_RESET); - outb(0x80, 0); /* I/O delay */ - /* - * Set up the ASIC registers, just in case something changed them. - */ - outb(port, ((wd->sc_mstart >> 13) & 0x3f) | WD_MEMEN); - if (ns->sc_word16) - outb(port + WD_CMDREG5, NIC16 | ((wd->sc_mstart>>19) & 0x1f)); -} - -void -wd_input(ns, count, buf, ring_offset) - struct nssoftc *ns; - int count; - char *buf; - int ring_offset; -{ - int port = ns->sc_port - WD_NIC_OFF; - int xfer_start; - struct wdsoftc *wd = &wdsoftc[ns->sc_unit]; - - DEBUGF(printf("wd%d: ring_offset = %d\n", ns->sc_unit, ring_offset)); - - xfer_start = wd->sc_mstart + ring_offset - (WD_START_PG << 8); - - /* - * The NIC driver calls us 3 times. Once to read the NIC 4 byte - * header, next to read the Ethernet header and finally to read - * the actual data. We enable 16 bit mode before the NIC header - * and disable it after the packet body. - */ - if (count == 4) { - if (ns->sc_word16) - outb(port + WD_CMDREG5, ISA16 | wd->sc_reg5); - ((int *)buf)[0] = ((int *)phystokv(xfer_start))[0]; - return; - } - if (count == sizeof(struct ether_header)) { - xfer_start = (int)phystokv(xfer_start); - ((int *)buf)[0] = ((int *)xfer_start)[0]; - ((int *)buf)[1] = ((int *)xfer_start)[1]; - ((int *)buf)[2] = ((int *)xfer_start)[2]; - ((short *)(buf + 12))[0] = ((short *)(xfer_start + 12))[0]; - return; - } - if (xfer_start + count > wd->sc_rmend) { - int semi_count = wd->sc_rmend - xfer_start; - - /* - * Input move must be wrapped. - */ - bcopy((char *)phystokv(xfer_start), buf, semi_count); - count -= semi_count; - bcopy((char *)phystokv(wd->sc_rmstart),buf+semi_count,count); - } else - bcopy((char *)phystokv(xfer_start), buf, count); - if (ns->sc_word16) - outb(port + WD_CMDREG5, wd->sc_reg5); -} - -int -wd_output(ns, count, buf, start_page) - struct nssoftc *ns; - int count; - char *buf; - int start_page; -{ - char *shmem; - int i, port = ns->sc_port - WD_NIC_OFF; - struct wdsoftc *wd = &wdsoftc[ns->sc_unit]; - - DEBUGF(printf("wd%d: start_page = %d\n", ns->sc_unit, start_page)); - - shmem = (char *)phystokv(wd->sc_mstart+((start_page-WD_START_PG)<<8)); - if (ns->sc_word16) { - outb(port + WD_CMDREG5, ISA16 | wd->sc_reg5); - bcopy(buf, shmem, count); - outb(port + WD_CMDREG5, wd->sc_reg5); - } else - bcopy(buf, shmem, count); - while (count < ETHERMIN + sizeof(struct ether_header)) { - *(shmem + count) = 0; - count++; - } - return (count); -} - -/* - * Watchdog. - * Check for hung transmissions. - */ -void -wdwatch() -{ - int unit, s; - struct nssoftc *ns; - - timeout(wdwatch, 0, hz); - - s = splimp(); - for (unit = 0; unit < NWD; unit++) { - if (wdinfo[unit] == 0 || wdinfo[unit]->alive == 0) - continue; - ns = &wdnssoftc[unit]; - if (ns->sc_timer && --ns->sc_timer == 0) { - printf("wd%d: transmission timeout\n", unit); - nsinit(ns); - } - } - splx(s); -} - -#endif /* NWD > 0 */ |