📄 if_bp.c
字号:
u_char bs_ivec;#endif /* UNIX */ } BP_SOFTC;#ifdef UNIXextern struct mb_driver bpdriver;struct mb_device *bpinfo[NBP];LOCAL BP_SOFTC bp_softc [NBP];#define BP_SOFTC_P &bp_softc#define dbgprintf printf#define sysProcNumGet() (bp_procnum)FUNCPTR bpProbeType;LOCAL char *cpudesc_vaddr [MAXCPU];#else /* UNIX *//* bpPollTask parameters */int bpPollTaskId;int bpPollTaskOptions = VX_SUPERVISOR_MODE | VX_UNBREAKABLE;int bpPollTaskStackSize = 2000;int bpPollTaskPriority = 250;LOCAL BP_SOFTC *bp_softc[NBP];#define BP_SOFTC_P bp_softc#define dbgprintf logMsgint bpProbeType;#endif /* UNIX */LOCAL BOOL vxTasac ();/* * the default TAS, use undef if you dont like it */#define TAS(x) (bpTasOK ? sysBusTas (x) : vxTasac (x))#if (CPU_FAMILY==MIPS)#define TAS_CLEAR(x) (bpTasOK ? sysBusClearTas (&(x)) : ((x)=0))#endif /* CPU_FAMILY==MIPS */#if CPU_FAMILY==SPARCIMPORT BOOL vxTas ();IMPORT BOOL sysBusTas ();FUNCPTR bpTasRtn = vxTasac; /* Test-and-Set Routine */#undef TAS(x)#define TAS(x) (*bpTasRtn)(x)/********************************************************************************* bpTas - determine backplane test-and-set macro TAS(x)** NOMANUAL*/void bpTas (bp_tas, bp_off_board, bp_target) BOOL bp_tas; /* BP_TAS */ BOOL bp_off_board; /* BP_OFF_BOARD */ int bp_target; /* target id */ { if (!bp_tas) bpTasRtn = vxTasac; /* software TAS */ else { /* hardware TAS */ if (bp_target == 0x1E) { /* Sun-1E */ if (bp_off_board) bpTasRtn = vxTas; else bpTasRtn = sysBusTas; } else { if (bp_off_board) bpTasRtn = sysBusTas; else bpTasRtn = vxTas; } } }#endif /* CPU_FAMILY==SPARC */#ifdef UNIX#define intLock spl7#define intUnlock splx#endif /* UNIX */#define DELAY_COUNT 5000 /* how high to count when waiting on TAS */#ifdef UNIXIMPORT int bpParity;IMPORT int bpDebug; /* flags: 1-usage, 2-dropped packets */#else /* UNIX */int bpParity = FALSE;int bpDebug; /* flags: 1-usage, 2-dropped packets */#endif /* UNIX */#define DEBUG_OPTION_1 (bpDebug & 0x1)#define DEBUG_OPTION_2 (bpDebug & 0x2)#define DEBUG_OPTION_3 (bpDebug & 0x4)#define DEBUG_OPTION_4 (bpDebug & 0x8)#define DEBUG_OPTION_5 (bpDebug & 0x10) /* 0, 0, 0, 0, unit, host */u_char bpEnetAdrs [6] = { 0, 0, 0, 0, 0, 0 };/* local variables */LOCAL BOOL bpTasOK; /* whether hardward can do test-and-set */LOCAL int bpHeartbeatRate;int bpBitBucket; /* spare change *//* forward declarations */void bpPollTask ();void bpintr ();/* forward static functions */static void bpReset (int unit);static STATUS bpAlive (BP_SOFTC *bs);static STATUS bpIfInit (int unit);static void bpReadAll (int unit);static STATUS bpRead (BP_SOFTC *bs, BUF_NODE *pBufNode, BUF_NODE *pBufNodeOrig);#if defined BSD43_DRIVER || defined (UNIX)static void bpStart (int unit);static int bpOutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst);#elsestatic void bpStart (BP_SOFTC * bs);#endifstatic STATUS bpPut (BP_SOFTC *bs, struct mbuf *m);static void bpXmit (BP_SOFTC *bs, BUF_NODE *pBufNode, int destProcNum, int srcProcNum);static void bpIntAck (BP_SOFTC *bs);static STATUS bpConnect (BP_SOFTC *bs, int unit);static STATUS bpIntEnable (BP_SOFTC *bs);static void bpIntGen (CPU_DESC *pCpu, int srcProcNum);static void bpHeartbeat (BP_ANCHOR *pAnchor);static int bpSizeMem (caddr_t memAdrs, int memSize);static int bpIoctl (struct ifnet *ifp, int cmd, caddr_t data);static void ringinit (RING *rp, short size);#if CPU==R3000static int ringput ();static int ringget ();#elsestatic int ringput (RING *rp, int v);static int ringget (RING *rp);#endifstatic int ringcount (RING *pRing);static BOOL vxTasac (char *address);#ifdef UNIXLOCAL void bpRead ();#else /* UNIX */LOCAL STATUS bpRead ();#endif /* UNIX */#ifdef UNIX/********************************************************************************* bpattach - attach the `bp' interface to the network** Make the `bp' interface available by filling in the network interface record.* The system will initialize the interface when it is ready to accept packets.** RETURNS: N/A** NOMANUAL*/void bpattach (md) struct mb_device *md; { int unit = md->md_unit; FAST BP_SOFTC *bs = BP_SOFTC_P [unit]; struct ifnet *ifp = &bs->bs_if; bs->bs_procNum = bp_procnum; bs->bs_intType = bp_int_type; bs->bs_intArg1 = bp_int_arg1; bs->bs_intArg2 = bp_int_arg2; bs->bs_intArg3 = bp_int_arg3; bs->bs_addr = md->md_addr; bs->bs_ivec = md->md_intr->v_vec; ether_attach (ifp, unit, "bp", bpIfInit, bpIoctl, bpOutput, (FUNCPTR)bpReset); ifp->if_mtu = bp_mtu; bzero ((char*) cpudesc_vaddr, sizeof (cpudesc_vaddr)); }/********************************************************************************* bpPoke - map in physical memory and write value to address** This routine is used to map in CPU boards' mailboxes.* An array up to MAXCPU is kept so that a mailbox is* only mapped in once per CPU.*/LOCAL void bpPoke (addr, type, value, cpuNum) char *addr; /* physical address */ int type; /* mailbox size + read/write */ int value; /* value to write */ int cpuNum; /* which CPU */ { char *vaddr; /* virtual address */ int kmx; /* kernel map index */ int numClicks; /* int numBytes; */ int addrOffset; if (cpuNum < 0 && cpuNum > MAXCPU) { printf ("bp: bpPoke invalid cpu #%d\n", cpuNum); return; } if ((vaddr = cpudesc_vaddr [cpuNum]) == 0) { numClicks = btoc (sizeof (int)); /* numBytes = ctob (numClicks); */ addrOffset = (int)(addr - ptob (btop (addr))); /* get some virtual address space */ if ((kmx = rmalloc (kernelmap, numClicks)) == 0) { printf ("bp: no kernelmap for bp mailbox\n"); panic ("bpPoke"); } vaddr = (char *)kmxtob (kmx); mapin (&Usrptmap [kmx], btop (vaddr), btop (addr) | PGT_VME_D16, numClicks, PG_V | PG_KW); cpudesc_vaddr [cpuNum] = vaddr += addrOffset; if (DEBUG_OPTION_1) printf ("\nbp: cpu #%d mailbox addr = 0x%x, vaddr = 0x%x\n", cpuNum, (int)addr, (int)vaddr); } switch (type) { case BP_INT_MAILBOX_1: *(char *) vaddr = value; break; case BP_INT_MAILBOX_2: *(short *) vaddr = value; break; case BP_INT_MAILBOX_4: *(long *) vaddr = value; break; case BP_INT_MAILBOX_R1: value = *(char *) vaddr; break; case BP_INT_MAILBOX_R2: value = *(short *) vaddr; break; case BP_INT_MAILBOX_R4: value = *(long *) vaddr; break; default: printf ("bp: bpPoke - bad mailbox type 0x%x\n", type); break; }#ifdef MAP_OUT /* example of mapping out memory */ cpudesc_vaddr [cpuNum] = 0; mapout (&Usrptmap [kmx], numClicks, kmx); rmfree (kernelmap, numClicks, kmx);#endif /* MAP_OUT */ }/********************************************************************************* bpProbe - probe for backplane memory** RETURNS:* The amount of memory available, or 0 if error.** NOMANUAL*/int bpProbe (addr, unit) caddr_t addr; /* address of backplane memory */ int unit; /* device number */ { int memSize = bp_mem_size; FAST BP_SOFTC *bs = BP_SOFTC_P [unit]; extern int peek (), pokec (); if (BP_MASTER) bpProbeType = bpParity ? pokec : peek; else bpProbeType = peek; if (DEBUG_OPTION_1) printf ("bp%d: debugging on (level = 0x%x)\n", unit, bpDebug); /* anchor is at the start of shared memory */ bs->bs_pAnchor = (BP_ANCHOR *) addr; if ((*bpProbeType) (addr, 0) == -1) { printf ("bp%d: shared memory not present at 0x%x (0x%x)\n", unit, (int)bs->bs_pAnchor,(int)vir2phys((char*)bs->bs_pAnchor)); return (0); } if (BP_MASTER && bpInit ((char*)bs->bs_pAnchor, addr, memSize, bp_tas) == ERROR) { printf ("bp%d: bpProbe cannot initialize anchor!\n", unit); return (0); } if (DEBUG_OPTION_1) printf ("bp%d: shared memory size is %d bytes, at 0x%x (0x%x)\n", unit, memSize,(int)bs->bs_pAnchor, (int)vir2phys((char*)bs->bs_pAnchor)); return (memSize); }#else /* UNIX *//********************************************************************************* bpattach - publish the `bp' network interface and initialize the driver and device** This routine attaches a `bp' interface to the network, if the* interface exists. This routine makes the interface available by filling in* the network interface record. The system will initialize the interface* when it is ready to accept packets.** RETURN: OK or ERROR.*/STATUS bpattach ( int unit, /* backplane unit number */ char *pAnchor, /* bus pointer to bp anchor */ int procNum, /* processor number in backplane */ int intType, /* interrupt type: poll, bus, mailbox */ int intArg1, /* as per interrupt type */ int intArg2, /* as per interrupt type */ int intArg3 /* as per interrupt type */ ) { FAST BP_SOFTC *bs; FAST struct ifnet *ifp; FAST BP_ANCHOR *pBpAnchor = (BP_ANCHOR *) pAnchor; if (procNum == 0) bpProbeType = bpParity ? O_WRONLY : O_RDONLY; else bpProbeType = O_RDONLY; /* allocate bp_softc structure */ if ((bs = (BP_SOFTC *) malloc (sizeof (BP_SOFTC))) == NULL) return (ERROR); bp_softc [unit] = bs; /* XXX check if non-zero for re-attach? */ ifp = &bs->bs_if; /* initialize the interface structure */ bzero ((char *) bs, sizeof (BP_SOFTC)); bs->bs_pAnchor = pBpAnchor; bs->bs_procNum = procNum; bs->bs_intType = intType; bs->bs_intArg1 = intArg1; bs->bs_intArg2 = intArg2; bs->bs_intArg3 = intArg3; /* wait for shared memory to be initialized; master CPU does sanity check */ if (bpAlive (bs) == ERROR) { (void) free ((void *) bs); return (ERROR); } if (bpDebug != 0) { printf ("bp%d: debugging on (level = 0x%x)\n", unit, bpDebug); printf ("bpattach: anchor CPU can%s do real TAS.\n", bpTasOK ? "" : "not"); }#ifdef BSD43_DRIVER ether_attach (ifp, unit, "bp", bpIfInit, bpIoctl, bpOutput, (FUNCPTR)bpReset);#else ether_attach ( ifp, unit, "bp", (FUNCPTR) bpIfInit, (FUNCPTR) bpIoctl, (FUNCPTR) ether_output, (FUNCPTR) bpReset ); ifp->if_start = (FUNCPTR)bpStart;#endif ifp->if_mtu = bp_mtu; if (bpIfInit (unit) == ERROR) { (void) free ((void *) bs); return (ERROR); } return (OK); }#endif /* UNIX *//********************************************************************************* bpInit - initialize the backplane anchor** This routine initializes the backplane anchor. Typically, <pAnchor> and* <pMem> both point to the same block of shared memory. If the first* processor is dual-porting its memory, then, by convention, the anchor is* at 0x600 (only 16 bytes are required) and the start of memory <pMem> is* dynamically allocated by using the value NONE (-1). <memSize> should be at* least 64 Kbytes. The <tasOK> parameter is provided for CPUs that do* not support the test-and-set instruction. If the system includes any* test-and-set deficient CPUs, then all CPUs must use the software* "test-and-set".** RETURNS:* OK, or ERROR if data structures cannot be set up or memory is insufficient.*/STATUS bpInit ( FAST char *pAnchor, /* backplane anchor address */ FAST char *pMem, /* start of backplane shared memory, NONE = alloc */ int memSize, /* no. bytes in bp shared memory, 0 = 0x100000 */ BOOL tasOK /* TRUE = hardware can do test-and-set */ ) { FAST BP_ANCHOR *pBpAnchor = (BP_ANCHOR *) pAnchor; FAST RING *pFreeRing; FAST int ix; FAST char *pMemEnd; /* end of backplane shared memory */ FAST CPU_DESC *pCpu; FAST BP_HEADER *pHdr; int npackets = 0; memSize = (memSize == 0) ? 0x100000 : memSize; bpTasOK = tasOK; /* if bp header specified, probe it, otherwise malloc it */ if (pMem != (char *) NONE) { memSize = min (memSize, bpSizeMem (pMem, memSize)); if (memSize == 0) { printf ("bp: no shared memory at address 0x%x\n", (int)pMem); return (ERROR); } /* if anchor is at start of shared region, skip over it */ if (pMem == pAnchor) { pMem += sizeof (BP_ANCHOR); memSize -= sizeof (BP_ANCHOR); } } else {#ifndef UNIX#if ((CPU_FAMILY==MIPS) || (CPU_FAMILY==SH)) if ((pMem = (char *) cacheDmaMalloc ((unsigned) memSize)) == NULL)#else /* CPU_FAMILY==MIPS || CPU_FAMILY==SH */ if ((pMem = (char *) malloc ((unsigned) memSize)) == NULL)#endif /* CPU_FAMILY==MIPS || CPU_FAMILY==SH */#endif /* UNIX */ { printf ("bp: can't allocate shared memory\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -