📄 if_dmc.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_dmc.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* ------------------------------------------------------------------------ * Modification History: /sys/vaxif/if_dmc.c * * 29-nov-88 -- jaw remove sysproc stuff. * * 02-mar-87 -- ejf check address of protocol switch routines before * calling them. * * 04-jan-86 -- ejf fixed problem whereby DECnet counters were being * zeroed whenever the line cycled. * * 16-dec-86 -- ejf manipulate Tx Q at splimp, not spl5. * * 18-apr-86 -- ejf added DECnet support. * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * 03/12/86 -- Chet Juszczak * Modify MCLGET macro call to match new definition * * 09/16/85 -- Larry Cohen * Add 43bsd alpha tape changes for subnet routing * * 19-Jun-85 -- jaw * VAX8200 name change. * * 13 Mar 85 -- jaw * add support for VAX 8200 and bua * * 29 Oct 84 -- jrs * Update with latest version (1.12) from: * Bill Nesheim (Cornell) * Lou Salkind (NYU) * * Derived from 4.2BSD, labeled: * if_dmc.c 6.1 83/07/29 * * ----------------------------------------------------------------------- */#include "dmc.h"#if NDMC > 0 || defined(BINARY)/* * DMC11 device driver, internet version *//* #define DEBUG /* for base table dump on fatal error */#include "../data/if_dmc_data.c"int dmctimer; /* timer started? */int dmc_timeout = 25; /* timeout value */int dmcwatch();#define printd if(dmcdebug)printfint dmcdebug = 0;/* error reporting intervals */#define DMC_RPNBFS 50#define DMC_RPDSC 50#define DMC_RPTMO 10#define DMC_RPDCK 10struct mbuf *dmc_get();extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern struct timeval time;extern int boot_cpu_mask;/* * DMC software status per interface. * * Each interface is referenced by a network interface structure, * sc_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 set of 7 UBA interface structures * for each, which * contain 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. *//* flags */#define DMC_ALLOC 01 /* unibus resources allocated */#define DMC_BMAPPED 02 /* base table mapped */#define DMC_RESTART 04 /* software restart in progress */#define DMC_ACTIVE 08 /* device active *//* * Driver information for auto-configuration stuff. */int dmcprobe(), dmcattach(), dmcinit(), dmcioctl();int dmcoutput(), dmcreset();u_short dmcstd[] = { 0 };struct uba_driver dmcdriver = { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };/* * dmc software packet encapsulation. This allows the dmc * link to be multiplexed among several protocols. * The first eight bytes of the dmc header are garbage, * since on a vax the uba has been known to mung these * bytes. The next two bytes encapsulate packet type. */struct dmc_header { char dmc_buf[8]; /* space for uba on vax */ short dmc_type; /* encapsulate packet type */};/* queue manipulation macros */#define QUEUE_AT_HEAD(qp, head, tail) \ (qp)->qp_next = (head); \ (head) = (qp); \ if((tail) == (struct dmc_command *) 0) \ (tail) = (head) #define QUEUE_AT_TAIL(qp, head, tail) \ if((tail)) \ (tail)->qp_next = (qp); \ else \ (head) = (qp); \ (qp)->qp_next = (struct dmc_command *) 0; \ (tail) = (qp)#define DEQUEUE(head, tail) \ (head) = (head)->qp_next;\ if((head) == (struct dmc_command *) 0)\ (tail) = (head)dmcprobe(reg) caddr_t reg;{ register struct dmcdevice *addr = (struct dmcdevice *)reg; register int i;#ifdef lint dmcrint(0); dmcxint(0);#endif addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; if ((addr->bsel1 & DMC_RUN) == 0) { printf("dmcprobe: can't start device\n" ); return (0); } addr->bsel0 = DMC_RQI|DMC_IEI; /* let's be paranoid */ addr->bsel0 |= DMC_RQI|DMC_IEI; DELAY(1000000); addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; return (1);}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */dmcattach(ui) register struct uba_device *ui;{ register struct dmc_softc *sc = &dmc_softc[ui->ui_unit]; struct dmcdevice *addr = (struct dmcdevice *)dmcinfo[ui->ui_unit]->ui_addr; sc->sc_if.if_unit = ui->ui_unit; sc->sc_if.if_name = "dmc"; sc->sc_if.if_mtu = DMCMTU; sc->sc_if.if_init = dmcinit; sc->sc_if.if_output = dmcoutput; sc->sc_if.if_ioctl = dmcioctl; sc->sc_if.if_reset = dmcreset; sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_DYNPROTO; sc->sc_if.d_affinity = boot_cpu_mask; sc->sc_ifuba.ifu_flags = UBA_CANTWAIT; bzero(&sc->sc_dmccs, sizeof(sc->sc_dmccs)); bzero(sc->sc_basectrs, sizeof(sc->sc_basectrs)); bzero(sc->sc_errctrs, sizeof(sc->sc_errctrs)); sc->sc_dmccs.if_family = AF_UNSPEC; sc->sc_dmccs.if_next_family = AF_UNSPEC; sc->sc_dmccs.if_mode = ui->ui_flags; if ( (sc->sc_bufres.dmrdev = dmc_is_dmr(addr)) && (sc->sc_bufres.nxmt = ((NXMT_MASK & ui->ui_flags) >> NXMT_SHIFT)) > NXMT_MIN ) { if (sc->sc_bufres.nxmt > NXMT_MAX) sc->sc_bufres.nxmt = NXMT_MAX; } else sc->sc_bufres.nxmt = NXMT_MIN; sc->sc_bufres.nrcv = NRCV; sc->sc_bufres.ntot = sc->sc_bufres.nrcv + sc->sc_bufres.nxmt; sc->sc_bufres.ncmds = sc->sc_bufres.ntot + 4; if_attach(&sc->sc_if); if (dmctimer == 0) { dmctimer = 1; timeout(dmcwatch, (caddr_t) 0, hz); }}/* * Check to see if device is a dmc or dmr. * Return 0 if dmc, return 1 if dmr. */dmc_is_dmr(addr)struct dmcdevice *addr;{ int i; addr->bsel3 = DMC_DMRCHK; addr->bsel1 = DMC_MCLR; for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) ; if ((addr->bsel1 & DMC_RUN) == 0) { printf("dmc_is_dmr: can't start device\n" ); return (0); } switch ( addr->bsel3 & DMR_MASK ) { case DMR_0001: case DMR_0002: case DMR_0100: case DMR_0200: return(1); default: return(0); }}/* * Reset of interface after UNIBUS reset. * If interface is on specified UBA, reset it's state. */dmcreset(unit, uban) int unit, uban;{ register struct uba_device *ui; register struct dmc_softc *sc = &dmc_softc[unit]; if (unit >= nNDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" dmc%d", unit); sc->sc_flag = 0; dmcinit(unit);}/* * Initialization of interface; reinitialize UNIBUS usage. */dmcinit(unit) int unit;{ register struct dmc_softc *sc = &dmc_softc[unit]; register struct uba_device *ui = dmcinfo[unit]; register struct dmcdevice *addr; register struct ifnet *ifp = &sc->sc_if; register struct ifrw *ifrw; register struct ifxmt *ifxp; register struct dmcbufs *rp; register struct dmc_command *qp; register struct ifaddr *ifa; int base; int s; addr = (struct dmcdevice *)ui->ui_addr; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) break; if (ifa == (struct ifaddr *) 0) return; if((addr->bsel1&DMC_RUN) == 0) { printf("dmcinit: DMC not running\n"); ifp->if_flags &= ~(IFF_RUNNING|IFF_UP); return; } /* map base table */ if ((sc->sc_flag & DMC_BMAPPED) == 0) { sc->sc_ubinfo = uballoc(ui->ui_ubanum, (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0); sc->sc_flag |= DMC_BMAPPED; } /* initialize UNIBUS resources */ sc->sc_iused = sc->sc_oused = 0; if ((sc->sc_flag & DMC_ALLOC) == 0) { if (dmc_ubainit(&sc->sc_ifuba, ui->ui_ubanum, sizeof(struct dmc_header), (int)btoc(DMCMTU), &sc->sc_bufres) == 0) { printf("dmc%d: can't initialize\n", unit); ifp->if_flags &= ~IFF_UP; return; } sc->sc_flag |= DMC_ALLOC; } /* initialize buffer pool */ /* recieves */ ifrw= &sc->sc_ifuba.ifu_r[0]; for(rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[sc->sc_bufres.nrcv]; rp++) { rp->ubinfo = ifrw->ifrw_info & 0x3ffff; rp->cc = DMCMTU + sizeof (struct dmc_header); rp->flags = DBUF_OURS|DBUF_RCV; ifrw++; } /* transmits */ ifxp= &sc->sc_ifuba.ifu_w[0]; for(rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[sc->sc_bufres.nxmt]; rp++) { rp->ubinfo = ifxp->x_ifrw.ifrw_info & 0x3ffff; rp->cc = 0; rp->flags = DBUF_OURS|DBUF_XMIT; ifxp++; } /* set up command queues */ sc->sc_qfreeh = sc->sc_qfreet = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = (struct dmc_command *)0; /* set up free command buffer list */ for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[sc->sc_bufres.ncmds]; qp++) { QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); } /* * if coming through for the first time, zero out counters. * else remember counters */ if ( ! (ifp->if_flags & IFF_RUNNING) ) { sc->sc_ztime = time.tv_sec; bzero(&sc->sc_rxtxctrs[DMCZ_RXBYTE], sizeof(sc->sc_rxtxctrs)); bzero(sc->sc_errctrs, sizeof(sc->sc_errctrs)); } else dmc_update_errctrs(sc, (u_char *) &dmc_base[unit].d_base[0]); bzero(sc->sc_basectrs, sizeof(sc->sc_basectrs)); /* set up internal loopback if requested */ if ( ifp->if_flags & IFF_LOOPBACK ) addr->bsel1 |= DMC_ILOOP; /* base in */ base = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM); /* specify half duplex operation, flags tell if primary */ /* or secondary station */ if (sc->sc_dmccs.if_mode == 0) /* use DDMCP mode in full duplex */ dmcload(sc, DMC_CNTLI, 0, 0); else if (sc->sc_dmccs.if_mode == 1) /* use MAINTENENCE mode */ dmcload(sc, DMC_CNTLI, 0, DMC_MAINT ); else if (sc->sc_dmccs.if_mode == 2) /* use DDCMP half duplex as primary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX); else if (sc->sc_dmccs.if_mode == 3) /* use DDCMP half duplex as secondary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC); /* enable operation done interrupts */ sc->sc_flag &= ~DMC_ACTIVE; while ((addr->bsel2 & DMC_IEO) == 0) addr->bsel2 |= DMC_IEO; s = splimp(); /* queue first NRCV buffers for DMC to fill */ for(rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[sc->sc_bufres.nrcv]; rp++) { rp->flags |= DBUF_DMCS; dmcload(sc, DMC_READ, rp->ubinfo, (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc)); sc->sc_iused++; } splx(s); ifp->if_flags |= IFF_UP|IFF_RUNNING; if ( sc->sc_dmccs.if_mode == IFS_MOP ) ifp->if_flags |= IFF_MOP; else ifp->if_flags &= ~IFF_MOP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -