📄 if_de.c
字号:
/* * Copyright (c) 1982, 1986, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_de.c 7.12 (Berkeley) 12/16/90 */#include "de.h"#if NDE > 0/* * DEC DEUNA interface * * Lou Salkind * New York University * * TODO: * timeout routine (get statistics) */#include "../include/pte.h"#include "sys/param.h"#include "sys/systm.h"#include "sys/mbuf.h"#include "sys/buf.h"#include "sys/protosw.h"#include "sys/socket.h"#include "sys/vmmac.h"#include "sys/ioctl.h"#include "sys/errno.h"#include "sys/syslog.h"#include "net/if.h"#include "net/netisr.h"#include "net/route.h"#ifdef INET#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#endif#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#ifdef ISO#include "netiso/iso.h"#include "netiso/iso_var.h"extern char all_es_snpa[], all_is_snpa[];#endif#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_dereg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#define NXMT 3 /* number of transmit buffers */#define NRCV 7 /* number of receive buffers (must be > 1) */int dedebug = 0;int deprobe(), deattach(), deintr();struct uba_device *deinfo[NDE];u_short destd[] = { 0 };struct uba_driver dedriver = { deprobe, 0, deattach, 0, destd, "de", deinfo };int deinit(),ether_output(),deioctl(),dereset(),destart();/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * ds_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */struct de_softc { struct arpcom ds_ac; /* Ethernet common part */#define ds_if ds_ac.ac_if /* network-visible interface */#define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ int ds_flags;#define DSF_RUNNING 2 /* board is enabled */#define DSF_SETADDR 4 /* physical address is changed */ int ds_ubaddr; /* map info for incore structs */ struct ifubinfo ds_deuba; /* unibus resource structure */ struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ /* the following structures are always mapped in */ struct de_pcbb ds_pcbb; /* port control block */ struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ /* end mapped area */#define INCORE_BASE(p) ((char *)&(p)->ds_pcbb)#define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))#define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))#define PCBB_OFFSET RVAL_OFF(ds_pcbb)#define XRENT_OFFSET LVAL_OFF(ds_xrent)#define RRENT_OFFSET LVAL_OFF(ds_rrent)#define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf)#define INCORE_SIZE RVAL_OFF(ds_xindex) int ds_xindex; /* UNA index into transmit chain */ int ds_rindex; /* UNA index into receive chain */ int ds_xfree; /* index for next transmit buffer */ int ds_nxmit; /* # of transmits in progress */} de_softc[NDE];deprobe(reg) caddr_t reg;{ register int br, cvec; /* r11, r10 value-result */ register struct dedevice *addr = (struct dedevice *)reg; register i;#ifdef lint br = 0; cvec = br; br = cvec; i = 0; derint(i); deintr(i);#endif /* * Make sure self-test is finished before we screw with the board. * Self-test on a DELUA can take 15 seconds (argh). */ for (i = 0; i < 160 && (addr->pcsr0 & PCSR0_FATI) == 0 && (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; ++i) DELAY(100000); if ((addr->pcsr0 & PCSR0_FATI) != 0 || (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) return(0); addr->pcsr0 = 0; DELAY(100); addr->pcsr0 = PCSR0_RSET; while ((addr->pcsr0 & PCSR0_INTR) == 0) ; /* make board interrupt by executing a GETPCBB command */ addr->pcsr0 = PCSR0_INTE; addr->pcsr2 = 0; addr->pcsr3 = 0; addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; DELAY(100000); return(1);}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. We get the ethernet address here. */deattach(ui) struct uba_device *ui;{ register struct de_softc *ds = &de_softc[ui->ui_unit]; register struct ifnet *ifp = &ds->ds_if; register struct dedevice *addr = (struct dedevice *)ui->ui_addr; int csr1; ifp->if_unit = ui->ui_unit; ifp->if_name = "de"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * What kind of a board is this? * The error bits 4-6 in pcsr1 are a device id as long as * the high byte is zero. */ csr1 = addr->pcsr1; if (csr1 & 0xff60) printf("de%d: broken\n", ui->ui_unit); else if (csr1 & 0x10) printf("de%d: delua\n", ui->ui_unit); else printf("de%d: deuna\n", ui->ui_unit); /* * Reset the board and temporarily map * the pcbb buffer onto the Unibus. */ addr->pcsr0 = 0; /* reset INTE */ DELAY(100); addr->pcsr0 = PCSR0_RSET; (void)dewait(ui, "reset"); ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, sizeof (struct de_pcbb), 0); addr->pcsr2 = ds->ds_ubaddr & 0xffff; addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; addr->pclow = CMD_GETPCBB; (void)dewait(ui, "pcbb"); ds->ds_pcbb.pcbb0 = FC_RDPHYAD; addr->pclow = CMD_GETCMD; (void)dewait(ui, "read addr "); ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, sizeof (ds->ds_addr)); printf("de%d: hardware address %s\n", ui->ui_unit, ether_sprintf(ds->ds_addr)); ifp->if_init = deinit; ifp->if_output = ether_output; ifp->if_ioctl = deioctl; ifp->if_reset = dereset; ifp->if_start = destart; ds->ds_deuba.iff_flags = UBA_CANTWAIT;#ifdef notdef /* CAN WE USE BDP's ??? */ ds->ds_deuba.iff_flags |= UBA_NEEDBDP;#endif if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */dereset(unit, uban) int unit, uban;{ register struct uba_device *ui; if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" de%d", unit); de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); de_softc[unit].ds_flags &= ~DSF_RUNNING; ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; (void)dewait(ui, "reset"); deinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */deinit(unit) int unit;{ register struct de_softc *ds = &de_softc[unit]; register struct uba_device *ui = deinfo[unit]; register struct dedevice *addr; register struct ifrw *ifrw; register struct ifxmt *ifxp; struct ifnet *ifp = &ds->ds_if; int s; struct de_ring *rp; int incaddr; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ds->ds_flags & DSF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(ETHERMTU), ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { printf("de%d: can't initialize\n", unit); ds->ds_if.if_flags &= ~IFF_UP; return; } ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), INCORE_SIZE, 0); } addr = (struct dedevice *)ui->ui_addr; /* set the pcbb block address */ incaddr = ds->ds_ubaddr + PCBB_OFFSET; addr->pcsr2 = incaddr & 0xffff; addr->pcsr3 = (incaddr >> 16) & 0x3; addr->pclow = 0; /* reset INTE */ DELAY(100); addr->pclow = CMD_GETPCBB; (void)dewait(ui, "pcbb"); /* set the transmit and receive ring header addresses */ incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; ds->ds_pcbb.pcbb0 = FC_WTRING; ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; incaddr = ds->ds_ubaddr + XRENT_OFFSET; ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_trlen = NXMT; incaddr = ds->ds_ubaddr + RRENT_OFFSET; ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); ds->ds_udbbuf.b_rrlen = NRCV; addr->pclow = CMD_GETCMD; (void)dewait(ui, "wtring"); /* initialize the mode - enable hardware padding */ ds->ds_pcbb.pcbb0 = FC_WTMODE; /* let hardware do padding - set MTCH bit on broadcast */ ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; addr->pclow = CMD_GETCMD; (void)dewait(ui, "wtmode"); /* set up the receive and transmit ring entries */ ifxp = &ds->ds_ifw[0]; for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { rp->r_segbl = ifxp->ifw_info & 0xffff; rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; rp->r_flags = 0; ifxp++; } ifrw = &ds->ds_ifr[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -