diff options
Diffstat (limited to 'i386/i386at/gpl/if_ul.c')
-rw-r--r-- | i386/i386at/gpl/if_ul.c | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/i386/i386at/gpl/if_ul.c b/i386/i386at/gpl/if_ul.c deleted file mode 100644 index 59e74f55..00000000 --- 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 */ |