📄 if_qe.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Digital Equipment Corp. * * 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_qe.c 7.21 (Berkeley) 5/4/92 *//* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 *//**************************************************************** * * * Licensed from Digital Equipment Corporation * * Copyright (c) * * Digital Equipment Corporation * * Maynard, Massachusetts * * 1985, 1986 * * All rights reserved. * * * * The Information in this software is subject to change * * without notice and should not be construed as a commitment * * by Digital Equipment Corporation. Digital makes no * * representations about the suitability of this software for * * any purpose. It is supplied "As Is" without expressed or * * implied warranty. * * * * If the Regents of the University of California or its * * licensees modify the software in a manner creating * * derivative copyright rights, appropriate copyright * * legends may be placed on the derivative work in addition * * to that set forth above. * * * ****************************************************************//* --------------------------------------------------------------------- * Modification History * * 15-Apr-86 -- afd * Rename "unused_multi" to "qunused_multi" for extending Generic * kernel to MicroVAXen. * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * 12 March 86 -- Jeff Chase * Modified to handle the new MCLGET macro * Changed if_qe_data.c to use more receive buffers * Added a flag to poke with adb to log qe_restarts on console * * 19 Oct 85 -- rjl * Changed the watch dog timer from 30 seconds to 3. VMS is using * less than 1 second in their's. Also turned the printf into an * mprintf. * * 09/16/85 -- Larry Cohen * Add 43bsd alpha tape changes for subnet routing * * 1 Aug 85 -- rjl * Panic on a non-existent memory interrupt and the case where a packet * was chained. The first should never happen because non-existant * memory interrupts cause a bus reset. The second should never happen * because we hang 2k input buffers on the device. * * 1 Aug 85 -- rich * Fixed the broadcast loopback code to handle Clusters without * wedging the system. * * 27 Feb. 85 -- ejf * Return default hardware address on ioctl request. * * 12 Feb. 85 -- ejf * Added internal extended loopback capability. * * 27 Dec. 84 -- rjl * Fixed bug that caused every other transmit descriptor to be used * instead of every descriptor. * * 21 Dec. 84 -- rjl * Added watchdog timer to mask hardware bug that causes device lockup. * * 18 Dec. 84 -- rjl * Reworked driver to use q-bus mapping routines. MicroVAX-I now does * copying instead of m-buf shuffleing. * A number of deficencies in the hardware/firmware were compensated * for. See comments in qestart and qerint. * * 14 Nov. 84 -- jf * Added usage counts for multicast addresses. * Updated general protocol support to allow access to the Ethernet * header. * * 04 Oct. 84 -- jf * Added support for new ioctls to add and delete multicast addresses * and set the physical address. * Add support for general protocols. * * 14 Aug. 84 -- rjl * Integrated Shannon changes. (allow arp above 1024 and ? ) * * 13 Feb. 84 -- rjl * * Initial version of driver. derived from IL driver. * * --------------------------------------------------------------------- */#include "qe.h"#if NQE > 0/* * Digital Q-BUS to NI Adapter */#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 "sys/time.h"#include "sys/kernel.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[], all_l1is_snpa[], all_l2is_snpa[];#endif#include "../include/pte.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_qereg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#if NQE == 1 && !defined(QNIVERT)#define NRCV 15 /* Receive descriptors */#else#define NRCV 10 /* Receive descriptors */#endif#define NXMT 5 /* Transmit descriptors */#define NTOT (NXMT + NRCV)#define QETIMEOUT 2 /* transmit timeout, must be > 1 */#define QESLOWTIMEOUT 40 /* timeout when no xmits in progress */#define MINDATA 60/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * qe_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct qe_softc { struct arpcom qe_ac; /* Ethernet common part */#define qe_if qe_ac.ac_if /* network-visible interface */#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */ struct ifubinfo qe_uba; /* Q-bus resources */ struct ifrw qe_ifr[NRCV]; /* for receive buffers; */ struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */ int qe_flags; /* software state */#define QEF_RUNNING 0x01#define QEF_SETADDR 0x02#define QEF_FASTTIMEO 0x04 int setupaddr; /* mapping info for setup pkts */ int ipl; /* interrupt priority */ struct qe_ring *rringaddr; /* mapping info for rings */ struct qe_ring *tringaddr; /* "" */ struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */ struct qe_ring tring[NXMT+1]; /* Transmit ring descriptors */ u_char setup_pkt[16][8]; /* Setup packet */ int rindex; /* Receive index */ int tindex; /* Transmit index */ int otindex; /* Old transmit index */ int qe_intvec; /* Interrupt vector */ struct qedevice *addr; /* device addr */ int setupqueued; /* setup packet queued */ int nxmit; /* Transmits in progress */ int qe_restarts; /* timeouts */} qe_softc[NQE];struct uba_device *qeinfo[NQE];extern struct timeval time;int qeprobe(), qeattach(), qeintr(), qetimeout();int qeinit(), qeioctl(), qereset(), qestart();u_short qestd[] = { 0 };struct uba_driver qedriver = { qeprobe, 0, qeattach, 0, qestd, "qe", qeinfo };#define QEUNIT(x) minor(x)/* * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) * but will actually take in up to 2048 bytes. To guard against the receiver * chaining buffers (which we aren't prepared to handle) we allocate 2kb * size buffers. */#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU *//* * Probe the QNA to see if it's there */qeprobe(reg, ui) caddr_t reg; struct uba_device *ui;{ register int br, cvec; /* r11, r10 value-result */ register struct qedevice *addr = (struct qedevice *)reg; register struct qe_ring *rp; register struct qe_ring *prp; /* physical rp */ register int i; register struct qe_softc *sc = &qe_softc[ui->ui_unit];#ifdef lint br = 0; cvec = br; br = cvec; qeintr(0);#endif /* * The QNA interrupts on i/o operations. To do an I/O operation * we have to setup the interface by transmitting a setup packet. */ addr->qe_csr = QE_RESET; addr->qe_csr &= ~QE_RESET; addr->qe_vector = (uba_hd[numuba].uh_lastiv -= 4); /* * Map the communications area and the setup packet. */ sc->setupaddr = uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0); prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr); /* * The QNA will loop the setup packet back to the receive ring * for verification, therefore we initialize the first * receive & transmit ring descriptors and link the setup packet * to them. */ qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr), sizeof(sc->setup_pkt)); qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr), sizeof(sc->setup_pkt)); rp = (struct qe_ring *)sc->tring; rp->qe_setup = 1; rp->qe_eomsg = 1; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; rp = (struct qe_ring *)sc->rring; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; /* * Get the addr off of the interface and place it into the setup * packet. This code looks strange due to the fact that the address * is placed in the setup packet in col. major order. */ for( i = 0 ; i < 6 ; i++ ) sc->setup_pkt[i][1] = addr->qe_sta_addr[i]; qesetup( sc ); /* * Start the interface and wait for the packet. */ (void) spl6(); addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT; addr->qe_rcvlist_lo = (short)prp; addr->qe_rcvlist_hi = (short)((int)prp >> 16); prp += NRCV+1; addr->qe_xmtlist_lo = (short)prp; addr->qe_xmtlist_hi = (short)((int)prp >> 16); DELAY(10000); /* * All done with the bus resources. */ ubarelse(0, &sc->setupaddr); ubarelse(0, (int *)&sc->rringaddr); sc->ipl = br = qbgetpri(); return( sizeof(struct qedevice) );}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */qeattach(ui) struct uba_device *ui;{ register struct qe_softc *sc = &qe_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->qe_if; register struct qedevice *addr = (struct qedevice *)ui->ui_addr; register int i; ifp->if_unit = ui->ui_unit; ifp->if_name = "qe"; ifp->if_mtu = ETHERMTU; /* * The Deqna is cable of transmitting broadcasts, but * doesn't listen to its own. */ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* * Read the address from the prom and save it. */ for( i=0 ; i<6 ; i++ ) sc->setup_pkt[i][1] = sc->qe_addr[i] = addr->qe_sta_addr[i] & 0xff; addr->qe_vector |= 1; printf("qe%d: %s, hardware address %s\n", ui->ui_unit, addr->qe_vector&01 ? "delqa":"deqna", ether_sprintf(sc->qe_addr)); addr->qe_vector &= ~1; /* * Save the vector for initialization at reset time. */ sc->qe_intvec = addr->qe_vector; ifp->if_init = qeinit; ifp->if_output = ether_output; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_reset = qereset; ifp->if_watchdog = qetimeout; sc->qe_uba.iff_flags = UBA_CANTWAIT; if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */qereset(unit, uban) int unit, uban;{ register struct uba_device *ui; if (unit >= NQE || (ui = qeinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" qe%d", unit); qe_softc[unit].qe_if.if_flags &= ~IFF_RUNNING; qeinit(unit);}/* * Initialization of interface. */qeinit(unit) int unit;{ register struct qe_softc *sc = &qe_softc[unit]; register struct uba_device *ui = qeinfo[unit]; register struct qedevice *addr = (struct qedevice *)ui->ui_addr; register struct ifnet *ifp = &sc->qe_if; register i; int s; /* address not known */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (sc->qe_flags & QEF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { /* * map the communications area onto the device */ i = uballoc(0, (caddr_t)sc->rring, sizeof(struct qe_ring) * (NTOT+2), 0); if (i == 0) goto fail; sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i); sc->tringaddr = sc->rringaddr + NRCV + 1; i = uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); if (i == 0) goto fail; sc->setupaddr = UBAI_ADDR(i); /* * init buffers and maps */ if (if_ubaminit(&sc->qe_uba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) { fail: printf("qe%d: can't allocate uba resources\n", unit); sc->qe_if.if_flags &= ~IFF_UP; return; } } /* * Init the buffer descriptors and indexes for each of the lists and * loop them back to form a ring. */ for (i = 0; i < NRCV; i++) { qeinitdesc( &sc->rring[i], (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE); sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; } qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0); sc->rring[i].qe_addr_lo = (short)sc->rringaddr; sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16); sc->rring[i].qe_chain = 1; sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; for( i = 0 ; i <= NXMT ; i++ ) qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0); i--; sc->tring[i].qe_addr_lo = (short)sc->tringaddr; sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16); sc->tring[i].qe_chain = 1; sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; sc->tring[i].qe_valid = 1; sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; /* * Take the interface out of reset, program the vector, * enable interrupts, and tell the world we are up. */ s = splimp(); addr->qe_vector = sc->qe_intvec; sc->addr = addr; addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -