📄 if_ni.c
字号:
/* * if_ni.c */#ifndef lintstatic char *sccsid = "@(#)if_ni.c 4.3 ULTRIX 3/7/91";#endif lint/************************************************************************ * * * Copyright (c) 1986-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. * * * * 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. * * * ************************************************************************/#include "bvpni.h"#if NBVPNI > 0 || defined(BINARY)/* Modification History: * * 24-Feb-91 - jsd * Allow loopback packets if COPYALL mode is set * * 28-Oct-89 - Uttam Shikarpur * Added: * 1) Reporting counters for multicast packs. and bytes * 2) Ability to report back the type of network interface. * * 3-May-89 Uttam Shikarpur * Add support for Ethernet packet filter * Moved common read code to ../net/ether_read.c * * 3-Mar-89 U. Sinkewicz * Picked up R. Bhanukitsiri changes for pmax/vax. * * 28-Dec-88 Fred L. Templin * Rearranged "nistart" to schedule an interrupt for every datagram * sent. (Instead of just NFS and broadcast loopbacks as was done * before). This prevents temporary transmit-side livelocks in the * case of many transmits enqueued WITHOUT any receive datagrams * to trigger an interrupt. * * 16-Sep-88 condylis * Unlocked lk_ni_softc during call to m_freem in nirecv to permit * the acquisition of locks in the free routine specified in * the mclgetx call for the mbuf * * 22-Aug-88 U. Sinkewicz * Changed flags to KM_ALLOC calls to prevent any possibility of * sleeping. Needed for SMP. * * 22-Jun-88 Fred L. Templin * Moved m_compress() code into the nistart routine, and used MCLGET * instead of messing around with little mbuf's, since the old scheme * could possibly leave you with a chain that's still too long to be * mapped onto a command queue entry. Fixed another bug in which the * start routine wasn't checking to see if an mbuf was actually a * cluster-type mbuf before checking the m_cltype field. This could * possibly generate unnecessary interrupts for non-cluster mbufs. * Also, added check to make sure that nioutput isn't called with * the interface down. * * 10-Jun-88 lp * Crank up in niinit when laying out bde's to keep reset from * corrupting them. * * 15-Jan-88 lp (Larry Palmer) * Minor rewrite to better use allocated mbufs. * 43BSD support added. NO MORE PAGE FLIPPING! * * 25-Aug-87 -- templin@decvax * Added fix pointed out by Ed Ferris which subtracts * the CRC field length from the length of the data field * used by niget(). Also added code to avoid reporting * non-error free queue exhaustions. * 28-Jul-87 -- lp * Fix problem with multiple interfaces. * * 07-Jul-87 -- templin@decvax * Fixed "ni_counters" type casts to correct a * word ordering problem with the counters. * 31-Mar-87 -- lp * Put apa back on a reset for decnet. * 06-Feb-87 -- lp * Check return of ifproto_type to gaurantee that * we dont jump to 0. * 28-Jan-87 -- lp * Cleanup as LINT showed some extra * variables. * * 12-Dec-86 -- lp Post FT-v2.0. Added dpaddr, Bumped up * freeq0 allocation. * * 23-Oct-86 -- lp Type 2 mbuf are forced to return on respq. * * 2-Sep-86 -- lp Cleanup. Bugfix for long (improperly chained) * packets. * * 7-Aug-86 -- lp Removed some printf's ('I' baseline). * * 7-Jul-86 -- lp Fixed a timing problem in niattach. * * 5-Jun-86 -- lp Fixed a little bug in reset code. * * 5-Jun-86 -- jaw changes to config. * * 22 May 86 -- bjg * Include types.h and errlog.h for error logging. * * 21 May 86 -- lp * Reworked sptdb routine to allow clear prior to setting. Bugfixes * for decnet. Errlog for SUME errors. * * 08 May 86 -- lp * Trailer packets work. General cleanup. Vaddr no longer saved * in receive packets. * * 09 Apr 1986 -- lp * DEC AIE/NI ethernet driver * By * Larry Palmer (decvax!lp). * (rev 40 or higher aie firmware needed) * */#include "packetfilter.h" /* NPACKETFILTER */#include "../data/if_ni_data.c"#include "../h/types.h"#include "../h/errlog.h"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern int net_output();struct mbuf *niget();int niattach(), bvpniintr(), niprobe();int niinit(),nistart(),niioctl(),nireset(), ni_ignore;u_char ni_multi[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00};u_char ni_notset[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};u_short nistd[] = { 0 };#define vaddr(y) \((char *)(((unsigned long)(ptetosv((struct pte *)((y)->pt_addr))))+(y)->offset))int nidebug = 0;int ni_fqe = 0;/* * 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. * We initialize big mbuf storage for receives here. */niattach(ni) struct ni *ni;{ register struct ni_softc *ds = &ni_softc[ni->unit]; register struct ifnet *ifp = &ds->ds_if; int i=0; struct sockaddr_in *sin; /* Initialize SMP lock */ lockinit(&ds->lk_ni_softc, &lock_device15_d); ds->ds_devid = 0; ifp->if_unit = ni->unit; ifp->if_name = "ni"; ifp->lk_softc = &ds->lk_ni_softc; ifp->if_mtu = ETHERMTU; ifp->if_type = IFT_ETHER; ifp->if_flags |= IFF_BROADCAST|IFF_DYNPROTO|IFF_NOTRAILERS; ((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0; /* * Set ni to initialized state */ i=0; while((ni->ni_regs->ps&PS_STATEMASK) != PS_UNDEFINED) { if(++i > 200) { printf("ni%d in wrong state\n", ni->unit); return; } DELAY(100000); } DELAY(200000); ni->ni_regs->ps &= ~PS_OWN; ni->ni_regs->pc &= ~PC_OWN; /* Go to initialized state */ ni->ni_regs->pc = ni->phys_pqb|PC_INIT|PC_OWN; DELAY(1000000); while((ni->ni_regs->pc&PC_OWN)) ; i=0; while((ni->ni_regs->ps&PS_INITIALIZED) == 0) { if(i++ > 15) { printf("ni%d Cannot initialize\n", ni->unit); return; } else DELAY(1000000); } ni->ni_regs->ps &= ~PS_OWN; /* * Fill the multicast address table with unused entries (broadcast * address) so that we can always give the full table to the device * and we don't have to worry about gaps. */ for(i=0; i<NMULTI; i++) { ds->ds_muse[i] = 0; bcopy(ni_multi, ds->ds_multi[i], 8); } sin = (struct sockaddr_in *)&ifp->if_addr; sin->sin_family = AF_INET; ifp->if_init = niinit; ifp->if_output = net_output; ifp->if_start = nistart; ifp->if_ioctl = niioctl; ifp->if_reset = nireset; ifp->d_affinity = ALLCPU; /* 8.9.88.us For nonsym drivers. */ /* * Fill out the if_version field with HW (and SW) info */ bcopy("DEC DEBNA Ethernet Interface", ifp->if_version, 28); ifp->if_version[28] = '\0'; /* * Hardware address unavailable at this point. (Only avail. * after niinit(). */ printf("ni%d: %s\n", ifp->if_unit, ifp->if_version);#if NPACKETFILTER > 0 /* Tell the packet filter that we are here */ attachpfilter(&(ds->ds_ed));#endif NPACKETFILTER if_attach(ifp);}/* * Reset of interface after reset. */nireset(unit) int unit;{ register struct ni *ni; register struct ni_softc *ds = &ni_softc[unit]; register char *mem; register int i; struct ifnet *ifp = &ds->ds_if; if (unit >= nNI || (ni = &niinfo[unit]) == 0 || ni->alive == 0) return; printf("reset ni%d %x %x %x %x\n", unit, ni->ni_regs->pc, ni->ni_regs->ps, ni->ni_regs->pe, ni->ni_regs->pd); if((ni->ni_regs->ps&PS_STATEMASK) != PS_ENABLED) { /* Eat freeq 2 */ while((mem = (char *)remqhi(&ni->freeq2, NI_MAXITRY)) != (char *)QEMPTY) { struct _bd *bde = (struct _bd *)ni->ni_pqb->ni.bdt_base; bde += ((struct ni_data *)mem)->cbufs[0].bdt_index; for(i=0; i<NI_RBUF; bde++, i++) { if(i == 1) { KM_FREE(vaddr(bde), KM_CLUSTER); } else { KM_FREE(vaddr(bde), KM_DEVBUF); } } KM_FREE(mem, KM_DEVBUF); } /* Eat freeq0 & freeq1 */ while((mem = (char *)remqhi(&ni->freeq0, NI_MAXITRY)) != (char *)QEMPTY) { KM_FREE(mem, KM_DEVBUF); } while((mem = (char *)remqhi(&ni->freeq1, NI_MAXITRY)) != (char *)QEMPTY) { KM_FREE(mem, KM_DEVBUF); } /* Eat the respq */ while((mem = (char *)remqhi(&ni->respq, NI_MAXITRY)) != (char *)QEMPTY) { if(((struct ni_data *)mem)->opcode == DGREC) { struct _bd *bde = (struct _bd *)ni->ni_pqb->ni.bdt_base; bde += ((struct ni_data *)mem)->cbufs[0].bdt_index; for(i=0; i<NI_RBUF; bde++, i++) { if(i == 1) { KM_FREE(vaddr(bde), KM_CLUSTER); } else { KM_FREE(vaddr(bde), KM_DEVBUF); } } KM_FREE(mem, KM_DEVBUF); } else if(((struct ni_data *)mem)->opcode == SNDDG) { KM_FREE(mem, KM_DEVBUF); } else { KM_FREE(mem, KM_DEVBUF); } } if((ni->ni_regs->ps&PS_STATEMASK) == PS_STOPPED) { ni->ni_regs->ps &= ~PS_OWN; ni->ni_regs->pc = PC_RESTART|PC_OWN; DELAY(1000000); while((ni->ni_regs->pc&PC_OWN)) ; } ni->ni_regs->ps &= ~PS_OWN; /* * Set ni to initialized state */ i=0; while((ni->ni_regs->ps&PS_STATEMASK) != PS_UNDEFINED) { if(++i > 200) { printf("ni%d in wrong state\n", ni->unit); return(0); } DELAY(100000); } ni->ni_regs->ps &= ~PS_OWN; /* Go to initialized state */ ni->ni_regs->pc = ni->phys_pqb|PC_INIT|PC_OWN; DELAY(100000); while((ni->ni_regs->pc&PC_OWN)) ; if((ni->ni_regs->ps&PS_INITIALIZED) == 0) { printf("ni%d Cannot initialize\n", ni->unit); printf("nireset: init failed - %d %x %x %x %x\n", unit, ni->ni_regs->pc, ni->ni_regs->ps, ni->ni_regs->pe, ni->ni_regs->pd); return(0); } ni->ni_regs->ps &= ~PS_OWN; ni->ni_regs->pe = 0; ni->ni_regs->pd = 0; ifp->if_flags &= ~(IFF_RUNNING); untimeout(niinit, unit); timeout(niinit, unit, 1); return(0); } return(1);}/* * Initialization of interface; clear recorded pending * operations. */niinit(unit) int unit;{ register struct ni_softc *ds = &ni_softc[unit]; register struct ni *ni = &niinfo[unit]; register struct nidevice *addr; struct ifnet *ifp = &ds->ds_if; int s,i,empty; /* not yet, if address still unknown */ /* DECnet must set this somewhere to make device happy */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ifp->if_flags & IFF_RUNNING) return; /* * Set ni to enabled state. Still dont have freeq ready. */ addr = (struct nidevice *)ni->ni_regs; while((addr->pc&PC_OWN)) ; addr->pc = PC_ENABLE|PC_OWN; /* Should interrupt here */ while((addr->pc&PC_OWN)) ; while((addr->ps&PS_OWN)) ; i = 0; while((addr->ps&PS_STATEMASK) != PS_ENABLED) { if(i++ > 500000) { printf("ni%d Cannot enable\n", ni->unit); return; } } addr->ps &= ~PS_OWN; s = splimp(); /* * Setup message freeq Just a few so its not empty */ { struct ni_msg *ni_msg; for(i=0; i<6; i++) { KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL); if (ni_msg == 0){ printf("ni%d Init out of memory - ni_msg\n",ni->unit); return; } if((empty=insqti(ni_msg, &ni->freeq0, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN; while((addr->pc&PC_OWN)) ; } } } /* Setup xmit buffers (empty) */ for(i=0; i<NI_FREEQ_1; i += NI_NUMBUF) { struct ni_data *ni_data; struct _bd *bde; int j; KM_ALLOC(ni_data, struct ni_data *, NI_DQSIZE, KM_DEVBUF, KM_NOW_CL); if (ni_data == 0){ printf("ni%d Init out of memory - ni_data\n",ni->unit); return; } ni_data->status = 0; ni_data->dg_len = NI_DQSIZE-NI_DQHEAD; ni_data->dg_ptdb_index = 1; ni_data->opcode = SNDDG; for(j=0; j<NI_NUMBUF; j++) { ni_data->cbufs[j].offset = 0; ni_data->cbufs[j].buffer_key = 1; bde = (struct _bd *) ni->ni_pqb->ni.bdt_base; bde += i+j; bde->key = 1; bde->valid = 0; ni_data->cbufs[j].bdt_index = i+j; } if((empty=insqti(ni_data, &ni->freeq1, NI_MAXITRY)) > 0) printf("xmit insqti failed %d\n", i); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_DFREEQ|PC_OWN; while((addr->pc&PC_OWN)) ; } } /* * Setup recv buffers */ /* Note that these have mbuf data areas associated */ for(i=NI_FREEQ_1; i<(NI_FREEQ_1+NI_FREEQ_2); i += NI_RBUF) { struct ni_data *ni_data; struct _bd *bde; char *buffer; int j=0; KM_ALLOC(ni_data, struct ni_data *, sizeof(struct ni_data), KM_DEVBUF, KM_NOW_CL); if (ni_data == 0){ printf("ni%d Init out of memory - ni_data\n",ni->unit); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -