summaryrefslogtreecommitdiff
path: root/i386/i386at/if_ns8390.c
diff options
context:
space:
mode:
Diffstat (limited to 'i386/i386at/if_ns8390.c')
-rw-r--r--i386/i386at/if_ns8390.c2578
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