📄 if_qe.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_qe.c 4.5 (ULTRIX) 2/26/91";#endif lint/************************************************************************ * * * Copyright (c) 1985-89 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 * * 24-Feb-91 - jsd * Allow loopback packets if COPYALL mode is set * * 16-Nov-89 - chc * Added code to print out the station address at the system boot time. * * 14-Nov-89 - chc * Fixed the unaligned access problem for the 802.2 LLC transmit * frame. * * 27-Oct-89 - Uttam Shikarpur * Added: * 1) Ability to report back the type of network interface * we are running on. * 2) Counters to keep track of the multicast pack., bytes sent. * * 20-OCT-89 - chc * Added code to fixed the mapping register release problem * Changed the mapping register information mask ( form 21 to * 22 ) * * 31-Aug-89 - chc * Added code to restart the qe under the non-existant memory * condition * Modified the code in order to support MIPS processor * * 3-May-89 Uttam Shikarpur * Add support for Ethernet packet filter * Moved common read code to ../net/ether_read.c * * 06-Mar-89 - Lea Gottfredsen * Correct decnet counters not to include sizeof ethernet header * * 05-Dec-88 - robin * Changed the code that used the output of qballoc because the * format of the way map registers is coded in the return value * changed. * * 29-Jun-88 - Fred L. Templin * Added code to the qeoutput() routine to prevent qeoutput from * running if the interface has not yet been marked as "IFF_UP" * and "IFF_RUNNING". * * 15-Jan-88 - lp * Reworked how softc gets allocated. Also fixed driver to use new * larger mbufs. * * 26-Feb-87 -- jsd * Check return of iftype_to_proto so that we don't jump to 0. * Also, restored Ed Ferris DECnet fix from 04-Jan-87 that got zapped * * 06-Jan-87 -- robin * changed the way transmit and receive rings are mapped. The * old method used a loop and called the allocation routine in each * iteration, this wasted a map register (fire wall) on each call. * the new way makes one allocation call and the divides the mapped * area up, this saves the wasted fire walls (except one). * * 04-Jan-87 -- ejf * Fix to DECnet receive bytes/packets counters. * * 02-Sept-86 -- ejf * Fixed problem where qe driver was not properly handling packets * with an odd number of bytes less than the minimum packet size. * Also, added code in interrupt routine to validate transmit list * if it became invalid while there were still outstanding transmit * buffers. * * 13-Jun-86 -- jaw fix to uba reset and drivers. * * 19-May-86 -- Chase * Added code to free up mbufs left in the transmit ring after a * lockup. Failure to do this may cause systems under a heavy * network load to run out of mbufs. * * 06-May-86 -- larry * increase QETIMO to 1 second which implies 3 seconds till a qerestart. * clear RESET bit in qeprobe and qerestart so the LQA will work. * * 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 || defined(BINARY)/* * Digital Q-BUS to NI Adapter */#include "packetfilter.h" /* NPACKETFILTER */#include "../data/if_qe_data.c"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern int net_output();extern struct timeval time;extern timeout();int qeprobe(), qeattach(), qeint(), qewatch();int qeinit(),qestart(),qeioctl(),qereset(),qewatch();struct mbuf *qeget();u_short qestd[] = { 0 };struct uba_driver qedriver = { qeprobe, 0, qeattach, 0, qestd, "qe", qeinfo };u_char qunused_multi[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };u_char qe_multi[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define OMASK 0x1ff#define REGMASK 0x1fff#define NREGMASK 0x1ff#define QBAI_MR(i) ((int)((i) >> 9) & REGMASK)#define QBAI_NMR(i) ((int)((i) >> 22) & NREGMASK)#define QE_TIMEO (1 * hz)#define QEUNIT(x) minor(x)static int mask = 0x1fffff; /* address mask */int qewatchrun = 0; /* watchdog running */int qe_show_restarts = 0; /* restart diagnosis */ int qe_runt = 0;/* * The deqna shouldn't recieve 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) caddr_t reg;{#ifdef vax register struct qedevice *addr = (struct qedevice *)reg;#endif vax#ifdef mips volatile struct qedevice *addr = (struct qedevice *)reg;#endif mips register struct qe_ring *rp; register struct qe_ring *prp; /* physical rp */ register int i, j, ncl; register struct qe_softc *sc; struct uba_hd *uh = uba_hd; /* only one bus so no index here */ int unit; KM_ALLOC(sc,struct qe_softc *,sizeof(struct qe_softc),KM_DEVBUF,KM_CLEAR|KM_CONTIG|KM_CALL); qe_softc[nNQE] = sc; unit = nNQE++; /* * Set the address mask for the particular cpu */ if( uba_hd[numuba].uba_type&UBAUVI ) mask = 0x3fffff; else mask = 0x1fffff; /* * 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_vector = (uba_hd[numuba].uh_lastiv -= 4); /* * Map the communications area and the setup packet. */ sc->setupaddr = qballoc(0, sc->setup_pkt, sizeof(sc->setup_pkt), 0); sc->rringaddr = (struct qe_ring *) qballoc(0, sc->rring, sizeof(struct qe_ring)*(nNTOT+2),0); prp = (struct qe_ring *)((int)sc->rringaddr & mask); addr->qe_csr &= ~QE_RESET; /* * 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, sc->setupaddr & mask, sizeof(sc->setup_pkt)); qeinitdesc( sc->rring, sc->setupaddr & mask, 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] = (u_char)addr->qe_sta_addr[i]; qesetup( sc ); /* * Start the interface and wait for the packet. */ j = cvec; 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 += nNRCV+1; addr->qe_xmtlist_lo = (short)prp; addr->qe_xmtlist_hi = (short)((int)prp >> 16); DELAY(10000); /* * All done with the bus resources. If it's a uVAX-I they weren't * really allocated otherwise deallocated them. */ if((uba_hd[numuba].uba_type&UBAUVI) == 0 ) { qbarelse(0, &sc->setupaddr); qbarelse(0, &sc->rringaddr); } if( cvec == j ) return 0; /* didn't interrupt */ /* * Allocate page size buffers now. If we wait until the network * is setup they have already fragmented. By doing it here in * conjunction with always coping on uVAX-I processors we obtain * physically contigous buffers for dma transfers. */ ncl = clrnd((int)btoc(MAXPACKETSIZE) + CLSIZE) / CLSIZE; KM_ALLOC(sc->buffers, char *, nNTOT*ncl*CLBYTES, KM_DEVBUF, KM_NOWAIT|KM_CONTIG|KM_CALL); if(sc->buffers == NULL) panic("noncontig alloc in qe"); 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->is_if;#ifdef vax register struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif vax#ifdef mips volatile struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif mips register int i; struct sockaddr_in *sin; int nb; ifp->if_unit = ui->ui_unit; ifp->if_name = "qe"; ifp->if_mtu = ETHERMTU; ifp->if_type = IFT_ETHER; ifp->if_flags |= IFF_BROADCAST | IFF_DYNPROTO; ((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0; /* * Read the address from the prom and save it. */ for( i=0 ; i<6 ; i++ ) sc->setup_pkt[i][1] = sc->is_addr[i] = (u_char)addr->qe_sta_addr[i]; /* * Save the vector for initialization at reset time. */ sc->qe_intvec = addr->qe_vector; sin = (struct sockaddr_in *)&ifp->if_addr; sin->sin_family = AF_INET; ifp->if_init = qeinit; ifp->if_output = net_output; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_reset = qereset; addr->qe_vector |= 1; if(addr->qe_vector & 01) { ifp->if_sysid_type = 37; if(addr->qe_vector & 0x8000) { bcopy("DEC DELQA Ethernet Interface Normal Mode", ifp->if_version, 40); nb = 40; } else { bcopy("DEC DELQA Ethernet Interface DEQNA-lock Mode", ifp->if_version, 44); nb = 44; } } else { ifp->if_sysid_type = 5; bcopy("DEC DEQNA Ethernet Interface", ifp->if_version, 28); nb = 28; } ifp->if_version[nb] = '\0'; printf("qe%d: %s, hardware address %s\n", ui->ui_unit, ifp->if_version, ether_sprintf(sc->is_addr)); addr->qe_vector &= ~1;#if NPACKETFILTER > 0 /* Tell the packet filter we are here */ attachpfilter(&(sc->qe_ed));#endif NPACKETFILTER if_attach(ifp);#ifdef mips ifp->if_snd.ifq_maxlen = 1000;#endif mips}/* * 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 >= nNQE || (ui = qeinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" qe%d", unit); qeinit(unit);} /* * Initialization of interface. */qeinit(unit) int unit;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -