diff options
Diffstat (limited to 'i386/i386at/if_ns8390.c')
-rw-r--r-- | i386/i386at/if_ns8390.c | 2578 |
1 files changed, 0 insertions, 2578 deletions
diff --git a/i386/i386at/if_ns8390.c b/i386/i386at/if_ns8390.c deleted file mode 100644 index 15c9440..0000000 --- a/i386/i386at/if_ns8390.c +++ /dev/null @@ -1,2578 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * 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. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* NOTE: - * There are three outstanding bug/features in this implementation. - * They may even be hardware misfeatures. The conditions are registered - * by counters maintained by the software. - * 1: over_write is a condition that means that the board wants to store - * packets, but there is no room. So new packets are lost. What seems to - * be happening is that we get an over_write condition, but there are no - * or just a few packets in the board's ram. Also it seems that we get - * several over_writes in a row. - * 2: Since there is only one transmit buffer, we need a lock to indicate - * whether it is in use. We clear this lock when we get a transmit interrupt. - * Sometimes we go to transmit and although there is no transmit in progress, - * the lock is set. (In this case, we just ignore the lock.) It would look - * like we can miss transmit interrupts? - * 3: We tried to clean up the unnecessary switches to bank 0. - * Unfortunately, when you do an ifconfig "down", the system tend to lock up - * a few seconds later (this was when DSF_RUNNING) was not being set before. - * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after - * a few seconds. - */ - -/* - * Western Digital 8003E Mach Ethernet driver (for intel 80386) - * Copyright (c) 1990 by Open Software Foundation (OSF). - */ - -/* - Copyright 1990 by Open Software Foundation, -Cambridge, MA. - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appears in all copies and -that both the copyright notice and this permission notice appear in -supporting documentation, and that the name of OSF or Open Software -Foundation not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - - OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -<INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define IF_CNTRS MACH - -#include <ns8390.h> -#if NNS8390 > 0 - -#include <mach_ttd.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 "vm_param.h" -#include <i386/ipl.h> -#include <chips/busses.h> -#include <i386at/ds8390.h> -#include <i386at/if_wd8003.h> -#include <i386at/if_3c503.h> - -#if MACH_TTD -#include <ttd/ttd_stub.h> -#endif /* MACH_TTD */ - - -#define SPLNET spl6 - -int wd_debug = 0; - -int ns8390probe(); -void ns8390attach(); -int ns8390intr(); -int ns8390init(); -int ns8390output(); -int ns8390ioctl(); -int ns8390reset(); -int ns8390rcv(); -int ns8390watch(); -int ns8390get_CURR(); -int ns8390over_write(); - -struct bus_device *ns8390info[NNS8390]; /* ???? */ - -static vm_offset_t ns8390_std[NNS8390] = { 0 }; -static struct bus_device *ns8390_info[NNS8390]; -struct bus_driver ns8390driver = - {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0}; - -int watchdog_id; - -char *wd8003_card = "wd"; -char *elii_card = "el"; -/* 2e0, 2a0, 280, 250, 350, 330, 310, 300*/ -int elii_irq[8] = {5, 2, 2, 5, 5, 0x711, 0x711, 5}; -int elii_bnc[8] = {1, 0, 1, 1, 0, 0x711, 0x711, 0}; -/*int elii_bnc[8] = {0, 1, 1, 1, 1, 1, 0, 1}; */ - -typedef struct { -#ifdef MACH_KERNEL - struct ifnet ds_if; /* generic interface header */ - u_char ds_addr[6]; /* Ethernet hardware address */ -#else MACH_KERNEL - struct arpcom ns8390_ac; -#define ds_if ns8390_ac.ac_if -#define ds_addr ns8390_ac.ac_enaddr -#endif MACH_KERNEL - int flags; - int timer; - int interrupt; - char *nic; - u_char address[ETHER_ADDR_SIZE]; - short mode; - int tbusy; - char *sram; /* beginning of the shared memory RAM buffer */ - int read_nxtpkt_ptr;/* pointer to next packet available */ - int pstart; /* page start hold */ - int pstop; /* page stop hold */ - int tpsr; /* transmit page start hold */ - int fifo_depth; /* NIC fifo threshold */ - char *card; - int board_id; -} -ns8390_softc_t; - -ns8390_softc_t ns8390_softc[NNS8390]; - -struct ns8390_cntrs { -u_int ovw, - jabber, - crc, - frame, - miss, - fifo, - rcv; -u_int xmt, - xmti, - busy, - heart; -} ns8390_cntrs[NNS8390]; - -#if MACH_TTD -boolean_t ttd_poll_loop; - -int ns8390poll_receive(); -int ns8390transmit_ttd(); -#endif /* MACH_TTD */ - -#ifdef IF_CNTRS -int ns_narp = 1, ns_arp = 0; -int ns_ein[32], ns_eout[32]; -int ns_lin[128/8], ns_lout[128/8]; -static -log_2(no) -unsigned long no; -{ - return ({ unsigned long _temp__; - asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" : - "=r" (_temp__) : "a" (no)); - _temp__;}); -} -#endif IF_CNTRS - -/* Interrupts mask bits */ -int imr_hold = DSIM_PRXE|DSIM_PTXE|DSIM_RXEE|DSIM_TXEE|DSIM_OVWE|DSIM_CNTE; - -/* - * ns8390probe: - * - * This function "probes" or checks for the wd8003 board on the bus to see - * if it is there. As far as I can tell, the best break between this - * routine and the attach code is to simply determine whether the board - * is configured in properly. Currently my approach to this is to test the - * base I/O special offset for the Western Digital unique byte sequence - * identifier. If the bytes match we assume board is there. - * The config code expects to see a successful return from the probe - * routine before attach will be called. - * - * input : address device is mapped to, and unit # being checked - * output : a '1' is returned if the board exists, and a 0 otherwise - * - */ - -ns8390probe(port, dev) -struct bus_device *dev; -{ - caddr_t hdwbase = (caddr_t)dev->address; - int unit = dev->unit; - ns8390_softc_t *sp = &ns8390_softc[unit]; - int tmp; - int vendor_id; - - if ((unit < 0) || (unit > NNS8390)) { - printf("ns8390 ethernet unit %d out of range\n", unit); - return(0); - } - if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) && - ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) && - ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) { - ns8390info[unit] = dev; - sp->card = wd8003_card; - dev->name = wd8003_card; - sp->nic = hdwbase + OFF_8390; - /* enable mem access to board */ - sp->board_id = wd80xxget_board_id(dev); - - *(sp->address) = inb(hdwbase+IFWD_LAR_0); - *(sp->address + 1) = inb(hdwbase+IFWD_LAR_1); - *(sp->address + 2) = inb(hdwbase+IFWD_LAR_2); - *(sp->address + 3) = inb(hdwbase+IFWD_LAR_3); - *(sp->address + 4) = inb(hdwbase+IFWD_LAR_4); - *(sp->address + 5) = inb(hdwbase+IFWD_LAR_5); - return (1); - } /* checks the address of the board to verify that it is a WD */ - - /* try to avoid any NE2000 pretending to be an el II */ - if (inb(hdwbase + 0x408) == 0xff) - return 0; - - /* check vendor id */ - tmp = inb(hdwbase + CTLR); - - outb(hdwbase + CTLR, CTLR_RST|CTLR_THIN); /* Reset it... */ - outb(hdwbase + CTLR, CTLR_THIN); - /* - * Map the station addr PROM into the lower I/O ports. We now - * check for both the old and new 3Com prefix - */ - outb(hdwbase + CTLR, CTLR_STA_ADDR|CTLR_THIN); - vendor_id = inb(hdwbase)*0x10000 + inb(hdwbase + 1)*0x100 + - inb(hdwbase + 2); - /* Restore the register we frobbed. */ - outb(hdwbase + CTLR, tmp); - if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) - return 0; - - if ((tmp = inb(hdwbase+BCFR))) { - switch(tmp) { - case (1<<7): sp->board_id = 7; break; /*irq5 xvcr*/ -#ifdef not_currently_possible - case (1<<6): sp->board_id = 6; break; - case (1<<5): sp->board_id = 5; break; -#endif not_currently_possible - case (1<<4): sp->board_id = 4; break; - case (1<<3): sp->board_id = 3; break; - case (1<<2): sp->board_id = 2; break; /*irq2 bnc*/ - case (1<<1): sp->board_id = 1; break; /*irq2 xvcr*/ - case (1<<0): sp->board_id = 0; break; /*irq5 bnc*/ - default: return 0; - } - switch (inb(hdwbase+PCFR)) { - case (1<<7): dev->phys_address = 0xDC000; break; - case (1<<6): dev->phys_address = 0xD8000; break; -#ifdef not_currently_possible - case (1<<5): dev->phys_address = 0xCC000; break; - case (1<<4): dev->phys_address = 0xC8000; break; -#endif not_currently_possible - default: - printf("EtherLink II with NO memory configured\n"); - return 0; - } - ns8390info[unit] = dev; - dev->sysdep1 = elii_irq[sp->board_id]; - if (dev->sysdep1 == 2) - dev->sysdep1 = 9; - sp->card = elii_card; - dev->name = elii_card; - sp->nic = hdwbase; - return 1; - } - - return(0); -} - -/* - * ns8390attach: - * - * This function attaches a ns8390 board to the "system". The rest of - * runtime structures are initialized here (this routine is called after - * a successful probe of the board). Once the ethernet address is read - * and stored, the board's ifnet structure is attached and readied. - * - * input : bus_device structure setup in autoconfig - * output : board structs and ifnet is setup - * - */ - -void ns8390attach(dev) -struct bus_device *dev; -{ - ns8390_softc_t *sp; - struct ifnet *ifp; - u_char unit; - int temp; - - take_dev_irq(dev); - unit = (u_char)dev->unit; - sp = &ns8390_softc[unit]; - printf(", port = %x, spl = %d, pic = %d. ", - dev->address, dev->sysdep, dev->sysdep1); - - if (sp->card == elii_card) { - if (elii_bnc[sp->board_id]) - printf("cheapernet "); - else - printf("ethernet "); - } else - printf("ethernet "); - - (volatile char *)sp->sram = - (volatile char *) phystokv(dev->phys_address); - dev->address = (vm_offset_t) phystokv(dev->address); - sp->timer = -1; - sp->flags = 0; - sp->mode = 0; - - if (!ns8390hwrst(unit)) { - printf("%s%d: attach(): reset failed.\n", - sp->card, unit); - return; - } - /* N.B. sp->address is not determined till - * hwrst time. */ - *(sp->ds_addr) = *(sp->address); - *(sp->ds_addr + 1) = *(sp->address + 1); - *(sp->ds_addr + 2) = *(sp->address + 2); - *(sp->ds_addr + 3) = *(sp->address + 3); - *(sp->ds_addr + 4) = *(sp->address + 4); - *(sp->ds_addr + 5) = *(sp->address + 5); - - printf("id [%x:%x:%x:%x:%x:%x]", - sp->address[0],sp->address[1],sp->address[2], - sp->address[3],sp->address[4],sp->address[5]); - ifp = &(sp->ds_if); - ifp->if_unit = unit; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST; -#ifdef MACH_KERNEL - ifp->if_header_size = sizeof(struct ether_header); - ifp->if_header_format = HDR_ETHERNET; - ifp->if_address_size = 6; - ifp->if_address = (char *)&sp->address[0]; - if_init_queues(ifp); -#else MACH_KERNEL - ifp->if_name = sp->card; - ifp->if_init = ns8390init; - ifp->if_output = ns8390output; - ifp->if_ioctl = ns8390ioctl; - ifp->if_reset = ns8390reset; - ifp->if_next = NULL; - if_attach(ifp); -#ifdef notdef - watchdog_id = timeout(ns8390watch, &(ifp->if_unit), 20*HZ); -#endif -#endif MACH_KERNEL - -#ifdef MACH_KERNEL -#if MACH_TTD - if (!ttd_get_packet) { - ttd_device_unit = unit; - ttd_get_packet = ns8390poll_receive; - ttd_send_packet = ns8390transmit_ttd; - ttd_host_ether_id.array[0] = *(sp->address); - ttd_host_ether_id.array[1] = *(sp->address + 1); - ttd_host_ether_id.array[2] = *(sp->address + 2); - ttd_host_ether_id.array[3] = *(sp->address + 3); - ttd_host_ether_id.array[4] = *(sp->address + 4); - ttd_host_ether_id.array[5] = *(sp->address + 5); - } -#endif /* MACH_TTD */ -#endif /* MACH_KERNEL */ -} - -/* - * ns8390watch(): - * - */ - -int -ns8390watch(b_ptr) -caddr_t b_ptr; -{ - int x, - y, - opri, - unit; - int temp_cr; - caddr_t nic; - - unit = *b_ptr; -#ifdef MACH_KERNEL - timeout(ns8390watch,b_ptr,20*HZ); -#else MACH_KERNEL - watchdog_id = timeout(ns8390watch,b_ptr,20*HZ); -#endif MACH_KERNEL - nic = ns8390_softc[unit].nic; - temp_cr = inb(nic+ds_cmd); - outb(nic + ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); - printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ", - inb(nic + ds0_isr), - ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr, - inb(nic+ds0_bndy)); - outb(nic+ds_cmd,temp_cr); -} - -#ifdef MACH_KERNEL -int ns8390start(); /* forward */ - -/*ARGSUSED*/ -wd8003open(dev, flag) - dev_t dev; - int flag; -{ - register int unit = minor(dev); - - if (ns8390_softc[unit].card != wd8003_card) - return (ENXIO); - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - - ns8390_softc[unit].ds_if.if_flags |= IFF_UP; - ns8390init(unit); - return(0); -} - -eliiopen(dev, flag) - dev_t dev; - int flag; -{ - register int unit = minor(dev); - - if (ns8390_softc[unit].card != elii_card) - return (ENXIO); - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - - ns8390_softc[unit].ds_if.if_flags |= IFF_UP; - ns8390init(unit); - return(0); -} - -ns8390output(dev, ior) - dev_t dev; - io_req_t ior; -{ - register int unit = minor(dev); - - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior)); -} - -ns8390setinput(dev, receive_port, priority, filter, filter_count) - dev_t dev; - mach_port_t receive_port; - int priority; - filter_t filter[]; - unsigned int filter_count; -{ - register int unit = minor(dev); - - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - - return (net_set_filter(&ns8390_softc[unit].ds_if, - receive_port, priority, - filter, filter_count)); -} - -#else MACH_KERNEL -/* - * ns8390output: - * - * This routine is called by the "if" layer to output a packet to - * the network. This code resolves the local ethernet address, and - * puts it into the mbuf if there is room. If not, then a new mbuf - * is allocated with the header information and precedes the data - * to be transmitted. The routine ns8390xmt() which actually - * transmits the data expects the ethernet header to precede the - * data in the mbuf. - * - * input: ifnet structure pointer, an mbuf with data, and address - * to be resolved - * output: mbuf is updated to hold enet address, or a new mbuf - * with the address is added - * - */ - -ns8390output(ifp, m0, dst) -struct ifnet *ifp; -struct mbuf *m0; -struct sockaddr *dst; -{ - register ns8390_softc_t *is = &ns8390_softc[ifp->if_unit]; - u_char edst[6]; - struct in_addr idst; - register struct mbuf *m = m0; - register struct ether_header *eh; - register int off; - int usetrailers; - int type, error; - spl_t opri; - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - printf("%s%d output(): Turning off board %d\n", - is->card, ifp->if_unit); - ns8390intoff(ifp->if_unit); - error = ENETDOWN; - goto bad; - } - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - idst = ((struct sockaddr_in *)dst)->sin_addr; - if (!arpresolve(&is->ns8390_ac, m, &idst, edst, &usetrailers)){ - return (0); /* if not yet resolved */ - } - off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; - if (usetrailers && off > 0 && (off & 0x1ff) == 0 && - m->m_off >= MMINOFF + 2 * sizeof (u_short)) { - type = ETHERTYPE_TRAIL + (off>>9); - m->m_off -= 2 * sizeof (u_short); - m->m_len += 2 * sizeof (u_short); - *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); - *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); - goto gottrailertype; - } - type = ETHERTYPE_IP; - off = 0; - goto gottype; -#endif -#ifdef NS - case AF_NS: - type = ETHERTYPE_NS; - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, - sizeof (edst)); - off = 0; - goto gottype; -#endif - case AF_UNSPEC: - eh = (struct ether_header *)dst->sa_data; - bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); - type = eh->ether_type; - goto gottype; - default: - printf("%s%d output(): can't handle af%d\n", - is->card, ifp->if_unit, - dst->sa_family); - error = EAFNOSUPPORT; - goto bad; - } -gottrailertype: - /* - * Packet to be sent as trailer: move first packet - * (control information) to end of chain. - */ - while (m->m_next) - m = m->m_next; - m->m_next = m0; - m = m0->m_next; - m0->m_next = 0; - m0 = m; -gottype: - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - if (m->m_off > MMAXOFF || - MMINOFF + sizeof (struct ether_header) > m->m_off) { - m = m_get(M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - goto bad; - } - m->m_next = m0; - m->m_off = MMINOFF; - m->m_len = sizeof (struct ether_header); - } else { - m->m_off -= sizeof (struct ether_header); - m->m_len += sizeof (struct ether_header); - } - eh = mtod(m, struct ether_header *); - eh->ether_type = htons((u_short)type); - bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); - bcopy((caddr_t)is->address, - (caddr_t)eh->ether_shost, - sizeof(edst)); - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - opri = SPLNET(); - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(opri); - m_freem(m); - return (ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - /* - * Some action needs to be added here for checking whether the - * board is already transmitting. If it is, we don't want to - * start it up (ie call ns8390start()). We will attempt to send - * packets that are queued up after an interrupt occurs. Some - * flag checking action has to happen here and/or in the start - * routine. This note is here to remind me that some thought - * is needed and there is a potential problem here. - * - */ - ns8390start(ifp->if_unit); - splx(opri); - return (0); -bad: - m_freem(m0); - return (error); -} -#endif MACH_KERNEL - -/* - * ns8390reset: - * - * This routine is in part an entry point for the "if" code. Since most - * of the actual initialization has already (we hope already) been done - * by calling ns8390attach(). - * - * input : unit number or board number to reset - * output : board is reset - * - */ - -int -ns8390reset(unit) -int unit; -{ - - ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; - return(ns8390init(unit)); -} - -/* - * ns8390init: - * - * Another routine that interfaces the "if" layer to this driver. - * Simply resets the structures that are used by "upper layers". - * As well as calling ns8390hwrst that does reset the ns8390 board. - * - * input : board number - * output : structures (if structs) and board are reset - * - */ - -int -ns8390init(unit) -int unit; -{ - struct ifnet *ifp; - int stat; - spl_t oldpri; - - ifp = &(ns8390_softc[unit].ds_if); -#ifdef MACH_KERNEL -#else MACH_KERNEL - if (ifp->if_addrlist == (struct ifaddr *)0) { - return; - } -#endif MACH_KERNEL - oldpri = SPLNET(); - if ((stat = ns8390hwrst(unit)) == TRUE) { - ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING; - ns8390_softc[unit].flags |= DSF_RUNNING; - ns8390_softc[unit].tbusy = 0; - ns8390start(unit); - } else - printf("%s%d init(): trouble resetting board %d\n", - ns8390_softc[unit].card, unit); - ns8390_softc[unit].timer = 5; - splx(oldpri); - return(stat); -} - -/* - * ns8390start: - * - * This is yet another interface routine that simply tries to output a - * in an mbuf after a reset. - * - * input : board number - * output : stuff sent to board if any there - * - */ - -ns8390start(unit) -int unit; -{ - register ns8390_softc_t *is = &ns8390_softc[unit]; - struct ifnet *ifp; -#ifdef MACH_KERNEL - io_req_t m; -#else MACH_KERNEL - struct mbuf *m; -#endif MACH_KERNEL - - if (is->tbusy) { - caddr_t nic = ns8390_softc[unit].nic; - if (!(inb(nic+ds_cmd) & DSCM_TRANS)) { - is->tbusy = 0; - ns8390_cntrs[unit].busy++; - } else - return; - } - - ifp = &(ns8390_softc[unit].ds_if); - - IF_DEQUEUE(&ifp->if_snd, m); -#ifdef MACH_KERNEL - if (m != 0) -#else MACH_KERNEL - if (m != (struct mbuf *)0) -#endif MACH_KERNEL - { - is->tbusy++; - ns8390_cntrs[unit].xmt++; - ns8390xmt(unit, m); - } -} - -#ifdef MACH_KERNEL -/*ARGSUSED*/ -ns8390getstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; /* pointer to OUT array */ - unsigned int *count; /* out */ -{ - register int unit = minor(dev); - - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - - return (net_getstat(&ns8390_softc[unit].ds_if, - flavor, - status, - count)); -} -ns8390setstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned int count; -{ - register int unit = minor(dev); - register ns8390_softc_t *sp; - - if (unit < 0 || unit >= NNS8390 || - ns8390_softc[unit].nic == 0) - return (ENXIO); - - sp = &ns8390_softc[unit]; - - switch (flavor) { - case NET_STATUS: - { - /* - * All we can change are flags, and not many of those. - */ - register struct net_status *ns = (struct net_status *)status; - int mode = 0; - - if (count < NET_STATUS_COUNT) - return (D_INVALID_SIZE); - - if (ns->flags & IFF_ALLMULTI) - mode |= MOD_ENAL; - if (ns->flags & IFF_PROMISC) - mode |= MOD_PROM; - - /* - * Force a complete reset if the receive mode changes - * so that these take effect immediately. - */ - if (sp->mode != mode) { - sp->mode = mode; - if (sp->flags & DSF_RUNNING) { - sp->flags &= ~(DSF_LOCK | DSF_RUNNING); - ns8390init(unit); - } - } - break; - } - - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); -} -#else MACH_KERNEL -/* - * ns8390ioctl: - * - * This routine processes an ioctl request from the "if" layer - * above. - * - * input : pointer the appropriate "if" struct, command, and data - * output : based on command appropriate action is taken on the - * ns8390 board(s) or related structures - * return : error is returned containing exit conditions - * - */ - -int -ns8390ioctl(ifp, cmd, data) -struct ifnet *ifp; -int cmd; -caddr_t data; -{ - register struct ifaddr *ifa = (struct ifaddr *)data; - register ns8390_softc_t *is; - int error; - spl_t opri; - short mode = 0; - - is = &ns8390_softc[ifp->if_unit]; - opri = SPLNET(); - error = 0; - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - ns8390init(ifp->if_unit); - switch (ifa->ifa_addr.sa_family) { -#ifdef INET - case AF_INET: - ((struct arpcom *)ifp)->ac_ipaddr = - IA_SIN(ifa)->sin_addr; - arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = - &(IA_SNS(ifa)->sns_addr); - if (ns_nullhost(*ina)) - ina->x_host = - *(union ns_host *)(ds->ds_addr); - else -???? - ns8390seteh(ina->x_host.c_host, - ns8390_softc[ifp->if_unit].base); - break; - } -#endif - } - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_ALLMULTI) - mode |= MOD_ENAL; - if (ifp->if_flags & IFF_PROMISC) - mode |= MOD_PROM; - /* - * force a complete reset if the receive multicast/ - * promiscuous mode changes so that these take - * effect immediately. - * - */ - if (is->mode != mode) { - is->mode = mode; - if (is->flags & DSF_RUNNING) { - is->flags &= - ~(DSF_LOCK|DSF_RUNNING); - ns8390init(ifp->if_unit); - } - } - if ((ifp->if_flags & IFF_UP) == 0 && - is->flags & DSF_RUNNING) { - printf("%s%d ioctl(): turning off board %d\n", - is->card, ifp->if_unit); - is->flags &= ~(DSF_LOCK | DSF_RUNNING); - is->timer = -1; - ns8390intoff(ifp->if_unit); - ns8390over_write(ifp->if_unit); - } else - if (ifp->if_flags & IFF_UP && - (is->flags & DSF_RUNNING) == 0) - ns8390init(ifp->if_unit); - break; -#ifdef IF_CNTRS - case SIOCCIFCNTRS: - if (!suser()) { - error = EPERM; - break; - } - bzero((caddr_t)ns_ein, sizeof (ns_ein)); - bzero((caddr_t)ns_eout, sizeof (ns_eout)); - bzero((caddr_t)ns_lin, sizeof (ns_lin)); - bzero((caddr_t)ns_lout, sizeof (ns_lout)); - bzero((caddr_t)&ns_arp, sizeof (int)); - bzero((caddr_t)&ns8390_cntrs, sizeof (ns8390_cntrs)); - break; -#endif IF_CNTRS - default: - error = EINVAL; - } - splx(opri); - return (error); -} -#endif MACH_KERNEL - -/* - * ns8390hwrst: - * - * This routine resets the ns8390 board that corresponds to the - * board number passed in. - * - * input : board number to do a hardware reset - * output : board is reset - * - */ - -int -ns8390hwrst(unit) -int unit; -{ - caddr_t nic = ns8390_softc[unit].nic; - int count; - u_char stat; - spl_t spl = SPLNET(); - - if (ns8390_softc[unit].card == wd8003_card && - config_wd8003(unit) == FALSE) { - printf("%s%d hwrst(): config_wd8003 failed.\n", - ns8390_softc[unit].card, unit); - splx(spl); - return(FALSE); - } - if (ns8390_softc[unit].card == elii_card && - config_3c503(unit) == FALSE) { - printf("%s%d hwrst(): config_3c503 failed.\n", - ns8390_softc[unit].card, unit); - splx(spl); - return(FALSE); - } - if (config_nic(unit) == FALSE) { - printf("%s%d hwrst(): config_nic failed.\n", - ns8390_softc[unit].card, unit); - splx(spl); - return(FALSE); - } - splx(spl); - return(TRUE); -} - -/* - * ns8390intr: - * - * This function is the interrupt handler for the ns8390 ethernet - * board. This routine will be called whenever either a packet - * is received, or a packet has successfully been transfered and - * the unit is ready to transmit another packet. - * - * input : board number that interrupted - * output : either a packet is received, or a packet is transfered - * - */ -int -ns8390intr(unit) -{ - int opri, i; - int isr_status; - int temp_cr; - caddr_t nic = ns8390_softc[unit].nic; - - temp_cr = inb(nic+ds_cmd); - outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); - outb(nic+ds0_imr, 0); /* stop board interrupts */ - outb(nic+ds_cmd, temp_cr); - while (isr_status = inb(nic+ds0_isr)) { - outb(nic+ds0_isr, isr_status); /* clear interrupt status */ - - if ((isr_status & (DSIS_ROVRN|DSIS_RXE)) == DSIS_RXE) { - int rsr = inb(nic+ds0_rsr); - if (rsr & DSRS_DFR) ns8390_cntrs[unit].jabber++; - if (rsr & ~(DSRS_DFR|DSRS_PHY|DSRS_FAE|DSRS_CRC|DSIS_RX)) - printf("%s%d intr(): isr = %x, RSR = %x\n", - ns8390_softc[unit].card, unit, - isr_status, rsr); - } else if (isr_status & DSIS_ROVRN) { - ns8390_cntrs[unit].ovw++; - ns8390over_write(unit); - } - if (isr_status & DSIS_RX) { /* DFR & PRX is possible */ - ns8390rcv(unit); - -#if MACH_TTD - if (kttd_active) - ttd_poll_loop = FALSE; -#endif /* MACH_TTD */ - } - - if (isr_status & DSIS_TXE) { - int tsr = inb(nic+ds0_tsr); - tsr &= ~0x2; /* unadvertised special */ -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { - if (tsr == (DSTS_CDH|DSTS_ABT)) - ns8390_cntrs[unit].heart++; - else - printf("%s%d intr(): isr = %x, TSR = %x\n", - ns8390_softc[unit].card, unit, - isr_status, tsr); - ns8390_softc[unit].tbusy = 0; - ns8390start(unit); - } - } else if (isr_status & DSIS_TX) { -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { - ns8390_cntrs[unit].xmti++; - ns8390_softc[unit].tbusy = 0; - ns8390start(unit); - } - } - - if (isr_status & DSIS_CTRS) { - int c0 = inb(nic+ds0_cntr0); - int c1 = inb(nic+ds0_cntr1); - int c2 = inb(nic+ds0_cntr2); - ns8390_cntrs[unit].frame += c0; - ns8390_cntrs[unit].crc += c1; - ns8390_cntrs[unit].miss += c2; -#ifdef COUNTERS - printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n", - ns8390_softc[unit].card, unit, - isr_status, c0, c1, c2); - printf("%s%d intr(): TOTAL , FRAME %x, CRC %x, MISS %x\n", - ns8390_softc[unit].card, unit, - ns8390_cntrs[unit].frame, - ns8390_cntrs[unit].crc, - ns8390_cntrs[unit].miss); -#endif COUNTERS - outb(nic+ds0_isr, isr_status); /* clear interrupt status again */ - } - } - temp_cr=inb(nic+ds_cmd); - outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); - outb(nic+ds0_imr, imr_hold); - outb(nic+ds_cmd, temp_cr); - return(0); -} - -/* - * Called if on board buffer has been completely filled by ns8390intr. It stops - * the board, reads in all the buffers that are currently in the buffer, and - * then restart board. - */ -ns8390over_write(unit) -int unit; -{ - caddr_t nic = ns8390_softc[unit].nic; - int no; - int count = 0; - - outb(nic+ds_cmd, DSCM_NODMA|DSCM_STOP|DSCM_PG0); /* clear the receive buffer */ - outb(nic+ds0_rbcr0, 0); - outb(nic+ds0_rbcr1, 0); - while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000)) - count++; - if (count == 10000) { - printf("%s%d: over_write(): would not reset.\n", - ns8390_softc[unit].card, unit); - } - no = ns8390rcv(unit); -#ifdef OVWBUG - printf("%s%d over_write(): ns8390 OVW ... %d.\n", - ns8390_softc[unit].card, unit, no); -#endif OVWBUG - outb(nic+ds0_tcr, DSTC_LB0); /* External loopback mode */ - outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); - outb(nic+ds0_tcr, 0); - return; -} - -/* - * ns8390rcv: - * - * This routine is called by the interrupt handler to initiate a - * packet transfer from the board to the "if" layer above this - * driver. This routine checks if a buffer has been successfully - * received by the ns8390. If so, it does the actual transfer of the - * board data (including the ethernet header) into a packet (consisting - * of an mbuf chain) and enqueues it to a higher level. - * Then check again whether there are any packets in the receive ring, - * if so, read the next packet, until there are no more. - * - * input : number of the board to check - * output : if a packet is available, it is "sent up" - */ -ns8390rcv(unit) -int unit; -{ - register ns8390_softc_t *is = &ns8390_softc[unit]; - register struct ifnet *ifp = &is->ds_if; - caddr_t nic = is->nic; - int packets = 0; - struct ether_header eh; - u_short mlen, len, bytes_in_mbuf, bytes; - u_short remaining; - int temp_cr; - u_char *mb_p; - int board_id = is->board_id; - vm_offset_t hdwbase = ns8390info[unit]->address; - spl_t s; - - /* calculation of pkt size */ - int nic_overcount; /* NIC says 1 or 2 more than we need */ - int pkt_size; /* calculated size of received data */ - int wrap_size; /* size of data before wrapping it */ - int header_nxtpkt_ptr; /* NIC's next pkt ptr in rcv header */ - int low_byte_count; /* low byte count of read from rcv header */ - int high_byte_count; /* calculated high byte count */ - - - volatile char *sram_nxtpkt_ptr; /* mem location of next packet */ - volatile char *sram_getdata_ptr; /* next location to be read */ -#ifdef MACH_KERNEL - ipc_kmsg_t new_kmsg; - struct ether_header *ehp; - struct packet_header *pkt; -#else MACH_KERNEL - struct mbuf *m, *tm; /* initial allocation of mem; temp */ -#endif MACH_KERNEL - - -#if MACH_TTD - if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) && - !kttd_active) { -#else - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { -#endif /* MACH_TTD */ - temp_cr = inb(nic+ds_cmd); /* get current CR value */ - outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP)); - outb(nic+ds0_imr, 0); /* Interrupt Mask Register */ - outb(nic+ds_cmd, temp_cr); - return -1; - } - - while(is->read_nxtpkt_ptr != ns8390get_CURR(unit)) { - - /* while there is a packet to read from the buffer */ - - if ((is->read_nxtpkt_ptr < is->pstart) || - (is->read_nxtpkt_ptr >= is->pstop)) { - ns8390hwrst(unit); - return -1; - } /* if next packet pointer is out of receive ring bounds */ - -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { - packets++; - ns8390_cntrs[unit].rcv++; - } - - sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8)); - - /* get packet size and location of next packet */ - header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); - header_nxtpkt_ptr &= 0xFF; - low_byte_count = *(sram_nxtpkt_ptr + 2); - low_byte_count &= 0xFF; - - if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE) - nic_overcount = 2; - else - nic_overcount = 1; - if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) { - wrap_size = 0; - high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr - - nic_overcount; - } else { - wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount); - high_byte_count = is->pstop - is->read_nxtpkt_ptr + - header_nxtpkt_ptr - is->pstart - nic_overcount; - } - pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF); - /* does not seem to include NIC_HEADER_SIZE */ - if (!pkt_size) { - printf("%s%d rcv(): zero length.\n", - ns8390_softc[unit].card, unit); - goto next_pkt; - } - len = pkt_size; - - sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE; - if (board_id & IFWD_SLOT_16BIT) { -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { s = splhi(); } - - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, - &eh, - sizeof(struct ether_header)); - dis_16bit_access (hdwbase, board_id); -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { splx(s); } - - } else { - bcopy16 (sram_getdata_ptr, - &eh, - sizeof(struct ether_header)); - } - sram_getdata_ptr += sizeof(struct ether_header); - len -= (sizeof(struct ether_header) + 4); /* crc size */ -#ifdef MACH_KERNEL -#if MACH_TTD - if (kttd_active) { - new_kmsg = (ipc_kmsg_t)ttd_request_msg; - }else -#endif /* MACH_TTD */ - { - new_kmsg = net_kmsg_get(); - if (new_kmsg == IKM_NULL) { - /* - * Drop the packet. - */ - is->ds_if.if_rcvdrops++; - /* - * not only do we want to return, we need to drop - * the packet on the floor to clear the interrupt. - */ - ns8390lost_frame(unit); - return;/* packets;*/ - } - } - -#if DEBUG_TTD - dump_ether_header("ns8390wire",&eh); -#endif /* DEBUG_TTD */ - - ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]); - pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]); - -#if DEBUG_TTD - printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt); -#endif /* DEBUG_TTD */ - - *ehp = eh; - if (len > - (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) { - /* if needs to wrap */ - if (board_id & IFWD_SLOT_16BIT) { -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { s = splhi(); } - - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, (char *) (pkt + 1), - wrap_size); - dis_16bit_access (hdwbase, board_id); -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { splx(s); } - } else { - bcopy (sram_getdata_ptr, (char *) (pkt + 1), - wrap_size); - } - sram_getdata_ptr = (volatile char *) - (is->sram + (is->pstart << 8)); - } else { /* normal getting data from buffer */ - wrap_size = 0; - } - if (board_id & IFWD_SLOT_16BIT) { -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { s = splhi(); } - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, - (char *) (pkt + 1) + wrap_size, - len - wrap_size); - dis_16bit_access (hdwbase, board_id); -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { splx(s); } - } else { - bcopy (sram_getdata_ptr, - (char *) (pkt + 1) + wrap_size, - len - wrap_size); - } - - pkt->type = ehp->ether_type; - pkt->length = len + sizeof(struct packet_header); - -#if MACH_TTD - /* - * Don't want to call net_packet if we are polling - * for a packet. - */ - if (!kttd_active) -#endif /* MACH_TTD */ - { - /* - * Hand the packet to the network module. - */ - net_packet(ifp, new_kmsg, pkt->length, - ethernet_priority(new_kmsg)); - } - -#else MACH_KERNEL -#define NEW -#ifdef NEW - m = (struct mbuf *) 0; - eh.ether_type = ntohs(eh.ether_type); - MGET(m, M_DONTWAIT, MT_DATA); - if (m == (struct mbuf *) 0) { - printf("%s%d rcv(): Lost frame\n", - ns8390_softc[unit].card, unit); - ns8390lost_frame(unit); /* update NIC pointers and registers */ - return packets; - } - m->m_next = (struct mbuf *) 0; - tm = m; - m->m_len = MLEN; - if (len > 2 * MLEN - sizeof (struct ifnet **)) { - MCLGET(m); - } - *(mtod(tm, struct ifnet **)) = ifp; - mlen = sizeof (struct ifnet **); - bytes_in_mbuf = m->m_len - sizeof(struct ifnet **); - mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **); - bytes = min(bytes_in_mbuf, len); - remaining = (int) (is->sram + (is->pstop << 8) - - sram_getdata_ptr); - bytes = min(bytes, remaining); - do { - if (board_id & IFWD_SLOT_16BIT) { - s = splhi(); - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, mb_p, bytes); - dis_16bit_access (hdwbase, board_id); - splx(s); - } else { - bcopy16 (sram_getdata_ptr, mb_p, bytes); - } - - mlen += bytes; - - if (!(bytes_in_mbuf -= bytes)) { - MGET(tm->m_next, M_DONTWAIT, MT_DATA); - tm = tm->m_next; - if (tm == (struct mbuf *)0) { - printf("%s%d rcv(): No mbufs, lost frame\n", - ns8390_softc[unit].card, unit); - m_freem(m); /* free the mbuf chain */ - ns8390lost_frame(unit); /* update NIC pointers and registers */ - return; - } - mlen = 0; - tm->m_len = MLEN; - bytes_in_mbuf = MLEN; - mb_p = mtod(tm, u_char *); - } else - mb_p += bytes; - - if (!(len -= bytes)) { - tm->m_len = mlen; - break; - } else if (bytes == remaining) { - sram_getdata_ptr = (volatile char *) (is->sram + - (is->pstart << 8)); - bytes = len; - remaining = ETHERMTU; - } else { - sram_getdata_ptr += bytes; - remaining -= bytes; - } - - bytes = min(bytes_in_mbuf, len); - bytes = min(bytes, remaining); - } while(1); -#else NEW - m = (struct mbuf *) 0; - eh.ether_type = ntohs(eh.ether_type); - - while ( len ) { - if (m == (struct mbuf *) 0) { - m = m_get(M_DONTWAIT, MT_DATA); - if (m == (struct mbuf *) 0) { - printf("%s%d rcv(): Lost frame\n", - ns8390_softc[unit].card, unit); - ns8390lost_frame(unit); /* update NIC pointers and registers */ - return packets; - } - tm = m; - tm->m_off = MMINOFF; - - - /* - * first mbuf in the packet must contain a pointer to the - * ifnet structure. other mbufs that follow and make up - * the packet do not need this pointer in the mbuf. - * - */ - - *(mtod(tm, struct ifnet **)) = ifp; - tm->m_len = sizeof(struct ifnet **); - - /* end of first buffer of packet */ - } else { - tm->m_next = m_get(M_DONTWAIT, MT_DATA); - tm = tm->m_next; - if (tm == (struct mbuf *) 0) { - printf("%s%d rcv(): No mbufs, lost frame\n", - ns8390_softc[unit].card, unit); - m_freem(m); /* free the mbuf chain */ - ns8390lost_frame(unit); /* update NIC pointers and registers */ - return packets; - } - tm->m_off = MMINOFF; - tm->m_len = 0; - } - - tlen = MIN( MLEN - tm->m_len, len); - /* size of mbuf so you know how much you can copy from board */ - tm->m_next = (struct mbuf *) 0; - if (sram_getdata_ptr + tlen >= - (volatile char *) (is->sram + (is->pstop << 8))) { - /* if needs to wrap */ - wrap_size = (int) (is->sram + (is->pstop << 8) - - sram_getdata_ptr); - if (board_id & IFWD_SLOT_16BIT) { - s = splhi(); - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, - mtod(tm, char*) + tm->m_len, - wrap_size); - dis_16bit_access (hdwbase, board_id); - splx(s); - } else { - bcopy16 (sram_getdata_ptr, - mtod(tm, char*) + tm->m_len, - wrap_size); - } - tm->m_len += wrap_size; - len -= wrap_size; - - sram_getdata_ptr = (volatile char *) (is->sram + - (is->pstart << 8)); - } else { /* normal getting data from buffer */ - if (board_id & IFWD_SLOT_16BIT) { - s = splhi(); - en_16bit_access(hdwbase, board_id); - bcopy16 (sram_getdata_ptr, - mtod(tm, char*) + tm->m_len, - tlen); - dis_16bit_access (hdwbase, board_id); - splx(s); - } else { - bcopy16 (sram_getdata_ptr, - mtod(tm, char*) + tm->m_len, - tlen); - } - sram_getdata_ptr += tlen; - tm->m_len += tlen; - len -= tlen; - - } - } - -#endif NEW - if (!ns8390send_packet_up(m, &eh, is)) - m_freem(m); -#ifdef IF_CNTRS - ns_ein[log_2(pkt_size)]++; - if (pkt_size < 128) ns_lin[(pkt_size)>>3]++; - - if (eh.ether_type == ETHERTYPE_ARP) { - ns_arp++; - if (ns_narp) { - ns_ein[log_2(pkt_size)]--; - if (pkt_size < 128) ns_lin[(pkt_size)>>3]--; - } - } -#endif IF_CNTRS -#endif MACH_KERNEL - -next_pkt: - is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); - is->read_nxtpkt_ptr &= 0xFF; - -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { - temp_cr = inb(nic+ds_cmd); - outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); - } - - if (is->read_nxtpkt_ptr == ns8390get_CURR(unit)) - if (is->read_nxtpkt_ptr == is->pstart) - outb(nic+ds0_bndy, is->pstop - 1); - else - outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1); - else - outb(nic+ds0_bndy, is->read_nxtpkt_ptr); - -#if MACH_TTD - if (!kttd_active) -#endif /* MACH_TTD */ - { outb(nic+ds_cmd, temp_cr); } - -#if MACH_TTD - /* - * Hand the packet back to the TTD server, if active. - */ - if (kttd_active && pkt_size) - return 1; -#endif /* MACH_TTD */ - - - } - return packets; - -} - -#ifdef MACH_KERNEL -#if MACH_TTD -/* - * Polling routines for the TTD debugger. - */ -int ns8390poll_receive(unit) - int unit; -{ - int s; - int orig_cr; - int orig_imr; - int isr_status; - int pkts; - - ttd_poll_loop = TRUE; - - - /* - * Should already in at splhigh. Is this necessary? XXX - */ - s = splhigh(); - -#if 0 - if (kttd_debug) - printf("ns8390poll_receive: beginning polling loop\n"); -#endif /* DEBUG_TTD */ - - /* - * Loop until packet arrives. - */ - while(ttd_poll_loop) { - - /* - * Call intr routine - */ - - ns8390intr(unit); - } - -#if 0 - if (kttd_debug) - printf("ns8390poll_receive: got packet exiting loop\n"); -#endif /* DEBUG_TTD */ - - splx(s); -} - -int ns8390transmit_ttd(unit, packet, len) - int unit; - char * packet; - int len; -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - caddr_t nic = is->nic; - u_short count = 0; /* amount of data already copied */ - volatile char *sram_write_pkt; - int board_id = is->board_id; - caddr_t hdwbase = ns8390info[unit]->address; - int s; - int orig_cr; - int orig_imr; - int isr_status; - boolean_t loop = TRUE; - -#if 0 - dump_ipudpbootp("Beg of xmit",packet); -#endif - - s = splhigh(); - - /* begining of physical address of transmition buffer */ - - sram_write_pkt = is->sram + is->tpsr * 0x100; - - count = len; - if (board_id & IFWD_SLOT_16BIT) { - en_16bit_access(hdwbase, board_id); - bcopy16 (packet, sram_write_pkt, count); - dis_16bit_access (hdwbase, board_id); - } else { - bcopy (packet, sram_write_pkt, count); - } - - while (count < ETHERMIN+sizeof(struct ether_header)) { - *(sram_write_pkt + count) = 0; - count++; - } - outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); /* select page 0 */ - outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */ - outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */ - outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */ - outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); /* start transmission */ - - ns8390intr(unit); - - splx(s); -} -#endif /* MACH_TTD */ -#endif /* MACH_KERNEL */ - -#ifdef MACH_KERNEL -#else MACH_KERNEL -/* - * Send a packet composed of an mbuf chain to the higher levels - * - */ -ns8390send_packet_up(m, eh, is) -struct mbuf *m; -struct ether_header *eh; -ns8390_softc_t *is; -{ - register struct ifqueue *inq; - spl_t opri; - - switch (eh->ether_type) { -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; - case ETHERTYPE_ARP: - arpinput(&is->ns8390_ac, m); - return(TRUE); -#endif -#ifdef NS - case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; - break; -#endif - default: - return(FALSE); - } - opri = SPLNET(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - splx(opri); - return(FALSE); - } - IF_ENQUEUE(inq, m); - splx(opri); - return(TRUE); -} -#endif MACH_KERNEL - -/* - * ns8390lost_frame: - * this routine called by ns8390read after memory for mbufs could not be - * allocated. It sets the boundary pointers and registers to the next - * packet location. - */ - -ns8390lost_frame(unit) -int unit; -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - caddr_t nic = is->nic; - volatile char *sram_nxtpkt_ptr; - int temp_cr; - - - - sram_nxtpkt_ptr = (volatile char *) (is->sram + - (is->read_nxtpkt_ptr << 8)); - - is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); - is->read_nxtpkt_ptr &= 0xFF; - - temp_cr = inb(nic+ds_cmd); - outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); - - /* update boundary register */ - if (is->read_nxtpkt_ptr == ns8390get_CURR(unit)) - if (is->read_nxtpkt_ptr == is->pstart) - outb(nic+ds0_bndy, is->pstop - 1); - else - outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1); - else - outb(nic+ds0_bndy, is->read_nxtpkt_ptr); - - outb(nic+ds_cmd, temp_cr); - - return; -} - -/* - * ns8390get_CURR(): - * - * Returns the value of the register CURR, which points to the next - * available space for NIC to receive from network unto receive ring. - * - */ - -int -ns8390get_CURR(unit) -int unit; -{ - caddr_t nic = ns8390_softc[unit].nic; - int temp_cr; - int ret_val; - spl_t s; - - s = SPLNET(); - - temp_cr = inb(nic+ds_cmd); /* get current CR value */ - outb(nic+ds_cmd, ((temp_cr & 0x3F) | DSCM_PG1)); /* select page 1 registers */ - ret_val = inb(nic+ds1_curr); /* read CURR value */ - outb(nic+ds_cmd, temp_cr); - splx(s); - return (ret_val & 0xFF); -} - -/* - * ns8390xmt: - * - * This routine fills in the appropriate registers and memory - * locations on the ns8390 board and starts the board off on - * the transmit. - * - * input : board number of interest, and a pointer to the mbuf - * output : board memory and registers are set for xfer and attention - * - */ - -ns8390xmt(unit, m) -int unit; -#ifdef MACH_KERNEL -io_req_t m; -#else MACH_KERNEL -struct mbuf *m; -#endif MACH_KERNEL -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - caddr_t nic = is->nic; - struct ether_header *eh; - int i; - int opri; - u_short count = 0; /* amount of data already copied */ - volatile char *sram_write_pkt; - int board_id = is->board_id; - vm_offset_t hdwbase = ns8390info[unit]->address; - spl_t s; - -#ifdef MACH_KERNEL -#else MACH_KERNEL - register struct mbuf *tm_p; -#endif MACH_KERNEL - /* begining of physical address of transmition buffer */ - - sram_write_pkt = is->sram + is->tpsr * 0x100; - -#ifdef MACH_KERNEL - count = m->io_count; - if (board_id & IFWD_SLOT_16BIT) { - s = splhi(); - en_16bit_access(hdwbase, board_id); - bcopy16 (m->io_data, sram_write_pkt, count); - dis_16bit_access (hdwbase, board_id); - splx(s); - } else { - bcopy (m->io_data, sram_write_pkt, count); - } -#else MACH_KERNEL - for(tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next) { - if (count + tm_p->m_len > ETHERMTU + sizeof (struct ether_header)) - break; - if (tm_p->m_len == 0) - continue; - if (board_id & IFWD_SLOT_16BIT) { - s = splhi(); - en_16bit_access(hdwbase, board_id); - bcopy16 (mtod(tm_p, caddr_t), - sram_write_pkt + count, - tm_p->m_len); - dis_16bit_access (hdwbase, board_id); - splx(s); - } else { - bcopy16 (mtod(tm_p, caddr_t), - sram_write_pkt + count, - tm_p->m_len); - } - count += tm_p->m_len; - } -#ifdef IF_CNTRS - ns_eout[log_2(count+4/*crc*/)]++; - if (count < 128) ns_lout[(count+4/*crc*/)>>3]++; -#endif IF_CNTRS -#endif MACH_KERNEL - while (count < ETHERMIN+sizeof(struct ether_header)) { - *(sram_write_pkt + count) = 0; - count++; - } - - /* select page 0 */ - outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); - outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */ - outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */ - outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */ - /* start transmission */ - outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); - -#ifdef MACH_KERNEL - iodone(m); - m=0; -#else MACH_KERNEL - /* If this is a broadcast packet, loop it back to rcv. */ - eh = mtod( m, struct ether_header *); - for (i=0; ((i < 6) && (eh->ether_dhost[i] == 0xff)); i++) ; - if (i == 6) { - if (!ns8390send_packet_up(m, eh, is)) - m_freem(m); - } else - m_freem(m); -#endif MACH_KERNEL - return; -} - -config_nic(unit) -int unit; -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - caddr_t nic = is->nic; - int i; - int temp; - int count = 0; - spl_t s; - - /* soft reset and page 0 */ - outb (nic+ds_cmd, DSCM_PG0|DSCM_NODMA|DSCM_STOP); - - while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000)) - count++; - if (count == 10000) { - printf("%s%d: config_nic(): would not reset.\n", - ns8390_softc[unit].card, unit); - } - - /* fifo depth | not loopback */ - temp = ((is->fifo_depth & 0x0c) << 3) | DSDC_BMS; - - /* word xfer select (16 bit cards ) */ - if (is->board_id & IFWD_SLOT_16BIT) - temp |= DSDC_WTS; - - outb (nic+ds0_dcr, temp); - outb (nic+ds0_tcr, 0); - outb (nic+ds0_rcr, DSRC_MON); /* receive configuration register */ - /* recieve ring starts 2k into RAM */ - outb (nic+ds0_pstart, is->pstart); - /* stop at last RAM buffer rcv location */ - outb (nic+ds0_pstop, is->pstop); - - /* boundary pointer for page 0 */ - outb (nic+ds0_bndy, is->pstart); - s = SPLNET(); - - /* maintain rst | sel page 1 */ - outb (nic+ds_cmd, DSCM_PG1|DSCM_NODMA|DSCM_STOP); - - /* internal next packet pointer */ - is->read_nxtpkt_ptr = is->pstart + 1; - - outb (nic+ds1_curr, is->read_nxtpkt_ptr); /* Current page register */ - for(i=0; i<ETHER_ADDR_SIZE; i++) - outb (nic+ds1_par0+i, is->address[i]); - for(i=0; i<8; i++) - outb (nic+ds1_mar0+i, 0); - - outb (nic+ds_cmd, DSCM_PG0|DSCM_STOP|DSCM_NODMA); - splx(s); - outb (nic+ds0_isr, 0xff); /* clear all interrupt status bits */ - outb (nic+ds0_imr, imr_hold); /* Enable interrupts */ - outb (nic+ds0_rbcr0, 0); /* clear remote byte count */ - outb (nic+ds0_rbcr1, 0); - - /* start NIC | select page 0 */ - outb (nic+ds_cmd, DSCM_PG0|DSCM_START|DSCM_NODMA); - - outb (nic+ds0_rcr, DSRC_AB); /* receive configuration register */ - - return TRUE; -} - -/* - * config_ns8390: - * - * This routine does a standard config of a wd8003 family board, with - * the proper modifications to different boards within this family. - * - */ -config_wd8003(unit) -int unit; -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - vm_offset_t hdwbase = ns8390info[unit]->address; - int i; - int RAMsize; - volatile char *RAMbase; - int addr_temp; - - is->tpsr = 0; /* transmit page start hold */ - is->pstart = 0x06; /* receive page start hold */ - is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */ - is->fifo_depth = 0x08; /* NIC fifo threshold */ - switch (is->board_id & IFWD_RAM_SIZE_MASK) { - case IFWD_RAM_SIZE_8K: - RAMsize = 0x2000; break; - case IFWD_RAM_SIZE_16K: - RAMsize = 0x4000; break; - case IFWD_RAM_SIZE_32K: - RAMsize = 0x8000; break; - case IFWD_RAM_SIZE_64K: - RAMsize = 0x10000; break; - default: - RAMsize = 0x2000; break; - } - is->pstop = (((int)RAMsize >> 8) & 0x0ff); /* rcv page stop hold */ - RAMbase = (volatile char *)ns8390info[unit]->phys_address; - addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */ - outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */ - /* enable 16 bit access from lan controller */ - if (is->board_id & IFWD_SLOT_16BIT) { - if (is->board_id & IFWD_INTERFACE_CHIP) { - outb(hdwbase+IFWD_REG_5, - (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) | - IFWD_LAN16ENB); - } else { - outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19)); - } - } - /* - outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT); - */ - - return TRUE; -} - -/* - * config_ns8390: - * - * This routine does a standard config of a 3 com etherlink II board. - * - */ -int -config_3c503(unit) -int unit; -{ - ns8390_softc_t *is = &ns8390_softc[unit]; - struct bus_device *dev = ns8390info[unit]; - vm_offset_t hdwbase = dev->address; - int RAMsize = dev->am; - int i; - - is->tpsr = 0x20; /* transmit page start hold */ - is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100; - /* When NIC says page 20, this means go to - the beginning of the sram range */ - is->pstart = 0x26; /* receive page start hold */ - is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */ - is->fifo_depth = 0x08; /* NIC fifo threshold */ - is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff); /* rcv page stop hold */ - - outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN); - outb(hdwbase+CTLR, CTLR_THIN); - outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN); - for (i = 0; i < 6; i++) - is->address[i] = inb(hdwbase+i); - outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK); - outb(hdwbase+PSTR, is->pstart); - outb(hdwbase+PSPR, is->pstop); - outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2)); - outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K); - /* BCFR & PCRFR ro */ - /* STREG ro & dma */ - outb(hdwbase+DQTR, 0); - outb(hdwbase+DAMSB, 0); - outb(hdwbase+DALSB, 0); - outb(hdwbase+VPTR2, 0); - outb(hdwbase+VPTR1, 0); - outb(hdwbase+VPTR0, 0); - outb(hdwbase+RFMSB, 0); - outb(hdwbase+RFLSB, 0); - return TRUE; -} - -/* - * ns8390intoff: - * - * This function turns interrupts off for the ns8390 board indicated. - * - */ -void -ns8390intoff(unit) -int unit; -{ - caddr_t nic = ns8390_softc[unit].nic; - int temp_cr = inb(nic+ds_cmd); /* get current CR value */ - - outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP)); - outb(nic+ds0_imr, 0); /* Interrupt Mask Register */ - outb(nic+ds_cmd, temp_cr|DSCM_STOP); - -} - - -/* - * wd80xxget_board_id: - * - * determine which board is being used. - * Currently supports: - * wd8003E (tested) - * wd8003EBT - * wd8003EP (tested) - * wd8013EP (tested) - * - */ -wd80xxget_board_id(dev) -struct bus_device *dev; -{ - vm_offset_t hdwbase = dev->address; - long unit = dev->unit; - long board_id = 0; - int reg_temp; - int rev_num; /* revision number */ - int ram_flag; - int intr_temp; - int i; - boolean_t register_aliasing; - - rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1; - printf("%s%d: ", ns8390_softc[unit].card, unit); - - if (rev_num == 0) { - printf("rev 0x00\n"); - /* It must be 8000 board */ - return 0; - } - - /* Check if register aliasing is true, that is reading from register - offsets 0-7 will return the contents of register offsets 8-f */ - - register_aliasing = TRUE; - for (i = 1; i < 5; i++) { - if (inb(hdwbase + IFWD_REG_0 + i) != - inb(hdwbase + IFWD_LAR_0 + i)) - register_aliasing = FALSE; - } - if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM)) - register_aliasing = FALSE; - - - if (register_aliasing == FALSE) { - /* Check if board has interface chip */ - - reg_temp = inb(hdwbase + IFWD_REG_7); /* save old */ - outb(hdwbase + IFWD_REG_7, 0x35); /* write value */ - inb(hdwbase + IFWD_REG_0); /* dummy read */ - if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) { - outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/ - inb(hdwbase + IFWD_REG_0); /* dummy read */ - if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) { - board_id |= IFWD_INTERFACE_CHIP; - outb(hdwbase + IFWD_REG_7, reg_temp); - /* restore old value */ - } - } - - /* Check if board is 16 bit by testing if bit zero in - register 1 is unchangeable by software. If so then - card has 16 bit capability */ - reg_temp = inb(hdwbase + IFWD_REG_1); - outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT); - inb(hdwbase + IFWD_REG_0); /* dummy read */ - if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) == - (reg_temp & IFWD_16BIT)) { /* Is bit unchanged */ - board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */ - reg_temp &= 0xfe; /* For 16 bit board - always reset bit 0 */ - } - outb(hdwbase + IFWD_REG_1, reg_temp); /* write value back */ - - /* Test if 16 bit card is in 16 bit slot by reading bit zero in - register 1. */ - if (board_id & IFWD_BOARD_16BIT) { - if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) { - board_id |= IFWD_SLOT_16BIT; - } - } - } - - /* Get media type */ - - if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) { - board_id |= IFWD_ETHERNET_MEDIA; - } else if (rev_num == 1) { - board_id |= IFWD_STARLAN_MEDIA; - } else { - board_id |= IFWD_TWISTED_PAIR_MEDIA; - } - - if (rev_num == 2) { - if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) { - if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB || - (board_id & IFWD_STATIC_ID_MASK) == WD8003W) { - board_id |= IFWD_ALTERNATE_IRQ_BIT; - } - } - /* Check for memory size */ - - ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE; - - switch (board_id & IFWD_STATIC_ID_MASK) { - case WD8003E: /* same as WD8003EBT */ - case WD8003S: /* same as WD8003SH */ - case WD8003WT: - case WD8003W: - case WD8003EB: /* same as WD8003EP */ - if (ram_flag) - board_id |= IFWD_RAM_SIZE_32K; - else - board_id |= IFWD_RAM_SIZE_8K; - break; - case WD8003ETA: - case WD8003STA: - case WD8003EA: - case WD8003SHA: - case WD8003WA: - board_id |= IFWD_RAM_SIZE_16K; - break; - case WD8013EBT: - if (board_id & IFWD_SLOT_16BIT) { - if (ram_flag) - board_id |= IFWD_RAM_SIZE_64K; - else - board_id |= IFWD_RAM_SIZE_16K; - } else { - if (ram_flag) - board_id |= IFWD_RAM_SIZE_32K; - else - board_id |= IFWD_RAM_SIZE_8K; - } - break; - default: - board_id |= IFWD_RAM_SIZE_UNKNOWN; - break; - } - } else if (rev_num >= 3) { - board_id &= (long) ~IFWD_MEDIA_MASK; /* remove media info */ - board_id |= IFWD_INTERFACE_584_CHIP; - board_id |= wd80xxget_eeprom_info(hdwbase, board_id); - } else { - /* Check for memory size */ - if (board_id & IFWD_BOARD_16BIT) { - if (board_id & IFWD_SLOT_16BIT) - board_id |= IFWD_RAM_SIZE_16K; - else - board_id |= IFWD_RAM_SIZE_8K; - } else if (board_id & IFWD_MICROCHANNEL) - board_id |= IFWD_RAM_SIZE_16K; - else if (board_id & IFWD_INTERFACE_CHIP) { - if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE) - board_id |= IFWD_RAM_SIZE_32K; - else - board_id |= IFWD_RAM_SIZE_8K; - } else - board_id |= IFWD_RAM_SIZE_UNKNOWN; - - /* No support for 690 chip yet. It should be checked here */ - } - - switch (board_id & IFWD_STATIC_ID_MASK) { - case WD8003E: printf("WD8003E or WD8003EBT"); break; - case WD8003S: printf("WD8003S or WD8003SH"); break; - case WD8003WT: printf("WD8003WT"); break; - case WD8003W: printf("WD8003W"); break; - case WD8003EB: - if (board_id & IFWD_INTERFACE_584_CHIP) - printf("WD8003EP"); - else - printf("WD8003EB"); - break; - case WD8003EW: printf("WD8003EW"); break; - case WD8003ETA: printf("WD8003ETA"); break; - case WD8003STA: printf("WD8003STA"); break; - case WD8003EA: printf("WD8003EA"); break; - case WD8003SHA: printf("WD8003SHA"); break; - case WD8003WA: printf("WD8003WA"); break; - case WD8013EBT: printf("WD8013EBT"); break; - case WD8013EB: - if (board_id & IFWD_INTERFACE_584_CHIP) - printf("WD8013EP"); - else - printf("WD8013EB"); - break; - case WD8013W: printf("WD8013W"); break; - case WD8013EW: printf("WD8013EW"); break; - default: printf("unknown"); break; - } - printf(" rev 0x%02x", rev_num); - switch(board_id & IFWD_RAM_SIZE_RES_7) { - case IFWD_RAM_SIZE_UNKNOWN: - break; - case IFWD_RAM_SIZE_8K: - printf(" 8 kB ram"); - break; - case IFWD_RAM_SIZE_16K: - printf(" 16 kB ram"); - break; - case IFWD_RAM_SIZE_32K: - printf(" 32 kB ram"); - break; - case IFWD_RAM_SIZE_64K: - printf(" 64 kB ram"); - break; - default: - printf("wd: Internal error ram size value invalid %d\n", - (board_id & IFWD_RAM_SIZE_RES_7)>>16); - } - - if (board_id & IFWD_BOARD_16BIT) { - if (board_id & IFWD_SLOT_16BIT) { - printf(", in 16 bit slot"); - } else { - printf(", 16 bit board in 8 bit slot"); - } - } - if (board_id & IFWD_INTERFACE_CHIP) { - if (board_id & IFWD_INTERFACE_584_CHIP) { - printf(", 584 chip"); - } else { - printf(", 583 chip"); - } - } - if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) { - /* program the WD83C583 EEPROM registers */ - int irr_temp, icr_temp; - - icr_temp = inb(hdwbase + IFWD_ICR); - irr_temp = inb(hdwbase + IFWD_IRR); - - irr_temp &= ~(IFWD_IR0 | IFWD_IR1); - irr_temp |= IFWD_IEN; - - icr_temp &= IFWD_WTS; - - if (!(board_id & IFWD_INTERFACE_584_CHIP)) { - icr_temp |= IFWD_DMAE | IFWD_IOPE; - if (ram_flag) - icr_temp |= IFWD_MSZ; - } - - if (board_id & IFWD_INTERFACE_584_CHIP) { - switch(ns8390info[unit]->sysdep1) { - case 10: - icr_temp |= IFWD_DMAE; - break; - case 2: - case 9: /* Same as 2 */ - break; - case 11: - icr_temp |= IFWD_DMAE; - /*FALLTHROUGH*/ - case 3: - irr_temp |= IFWD_IR0; - break; - case 15: - icr_temp |= IFWD_DMAE; - /*FALLTHROUGH*/ - case 5: - irr_temp |= IFWD_IR1; - break; - case 4: - icr_temp |= IFWD_DMAE; - /*FALLTHROUGH*/ - case 7: - irr_temp |= IFWD_IR0 | IFWD_IR1; - break; - default: - printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n", - ns8390_softc[unit].card, unit, - ns8390info[unit]->sysdep1); - break; - } - } else { - switch(ns8390info[unit]->sysdep1) { - /* attempt to set interrupt according to assigned pic */ - case 2: - case 9: /* Same as 2 */ - break; - case 3: - irr_temp |= IFWD_IR0; - break; - case 4: - irr_temp |= IFWD_IR1; - break; - case 5: - irr_temp |= IFWD_IR1 | IFWD_AINT; - break; - case 7: - irr_temp |= IFWD_IR0 | IFWD_IR1; - break; - default: - printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n", - ns8390_softc[unit].card, unit, - ns8390info[unit]->sysdep1); - } - } - outb(hdwbase + IFWD_IRR, irr_temp); - outb(hdwbase + IFWD_ICR, icr_temp); - } - printf("\n"); - return (board_id); -} - -wd80xxget_eeprom_info(hdwbase, board_id) - caddr_t hdwbase; - long board_id; -{ - unsigned long new_bits = 0; - int reg_temp; - - outb(hdwbase + IFWD_REG_1, - ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT)); - outb(hdwbase + IFWD_REG_3, - ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE)); - outb(hdwbase + IFWD_REG_1, - ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | - (IFWD_RLA | IFWD_OTHER_BIT))); - while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK) - ; - - reg_temp = inb(hdwbase + IFWD_EEPROM_1); - switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) { - case IFWD_EEPROM_BUS_TYPE_AT: - if (wd_debug & 1) printf("wd: AT bus, "); - break; - case IFWD_EEPROM_BUS_TYPE_MCA: - if (wd_debug & 1) printf("wd: MICROCHANNEL, "); - new_bits |= IFWD_MICROCHANNEL; - break; - default: - break; - } - switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) { - case IFWD_EEPROM_BUS_SIZE_8BIT: - if (wd_debug & 1) printf("8 bit bus size, "); - break; - case IFWD_EEPROM_BUS_SIZE_16BIT: - if (wd_debug & 1) printf("16 bit bus size "); - new_bits |= IFWD_BOARD_16BIT; - if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) { - new_bits |= IFWD_SLOT_16BIT; - if (wd_debug & 1) - printf("in 16 bit slot, "); - } else { - if (wd_debug & 1) - printf("in 8 bit slot (why?), "); - } - break; - default: - if (wd_debug & 1) printf("bus size other than 8 or 16 bit, "); - break; - } - reg_temp = inb(hdwbase + IFWD_EEPROM_0); - switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) { - case IFWD_STARLAN_TYPE: - if (wd_debug & 1) printf("Starlan media, "); - new_bits |= IFWD_STARLAN_MEDIA; - break; - case IFWD_TP_TYPE: - if (wd_debug & 1) printf("Twisted pair media, "); - new_bits |= IFWD_TWISTED_PAIR_MEDIA; - break; - case IFWD_EW_TYPE: - if (wd_debug & 1) printf("Ethernet and twisted pair media, "); - new_bits |= IFWD_EW_MEDIA; - break; - case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/ - default: - if (wd_debug & 1) printf("ethernet media, "); - new_bits |= IFWD_ETHERNET_MEDIA; - break; - } - switch (reg_temp & IFWD_EEPROM_IRQ_MASK) { - case IFWD_ALTERNATE_IRQ_1: - if (wd_debug & 1) printf("Alternate irq 1\n"); - new_bits |= IFWD_ALTERNATE_IRQ_BIT; - break; - default: - if (wd_debug & 1) printf("\n"); - break; - } - switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) { - case IFWD_EEPROM_RAM_SIZE_8K: - new_bits |= IFWD_RAM_SIZE_8K; - break; - case IFWD_EEPROM_RAM_SIZE_16K: - if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT)) - new_bits |= IFWD_RAM_SIZE_16K; - else - new_bits |= IFWD_RAM_SIZE_8K; - break; - case IFWD_EEPROM_RAM_SIZE_32K: - new_bits |= IFWD_RAM_SIZE_32K; - break; - case IFWD_EEPROM_RAM_SIZE_64K: - if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT)) - new_bits |= IFWD_RAM_SIZE_64K; - else - new_bits |= IFWD_RAM_SIZE_32K; - break; - default: - new_bits |= IFWD_RAM_SIZE_UNKNOWN; - break; - } - outb(hdwbase + IFWD_REG_1, - ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT)); - outb(hdwbase + IFWD_REG_3, - ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6)); - outb(hdwbase + IFWD_REG_1, - ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA)); - return (new_bits); -} - -wdpr(unit) -{ - caddr_t nic = ns8390_softc[unit].nic; - spl_t s; - int temp_cr; - - s = SPLNET(); - temp_cr = inb(nic+ds_cmd); /* get current CR value */ - - printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n", - inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5), - inb(nic+0x6), inb(nic+0x7), inb(nic+0xc)); - printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n", - inb(nic+0x1), inb(nic+0x2), - inb(nic+0x8), inb(nic+0x9), - inb(nic+0xd), inb(nic+0xe), inb(nic+0xf)); - - - outb(nic, (temp_cr&0x3f)|DSCM_PG1); /* page 1 CR value */ - printf("PHYS %x:%x:%x:%x:%x CUR %x\n", - inb(nic+0x1), inb(nic+0x2), inb(nic+0x3), - inb(nic+0x4), inb(nic+0x5), inb(nic+0x6), - inb(nic+0x7)); - printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n", - inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb), - inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf)); - outb(nic, temp_cr); /* restore current CR value */ - splx(s); -} - - -/* - This sets bit 7 (0 justified) of register offset 0x05. It will enable - the host to access shared RAM 16 bits at a time. It will also maintain - the LAN16BIT bit high in addition, this routine maintains address bit 19 - (previous cards assumed this bit high...we must do it manually) - - note 1: this is a write only register - note 2: this routine should be called only after interrupts are disabled - and they should remain disabled until after the routine 'dis_16bit_access' - is called -*/ - -en_16bit_access (hdwbase, board_id) - caddr_t hdwbase; - long board_id; -{ - if (board_id & IFWD_INTERFACE_CHIP) - outb(hdwbase+IFWD_REG_5, - (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) - | IFWD_MEM16ENB | IFWD_LAN16ENB); - else - outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB | - IFWD_LA19)); -} - -/* - This resets bit 7 (0 justified) of register offset 0x05. It will disable - the host from accessing shared RAM 16 bits at a time. It will maintain the - LAN16BIT bit high in addition, this routine maintains address bit 19 - (previous cards assumed this bit high...we must do it manually) - - note: this is a write only register -*/ - -dis_16bit_access (hdwbase, board_id) - caddr_t hdwbase; - long board_id; -{ - if (board_id & IFWD_INTERFACE_CHIP) - outb(hdwbase+IFWD_REG_5, - ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) | - IFWD_LAN16ENB)); - else - outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19)); -} - -#endif |