home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-27 | 33.2 KB | 1,089 lines |
- Newsgroups: comp.unix.bsd
- Path: sparky!uunet!europa.asd.contel.com!gatech!rpi!psinntp!psinntp!dg-rtp!ponds.uucp!rivers
- From: rivers@ponds.uucp (Thomas David Rivers)
- Subject: NE2000 test results (previous driver performs better).
- Summary: Here's a better driver (repost).
- Message-ID: <1992Dec27.181634.523@ponds.uucp>
- Keywords: ether, speed, 386bsd NE2000
- Date: Sun, 27 Dec 1992 18:16:34 GMT
- Lines: 1078
-
-
- Well, since Curt Mayer (curt@hoptoad.uucp) had re-written the
- NE2000 driver for us, I decided to take some time and give it
- a good shaking out.
-
- My test machines (ponds and lakes) are:
-
- ponds lakes
- 386DX, 33mhz 386DX, 33mhz
- NE2000 clone NE2000 clone
- 8-meg memory 12-meg memory
- Hercules ET4000 clone (running XFree86 1.1)
- IDE 240Meg. SCSI -663 meg
- Wangtek (EN2099) Wangtek (5150ES)
- 40-meg swap on wd0 40-meg swap on sd0
-
- They are directly connected by 6 feet on ethernet cable, With a
- 50-ohm terminator on lakes, and a 50-ohm grounded terminator on ponds.
- There is nothing else on this "network".
-
- So, here are some timings from the driver posted to comp.unix.bsd by
- Ralf Friedl (PA Peter) <friedl@informatik.uni-kl.de>, on Jul 15th.
- These are arrived by moving a copy of the 386bsd kernel from
- lakes to ponds (444736 bytes) using binary ftp (no hash).
-
- Time to Transfer (seconds) Kbytes/Sec
- 4.3 1e+02
- 3.3 1.3e+02
- 3.4 1.3e+02
- 2.8 1.6e+02
- 4.2 1e+02
-
- These appear to be rather good time, approaching what you would
- expect the bandwidth to be on such a network (few collisions...)
-
- Ok, so I installed the driver posted by Curt. My original intent
- was to install it on both machines, then only one. However, when
- that kernel came up on "lakes" the network didn't function (lots of
- overun-type errors from the driver: ne0 ... error: isr 15;
- ne0 ... error: isr 14, etc...)
-
- Thus, I was only able to get Curt's driver to run on "ponds". The
- following times reflect that situation (ponds is running Curt Mayer's
- driver, lakes is running the driver posted in July.) There was *no*
- other change in the test, hardware, etc... Since the times appeared
- so much worse, I ran more tests than before.
-
- Time to Transfer (seconds) Kbytes/Sec
- 10 42
- 10 42
- 11 39
- 10 42
- 15 29
- 6.3 69
- 9.4 46
-
- These numbers don't approach those of the other driver. Also, just to
- get a feel for NFS mounts, rlogin, etc... I tried out several NFS
- configurations, rlogin'ing and so forth - generally it seemed to be
- much slower.
-
- OK, so I thought I may have seriously goofed things up, since these
- numbers were so much lower than the other driver. So, I rebooted
- ponds with the (saved) kernel containing the Friedl drivers, and
- ran some tests. Again, the only change I made was to reboot the
- machine - no other modifications. The test results returned to a set
- similar to above, indicating that it was indeed the NE2000 driver
- which explained the slowdown.
-
-
- I have sent this driver to several people (who had requested an
- improved driver from this news group.) But, I would like other
- people to do the same comparison (or a comparison in different
- circumstances) to validate my results. As such, I am *reposting*
- this same driver again.... (also, there were several people
- who requested this code, to whom I could not send mail (it bounced))
-
- - Dave Rivers -
- (rivers@ponds.uucp)
-
- ----------------- cut here ----------------------------
- Path: utnet-news!news.u-tokyo.ac.jp!ccut!wnoc-tyo-news!nec-tyo!nec-gw!mips!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!ames!network.ucsd.edu!nosc!jadpc!Ralf Friedl (PA Peter) <friedl@informatik.uni-kl.de>
- From: friedl@informatik.uni-kl.de (PA Peter)
- Newsgroups: comp.unix.bsd
- Subject: Device driver for NE1000/NE2000
- Message-ID: <9207152126.aa00382@superieur.informatik.uni-kl.de>
- Date: 15 Jul 92 19:53:32 GMT
- Sender: 386bsd-gate@jadpc.cts.com
- Reply-To: Ralf Friedl (PA Peter) <friedl@informatik.uni-kl.de>
- Organization: J. Deitch & Associates
- Lines: 212
- Originator: 386bsd-gate@jadpc.cts.com
- Precedence: bulk
-
-
- Below is a diff for the original net2 NE2000 driver, so that the driver can
- be used with both NE1000 and NE2000 or compatible interface cards. The type of
- the card is determined during the boot in the autoconfiguration phase, so it is
- not necessary to specify it at compile time.
-
- The driver may also work with more that one card at the same time, but I didn't
- try it.
-
- The driver includes a file "machine/asm.h". This is used for inline versions of
- the in../out.. function. If you don't have something like that, just remove the
- line, and the functions in locore.s will be used.
-
- Enjoy
-
- ----
- Ralf Friedl
- friedl@informatik.uni-kl.de
-
-
- #!/bin/sh
- # This is a shell archive (shar 3.32)
- # made 07/31/1992 07:20 UTC by shin@angora.nc.u-tokyo.ac.jp
- # Source directory /tmp
- #
- # existing files WILL be overwritten
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 24098 -rw-r--r-- if_ne.c
- # 2982 -rw-r--r-- if_nereg.h
- #
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= if_ne.c ==============
- echo "x - extracting if_ne.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > if_ne.c &&
- X/*-
- X * Copyright (c) 1990, 1991 William F. Jolitz.
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms, with or without
- X * modification, are permitted provided that the following conditions
- X * are met:
- X * 1. Redistributions of source code must retain the above copyright
- X * notice, this list of conditions and the following disclaimer.
- X * 2. Redistributions in binary form must reproduce the above copyright
- X * notice, this list of conditions and the following disclaimer in the
- X * documentation and/or other materials provided with the distribution.
- X * 3. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the University of
- X * California, Berkeley and its contributors.
- X * 4. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X * SUCH DAMAGE.
- X *
- X * @(#)if_ne.c 7.4 (Berkeley) 5/21/91
- X */
- X
- X/*
- X * NE1000/NE2000 Ethernet driver
- X *
- X * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
- X * insight on the ne2000 gained from Robert Clements PC/FTP driver.
- X */
- X
- X#include "ne.h"
- X#if NNE > 0
- X
- X#include "param.h"
- X#include "systm.h"
- X#include "mbuf.h"
- X#include "buf.h"
- X#include "protosw.h"
- X#include "socket.h"
- X#include "ioctl.h"
- X#include "errno.h"
- X#include "syslog.h"
- X
- X#include "net/if.h"
- X#include "net/netisr.h"
- X#include "net/route.h"
- X
- X#ifdef INET
- X#include "netinet/in.h"
- X#include "netinet/in_systm.h"
- X#include "netinet/in_var.h"
- X#include "netinet/ip.h"
- X#include "netinet/if_ether.h"
- X#endif
- X
- X#ifdef NS
- X#include "netns/ns.h"
- X#include "netns/ns_if.h"
- X#endif
- X
- X#include "i386/isa/isa_device.h"
- X#include "i386/isa/if_nereg.h"
- X#include "i386/isa/icu.h"
- X/* #include "machine/asm.h" */
- X
- Xint neprobe(), neattach(), neintr();
- Xint nestart(),neinit(), ether_output(), neioctl();
- X
- Xstruct isa_driver nedriver = {
- X neprobe, neattach, "ne",
- X};
- X
- Xstruct mbuf *neget();
- X
- X#define ETHER_MIN_LEN 64
- X#define ETHER_MAX_LEN 1536
- X
- X/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
- X#define DCR_CTRL2 DSDC_WTS|DSDC_BMS|DSDC_FT1
- X/* No Word Transfers, Burst Mode Select, Fifo at 8 bytes */
- X#define DCR_CTRL1 DSDC_BMS|DSDC_FT1
- X
- X
- X/*
- X * Ethernet software status per interface.
- X *
- X * Each interface is referenced by a network interface structure,
- X * ns_if, which the routing code uses to locate the interface.
- X * This structure contains the output queue for the interface, its address, ...
- X */
- Xstruct ne_softc {
- X struct arpcom ns_ac; /* Ethernet common part */
- X#define ns_if ns_ac.ac_if /* network-visible interface */
- X#define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */
- X int ns_flags;
- X#define DSF_LOCK 1 /* block re-entering enstart */
- X int ns_oactive ;
- X int ns_mask ;
- X int ns_ba; /* byte addr in buffer ram of inc pkt */
- X int ns_cur; /* current page being filled */
- X u_short ns_iobase;
- X u_short ns_board; /* Board-Type: 0:NE1000, 1:NE2000 */
- X u_short ns_tbuf;
- X u_short ns_rbuf;
- X u_short ns_rbufend;
- X struct prhdr ns_ph; /* hardware header of incoming packet*/
- X struct ether_header ns_eh; /* header of incoming packet */
- X u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
- X} ne_softc[NNE] ;
- X#define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
- X
- Xu_char boarddata[16];
- Xvoid nefetch (struct ne_softc *ns, void *up, u_int ad, u_int len);
- Xvoid neput (struct ne_softc *ns, void *up, u_int ad, u_int len);
- X
- X
- Xneprobe(dvp)
- X struct isa_device *dvp;
- X{
- X int val,i, test, unit;
- X u_short iobase;
- X register struct ne_softc *ns;
- X
- X unit = dvp->id_unit;
- X if (unit >= NNE)
- X return (0);
- X ns = &ne_softc[unit];
- X if (ns->ns_iobase)
- X /* Unit already configured */
- X return (0);
- X iobase = ns->ns_iobase = dvp->id_iobase;
- X
- X /* Reset the bastard */
- X val = inb(iobase+ne_reset);
- X /* DELAY(2000000); */
- X outb(iobase+ne_reset,val);
- X
- X outb(iobase+ds_cmd, DSCM_STOP|DSCM_NODMA);
- X
- X if (inb (iobase + ds_cmd) != (DSCM_STOP | DSCM_NODMA))
- X return (0);
- X i = 1000000;
- X while ((inb(iobase+ds0_isr)&DSIS_RESET) == 0 && i-- > 0);
- X if (i < 0) return (0);
- X
- X outb(iobase+ds0_isr, 0xff);
- X
- X /* No Word Transfers, Burst Mode Select, Fifo at 8 bytes */
- X outb (iobase+ds0_dcr, DCR_CTRL1);
- X
- X outb(iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
- X DELAY(10000);
- X
- X /* Check cmd reg and fail if not right */
- X if ((i=inb(iobase+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
- X return(0);
- X
- X outb(iobase+ds0_tcr, 0);
- X outb(iobase+ds0_rcr, DSRC_MON);
- X outb(iobase+ds0_pstart, RBUF1/DS_PGSIZE);
- X outb(iobase+ds0_pstop, RBUFEND1/DS_PGSIZE);
- X outb(iobase+ds0_bnry, RBUFEND1/DS_PGSIZE);
- X outb(iobase+ds0_imr, 0);
- X outb(iobase+ds0_isr, 0);
- X outb(iobase+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
- X outb(iobase+ds1_curr, RBUF1/DS_PGSIZE);
- X outb(iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
- X test = 0xA55A55AA;
- X neput (ns, &test, TBUF1, sizeof (test));
- X nefetch (ns, &test, TBUF1, sizeof (test));
- X if (test == 0xA55A55AA) {
- X ns->ns_board = 0; /* NE1000 */
- X ns->ns_tbuf = TBUF1;
- X ns->ns_rbuf = RBUF1;
- X ns->ns_rbufend = RBUFEND1;
- X }
- X else {
- X ns->ns_board = 1; /* NE2000 */
- X ns->ns_tbuf = TBUF2;
- X ns->ns_rbuf = RBUF2;
- X ns->ns_rbufend = RBUFEND2;
- X outb(iobase+ds0_dcr, DCR_CTRL2);
- X }
- X
- X#ifdef NEDEBUG
- X#define PAT(n) (0xa55a + 37*(n))
- X#define RCON 37
- X { int i, rom, pat;
- X
- X rom=1;
- X printf("ne ram ");
- X
- X for (i = 0; i < 0xfff0; i+=4) {
- X pat = PAT(i);
- X neput (ns, &pat,i,4);
- X nefetch (ns, &pat,i,4);
- X if (pat == PAT(i)) {
- X if (rom) {
- X rom=0;
- X printf(" %x", i);
- X }
- X } else {
- X if (!rom) {
- X rom=1;
- X printf("..%x ", i);
- X }
- X }
- X pat=0;
- X neput (ns, &pat,i,4);
- X }
- X printf("\n");
- X }
- X#endif
- X
- X /* Extract board address */
- X nefetch (ns, boarddata, 0, sizeof(boarddata));
- X if (ns->ns_board)
- X for (i = 0; i < 6; i++)
- X ns->ns_addr[i] = boarddata[2 * i];
- X else
- X for (i = 0; i < 6; i++)
- X ns->ns_addr[i] = boarddata[i];
- X return (1);
- X}
- X
- X/*
- X * Fetch from onboard ROM/RAM
- X */
- Xvoid nefetch (struct ne_softc *ns, void *up, u_int ad, u_int len)
- X{
- X u_char cmd;
- X const u_short iobase = ns->ns_iobase;
- X
- X if (len == 0)
- X return;
- X cmd = inb(iobase+ds_cmd);
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
- X
- X /* Setup remote dma */
- X outb (iobase+ds0_isr, DSIS_RDC);
- X outb (iobase+ds0_rbcr0, len);
- X outb (iobase+ds0_rbcr1, len>>8);
- X outb (iobase+ds0_rsar0, ad);
- X outb (iobase+ds0_rsar1, ad>>8);
- X
- X /* Execute & extract from card */
- X outb (iobase+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
- X if (ns->ns_board)
- X insw (iobase+ne_data, up, len/2);
- X else
- X insb (iobase+ne_data, up, len/1);
- X
- X /* Wait till done, then shutdown feature */
- X while ((inb (iobase+ds0_isr) & DSIS_RDC) == 0)
- X ;
- X outb (iobase+ds0_isr, DSIS_RDC);
- X outb (iobase+ds_cmd, cmd);
- X}
- X
- X/*
- X * Put to onboard RAM
- X */
- Xvoid neput (struct ne_softc *ns, void *up, u_int ad, u_int len)
- X{
- X u_char cmd;
- X const u_short iobase = ns->ns_iobase;
- X
- X if (len == 0)
- X return;
- X cmd = inb(iobase+ds_cmd);
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
- X
- X /* Setup for remote dma */
- X outb (iobase+ds0_isr, DSIS_RDC);
- X if(len&1) len++; /* roundup to words */
- X outb (iobase+ds0_rbcr0, len);
- X outb (iobase+ds0_rbcr1, len>>8);
- X outb (iobase+ds0_rsar0, ad);
- X outb (iobase+ds0_rsar1, ad>>8);
- X
- X /* Execute & stuff to card */
- X outb (iobase+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
- X if (ns->ns_board)
- X outsw (iobase+ne_data, up, len/2);
- X else
- X outsb (iobase+ne_data, up, len/1);
- X
- X /* Wait till done, then shutdown feature */
- X while ((inb (iobase+ds0_isr) & DSIS_RDC) == 0)
- X ;
- X outb (iobase+ds0_isr, DSIS_RDC);
- X outb (iobase+ds_cmd, cmd);
- X}
- X
- X/*
- X * Reset of interface.
- X */
- Xnereset(unit, uban)
- X int unit, uban;
- X{
- X if (unit >= NNE)
- X return;
- X printf("ne%d: reset\n", unit);
- X ne_softc[unit].ns_flags &= ~DSF_LOCK;
- X neinit(unit);
- X}
- X
- X/*
- X * Interface exists: make available by filling in network interface
- X * record. System will initialize the interface when it is ready
- X * to accept packets. We get the ethernet address here.
- X */
- Xneattach(dvp)
- X struct isa_device *dvp;
- X{
- X int unit = dvp->id_unit;
- X register struct ne_softc *ns = &ne_softc[unit];
- X register struct ifnet *ifp = &ns->ns_if;
- X
- X ifp->if_unit = unit;
- X ifp->if_name = nedriver.name ;
- X ifp->if_mtu = ETHERMTU;
- X printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ;
- X ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
- X ifp->if_init = neinit;
- X ifp->if_output = ether_output;
- X ifp->if_start = nestart;
- X ifp->if_ioctl = neioctl;
- X ifp->if_reset = nereset;
- X ifp->if_watchdog = 0;
- X if_attach(ifp);
- X}
- X
- X/*
- X * Initialization of interface; set up initialization block
- X * and transmit/receive descriptor rings.
- X */
- Xneinit(unit)
- X int unit;
- X{
- X register struct ne_softc *ns = &ne_softc[unit];
- X struct ifnet *ifp = &ns->ns_if;
- X int s;
- X register i; char *cp;
- X const u_short iobase = ns->ns_iobase;
- X
- X if (ifp->if_addrlist == (struct ifaddr *)0) return;
- X if (ifp->if_flags & IFF_RUNNING) return;
- X
- X s = splimp();
- X
- X /* set physical address on ethernet */
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
- X for (i=0 ; i < 6 ; i++) outb(iobase+ds1_par0+i,ns->ns_addr[i]);
- X
- X /* clr logical address hash filter for now */
- X for (i=0 ; i < 8 ; i++) outb(iobase+ds1_mar0+i,0xff);
- X
- X /* init regs */
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
- X outb (iobase+ds0_rbcr0, 0);
- X outb (iobase+ds0_rbcr1, 0);
- X outb (iobase+ds0_imr, 0);
- X outb (iobase+ds0_isr, 0xff);
- X
- X outb(iobase+ds0_tcr, 0);
- X outb (iobase+ds0_rcr, DSRC_MON);
- X outb (iobase+ds0_tpsr, 0);
- X outb(iobase+ds0_pstart, ns->ns_rbuf/DS_PGSIZE);
- X outb(iobase+ds0_pstop, ns->ns_rbufend/DS_PGSIZE);
- X outb(iobase+ds0_bnry, ns->ns_rbuf/DS_PGSIZE);
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
- X outb(iobase+ds1_curr, ns->ns_rbuf/DS_PGSIZE);
- X ns->ns_cur = ns->ns_rbuf/DS_PGSIZE;
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
- X outb (iobase+ds0_rcr, DSRC_AB);
- X if (ns->ns_board)
- X outb(iobase+ds0_dcr, DCR_CTRL2);
- X else
- X outb(iobase+ds0_dcr, DCR_CTRL1);
- X outb (iobase+ds0_imr, 0xff);
- X
- X ns->ns_if.if_flags |= IFF_RUNNING;
- X ns->ns_oactive = 0; ns->ns_mask = ~0;
- X nestart(ifp);
- X splx(s);
- X}
- X
- X/*
- X * Setup output on interface.
- X * Get another datagram to send off of the interface queue,
- X * and map it to the interface before starting the output.
- X * called only at splimp or interrupt level.
- X */
- Xnestart(ifp)
- X struct ifnet *ifp;
- X{
- X register struct ne_softc *ns = &ne_softc[ifp->if_unit];
- X struct mbuf *m0, *m;
- X int buffer;
- X int len = 0, i, total,t;
- X const u_short iobase = ns->ns_iobase;
- X
- X /*
- X * The DS8390 has only one transmit buffer, if it is busy we
- X * must wait until the transmit interrupt completes.
- X */
- X outb(iobase+ds_cmd,DSCM_NODMA|DSCM_START);
- X
- X if (ns->ns_flags & DSF_LOCK)
- X return;
- X
- X if (inb(iobase+ds_cmd) & DSCM_TRANS)
- X return;
- X
- X if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
- X return;
- X
- X IF_DEQUEUE(&ns->ns_if.if_snd, m);
- X
- X if (m == 0)
- X return;
- X
- X /*
- X * Copy the mbuf chain into the transmit buffer
- X */
- X
- X ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */
- X buffer = ns->ns_tbuf; len = i = 0;
- X t = 0;
- X for (m0 = m; m != 0; m = m->m_next)
- X t += m->m_len;
- X
- X m = m0;
- X total = t;
- X for (m0 = m; m != 0; ) {
- X
- X if (m->m_len&1 && t > m->m_len) {
- X neput (ns, mtod(m, caddr_t), buffer, m->m_len - 1);
- X t -= m->m_len - 1;
- X buffer += m->m_len - 1;
- X m->m_data += m->m_len - 1;
- X m->m_len = 1;
- X m = m_pullup(m, 2);
- X } else {
- X if (m->m_len) {
- X neput (ns, mtod(m, caddr_t), buffer, m->m_len);
- X buffer += m->m_len;
- X t -= m->m_len;
- X }
- X MFREE(m, m0);
- X m = m0;
- X }
- X }
- X
- X /*
- X * Init transmit length registers, and set transmit start flag.
- X */
- X
- X len = total;
- X if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
- X outb(iobase+ds0_tbcr0,len&0xff);
- X outb(iobase+ds0_tbcr1,(len>>8)&0xff);
- X outb(iobase+ds0_tpsr, ns->ns_tbuf/DS_PGSIZE);
- X outb(iobase+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
- X}
- X
- X/* buffer successor/predecessor in ring? */
- X#define succ1(n) (((n)+1 >= RBUFEND1/DS_PGSIZE) ? RBUF1/DS_PGSIZE : (n)+1)
- X#define pred1(n) (((n)-1 < RBUF1/DS_PGSIZE) ? RBUFEND1/DS_PGSIZE-1 : (n)-1)
- X#define succ2(n) (((n)+1 >= RBUFEND2/DS_PGSIZE) ? RBUF2/DS_PGSIZE : (n)+1)
- X#define pred2(n) (((n)-1 < RBUF2/DS_PGSIZE) ? RBUFEND2/DS_PGSIZE-1 : (n)-1)
- X
- X/*
- X * Controller interrupt.
- X */
- Xneintr(unit)
- X{
- X register struct ne_softc *ns = &ne_softc[unit];
- X u_char cmd,isr;
- X const u_short iobase = ns->ns_iobase;
- X
- X /* Save cmd, clear interrupt */
- X cmd = inb (iobase+ds_cmd);
- Xloop:
- X isr = inb (iobase+ds0_isr);
- X outb(iobase+ds_cmd,DSCM_NODMA|DSCM_START);
- X outb(iobase+ds0_isr, isr);
- X
- X /* Receiver error */
- X if (isr & DSIS_RXE) {
- X /* need to read these registers to clear status */
- X (void) inb(iobase+ ds0_rsr);
- X (void) inb(iobase+ 0xD);
- X (void) inb(iobase + 0xE);
- X (void) inb(iobase + 0xF);
- X ns->ns_if.if_ierrors++;
- X }
- X
- X /* We received something; rummage thru tiny ring buffer */
- X if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
- X u_char pend,lastfree;
- X
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
- X pend = inb(iobase+ds1_curr);
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
- X lastfree = inb(iobase+ds0_bnry);
- X
- X /* Have we wrapped? */
- X if (lastfree >= ns->ns_rbufend/DS_PGSIZE)
- X lastfree = ns->ns_rbuf/DS_PGSIZE;
- X if (pend < lastfree && ns->ns_cur < pend)
- X lastfree = ns->ns_cur;
- X else if (ns->ns_cur > lastfree)
- X lastfree = ns->ns_cur;
- X
- X /* Something in the buffer? */
- X while (pend != lastfree) {
- X u_char nxt;
- X
- X /* Extract header from microcephalic board */
- X nefetch (ns, &ns->ns_ph,lastfree*DS_PGSIZE,
- X sizeof(ns->ns_ph));
- X ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph);
- X
- X /* Incipient paranoia */
- X if (ns->ns_ph.pr_status == DSRS_RPC ||
- X /* for dequna's */
- X ns->ns_ph.pr_status == 0x21)
- X nerecv (ns);
- X#ifdef NEDEBUG
- X else {
- X printf("cur %x pnd %x lfr %x ",
- X ns->ns_cur, pend, lastfree);
- X printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
- X (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
- X printf("Bogus Sts %x\n", ns->ns_ph.pr_status);
- X }
- X#endif
- X
- X nxt = ns->ns_ph.pr_nxtpg ;
- X
- X /* Sanity check */
- X if ( nxt >= ns->ns_rbuf/DS_PGSIZE && nxt <= ns->ns_rbufend/DS_PGSIZE
- X && nxt <= pend)
- X ns->ns_cur = nxt;
- X else ns->ns_cur = nxt = pend;
- X
- X /* Set the boundaries */
- X lastfree = nxt;
- X if (ns->ns_board)
- X outb(iobase+ds0_bnry, pred2(nxt));
- X else
- X outb(iobase+ds0_bnry, pred1(nxt));
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
- X pend = inb(iobase+ds1_curr);
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
- X }
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA);
- X }
- X
- X /* Transmit error */
- X if (isr & DSIS_TXE) {
- X ns->ns_flags &= ~DSF_LOCK;
- X /* Need to read these registers to clear status */
- X ns->ns_if.if_collisions += inb(iobase+ds0_tbcr0);
- X ns->ns_if.if_oerrors++;
- X }
- X
- X /* Packet Transmitted */
- X if (isr & DSIS_TX) {
- X ns->ns_flags &= ~DSF_LOCK;
- X ++ns->ns_if.if_opackets;
- X ns->ns_if.if_collisions += inb(iobase+ds0_tbcr0);
- X }
- X
- X /* Receiver ovverun? */
- X if (isr & DSIS_ROVRN) {
- X log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr
- X /*, DSIS_BITS*/);
- X outb(iobase+ds0_rbcr0, 0);
- X outb(iobase+ds0_rbcr1, 0);
- X outb(iobase+ds0_tcr, DSTC_LB0);
- X outb(iobase+ds0_rcr, DSRC_MON);
- X outb(iobase+ds_cmd, DSCM_START|DSCM_NODMA);
- X outb(iobase+ds0_rcr, DSRC_AB);
- X outb(iobase+ds0_tcr, 0);
- X }
- X
- X /* Any more to send? */
- X outb (iobase+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
- X nestart(&ns->ns_if);
- X outb (iobase+ds_cmd, cmd);
- X outb (iobase+ds0_imr, 0xff);
- X
- X
- X /* Still more to do? */
- X isr = inb (iobase+ds0_isr);
- X if(isr) goto loop;
- X}
- X
- X/*
- X * Ethernet interface receiver interface.
- X * If input error just drop packet.
- X * Otherwise examine packet to determine type. If can't determine length
- X * from type, then have to drop packet. Othewise decapsulate
- X * packet based on type and pass to type specific higher-level
- X * input routine.
- X */
- Xnerecv(ns)
- X register struct ne_softc *ns;
- X{
- X int len,i;
- X
- X ns->ns_if.if_ipackets++;
- X len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
- X if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
- X return;
- X
- X /* this need not be so torturous - one/two bcopys at most into mbufs */
- X nefetch (ns, ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph)));
- X if (len > DS_PGSIZE-sizeof(ns->ns_ph)) {
- X int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b, m;
- X u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));
- X
- X for (;;) {
- X if (ns->ns_board == 1)
- X ns->ns_cur = succ2 (ns->ns_cur);
- X else
- X ns->ns_cur = succ1 (ns->ns_cur);
- X b = ns->ns_cur*DS_PGSIZE;
- X if (l >= DS_PGSIZE) {
- X nefetch (ns, p, b, DS_PGSIZE);
- X p += DS_PGSIZE; l -= DS_PGSIZE;
- X continue;
- X }
- X if (l > 0)
- X nefetch (ns, p, b, l);
- X break;
- X }
- X }
- X /* don't forget checksum! */
- X len -= sizeof(struct ether_header) + sizeof(long);
- X
- X neread(ns,(caddr_t)(ns->ns_pb), len);
- X}
- X
- X/*
- X * Pass a packet to the higher levels.
- X * We deal with the trailer protocol here.
- X */
- Xneread(ns, buf, len)
- X register struct ne_softc *ns;
- X char *buf;
- X int len;
- X{
- X register struct ether_header *eh;
- X struct mbuf *m;
- X int off, resid;
- X register struct ifqueue *inq;
- X
- X /*
- X * Deal with trailer protocol: if type is trailer type
- X * get true type from first 16-bit word past data.
- X * Remember that type was trailer by setting off.
- X */
- X eh = (struct ether_header *)buf;
- X eh->ether_type = ntohs((u_short)eh->ether_type);
- X#define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
- X if (eh->ether_type >= ETHERTYPE_TRAIL &&
- X eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
- X off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
- X if (off >= ETHERMTU) return; /* sanity */
- X eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *));
- X resid = ntohs(*(nedataaddr(eh, off+2, u_short *)));
- X if (off + resid > len) return; /* sanity */
- X len = off + resid;
- X } else off = 0;
- X
- X if (len == 0) return;
- X
- X /*
- X * Pull packet off interface. Off is nonzero if packet
- X * has trailing header; neget will then force this header
- X * information to be at the front, but we still have to drop
- X * the type and length which are at the front of any trailer data.
- X */
- X m = neget(buf, len, off, &ns->ns_if);
- X if (m == 0) return;
- X
- X ether_input(&ns->ns_if, eh, m);
- X}
- X
- X/*
- X * Supporting routines
- X */
- X
- X/*
- X * Pull read data off a interface.
- X * Len is length of data, with local net header stripped.
- X * Off is non-zero if a trailer protocol was used, and
- X * gives the offset of the trailer information.
- X * We copy the trailer information and then all the normal
- X * data into mbufs. When full cluster sized units are present
- X * we copy into clusters.
- X */
- Xstruct mbuf *
- Xneget(buf, totlen, off0, ifp)
- X caddr_t buf;
- X int totlen, off0;
- X struct ifnet *ifp;
- X{
- X struct mbuf *top, **mp, *m, *p;
- X int off = off0, len;
- X register caddr_t cp = buf;
- X char *epkt;
- X
- X buf += sizeof(struct ether_header);
- X cp = buf;
- X epkt = cp + totlen;
- X
- X
- X if (off) {
- X cp += off + 2 * sizeof(u_short);
- X totlen -= 2 * sizeof(u_short);
- X }
- X
- X MGETHDR(m, M_DONTWAIT, MT_DATA);
- X if (m == 0)
- X return (0);
- X m->m_pkthdr.rcvif = ifp;
- X m->m_pkthdr.len = totlen;
- X m->m_len = MHLEN;
- X
- X top = 0;
- X mp = ⊤
- X while (totlen > 0) {
- X if (top) {
- X MGET(m, M_DONTWAIT, MT_DATA);
- X if (m == 0) {
- X m_freem(top);
- X return (0);
- X }
- X m->m_len = MLEN;
- X }
- X len = min(totlen, epkt - cp);
- X if (len >= MINCLSIZE) {
- X MCLGET(m, M_DONTWAIT);
- X if (m->m_flags & M_EXT)
- X m->m_len = len = min(len, MCLBYTES);
- X else
- X len = m->m_len;
- X } else {
- X /*
- X * Place initial small packet/header at end of mbuf.
- X */
- X if (len < m->m_len) {
- X if (top == 0 && len + max_linkhdr <= m->m_len)
- X m->m_data += max_linkhdr;
- X m->m_len = len;
- X } else
- X len = m->m_len;
- X }
- X bcopy(cp, mtod(m, caddr_t), (unsigned)len);
- X cp += len;
- X *mp = m;
- X mp = &m->m_next;
- X totlen -= len;
- X if (cp == epkt)
- X cp = buf;
- X }
- X return (top);
- X}
- X
- X/*
- X * Process an ioctl request.
- X */
- Xneioctl(ifp, cmd, data)
- X register struct ifnet *ifp;
- X int cmd;
- X caddr_t data;
- X{
- X register struct ifaddr *ifa = (struct ifaddr *)data;
- X struct ne_softc *ns = &ne_softc[ifp->if_unit];
- X struct ifreq *ifr = (struct ifreq *)data;
- X int s = splimp(), error = 0;
- X
- X
- X switch (cmd) {
- X
- X case SIOCSIFADDR:
- X ifp->if_flags |= IFF_UP;
- X
- X switch (ifa->ifa_addr->sa_family) {
- X#ifdef INET
- X case AF_INET:
- X neinit(ifp->if_unit); /* before arpwhohas */
- X ((struct arpcom *)ifp)->ac_ipaddr =
- X IA_SIN(ifa)->sin_addr;
- X arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
- X break;
- X#endif
- X#ifdef NS
- X case AF_NS:
- X {
- X register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
- X
- X if (ns_nullhost(*ina))
- X ina->x_host = *(union ns_host *)(ns->ns_addr);
- X else {
- X /*
- X * The manual says we can't change the address
- X * while the receiver is armed,
- X * so reset everything
- X */
- X ifp->if_flags &= ~IFF_RUNNING;
- X bcopy((caddr_t)ina->x_host.c_host,
- X (caddr_t)ns->ns_addr, sizeof(ns->ns_addr));
- X }
- X neinit(ifp->if_unit); /* does ne_setaddr() */
- X break;
- X }
- X#endif
- X default:
- X neinit(ifp->if_unit);
- X break;
- X }
- X break;
- X
- X case SIOCSIFFLAGS:
- X if ((ifp->if_flags & IFF_UP) == 0 &&
- X ifp->if_flags & IFF_RUNNING) {
- X ifp->if_flags &= ~IFF_RUNNING;
- X outb(ns->ns_iobase+ds_cmd,DSCM_STOP|DSCM_NODMA);
- X } else if (ifp->if_flags & IFF_UP &&
- X (ifp->if_flags & IFF_RUNNING) == 0)
- X neinit(ifp->if_unit);
- X break;
- X
- X#ifdef notdef
- X case SIOCGHWADDR:
- X bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,
- X sizeof(ns->ns_addr));
- X break;
- X#endif
- X
- X default:
- X error = EINVAL;
- X }
- X splx(s);
- X return (error);
- X}
- X#endif
- SHAR_EOF
- $TOUCH -am 0731160392 if_ne.c &&
- chmod 0644 if_ne.c ||
- echo "restore of if_ne.c failed"
- set `wc -c if_ne.c`;Wc_c=$1
- if test "$Wc_c" != "24098"; then
- echo original size 24098, current size $Wc_c
- fi
- # ============= if_nereg.h ==============
- echo "x - extracting if_nereg.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > if_nereg.h &&
- X/*-
- X * Copyright (c) 1991 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms, with or without
- X * modification, are permitted provided that the following conditions
- X * are met:
- X * 1. Redistributions of source code must retain the above copyright
- X * notice, this list of conditions and the following disclaimer.
- X * 2. Redistributions in binary form must reproduce the above copyright
- X * notice, this list of conditions and the following disclaimer in the
- X * documentation and/or other materials provided with the distribution.
- X * 3. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the University of
- X * California, Berkeley and its contributors.
- X * 4. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X * SUCH DAMAGE.
- X *
- X * @(#)if_nereg.h 7.1 (Berkeley) 5/9/91
- X */
- X
- X/*
- X * NE2000 Ethernet Card registers
- X */
- X
- X/* The NE1000/NE2000 uses a DS8390 Ethernet controller in at the beginning of
- X its i/o space */
- X#include "ic/ds8390.h"
- X
- X#define ne_data 0x10 /* Data Transfer port */
- X#define ne_reset 0x1f /* Card Reset port */
- X
- X#define PKTSZ 0x600
- X#define TBUF(board) (0x2000 * (board)) /* Starting location of Transmit Buffer */
- X#define RBUF(board) (TBUF(board)+PKTSZ) /* Starting location of Receive Buffer */
- X#define RBUFEND(board) (0x4000 * (board)) /* Ending location of Tr ansmit Buffer */
- X
- X#define TBUF1 TBUF(1) /* Starting location of Transmit Buffer */
- X#define RBUF1 RBUF(1) /* Starting location of Receive Buffer */
- X#define RBUFEND1 RBUFEND(1) /* Ending location of Transmit Buffer */
- X#define TBUF2 TBUF(2) /* Starting location of Transmit Buffer */
- X#define RBUF2 RBUF(2) /* Starting location of Receive Buffer */
- X#define RBUFEND2 RBUFEND(2) /* Ending location of Transmit Buffer */
- X
- SHAR_EOF
- $TOUCH -am 0731160792 if_nereg.h &&
- chmod 0644 if_nereg.h ||
- echo "restore of if_nereg.h failed"
- set `wc -c if_nereg.h`;Wc_c=$1
- if test "$Wc_c" != "2982"; then
- echo original size 2982, current size $Wc_c
- fi
- exit 0
-