📄 if_bp.c
字号:
return (ERROR); } } pMemEnd = pMem + memSize; pHdr = (BP_HEADER *) pMem; /* initialize bp anchor region */ pBpAnchor->an_ready = 0; /* set bp not ready */ pBpAnchor->an_heartbeat = 0; /* clear heartbeat */ pBpAnchor->an_pHdr = KtoIval (pHdr, BP_HEADER *, pAnchor); if (pMem + sizeof (BP_HEADER) > pMemEnd) { printf ("bp: bpInit out of memory!\n"); return (ERROR); } /* initialize bp header region */ pHdr->hdr_ready = 0; /* set CPU region not ready */ pHdr->hdr_ncpu = BP_HTONS(NCPU); /* set number of CPUs */ bcopy ((char *) bpEnetAdrs, (char *) pHdr->hdr_enetAdrs, 6); /* initialize each CPU descriptor */ for (ix = 0; ix < MAXCPU; ++ix) { pCpu = &pHdr->hdr_cpuDesc[ix]; pCpu->cd_active = FALSE; pCpu->cd_cpuNum = BP_HTONL(ix); pCpu->cd_pInputRing = NULL; } /* initialize free ring */ pMem += sizeof (BP_HEADER); if ((pMem + sizeof (struct ring256) + NCPU * sizeof (struct ring32)) > pMemEnd) { printf ("bp: bpInit out of memory!\n"); return (ERROR); } ringinit ((pFreeRing = (RING *) pMem), 256); pHdr->hdr_pFreeRing = KtoIval (pFreeRing, RING *, pAnchor); pMem += sizeof (struct ring256); /* initialize each input ring */ for (ix = 0; ix < NCPU; ++ix) { ringinit ((RING *) pMem, 32); pHdr->hdr_cpuDesc[ix].cd_pInputRing = KtoIval (pMem, RING *, pAnchor); pMem += sizeof (struct ring32); } /* initialize as many buffer blocks as will fit in remaining shared memory*/ if ((pMem + sizeof (BUF_NODE) + BP_BUFSIZ) > pMemEnd) { printf ("bp: bpInit out of memory!\n"); return (ERROR); } while ((pMem + sizeof (BUF_NODE) + BP_BUFSIZ) <= pMemEnd) { ((BUF_NODE *)pMem)->b_addr = KtoIval (pMem + sizeof (BUF_NODE), char*, pAnchor); ((BUF_NODE *)pMem)->b_len = BP_BUFSIZ; (void) ringput (pFreeRing, KtoIval (pMem, int, pAnchor)); pMem += sizeof (BUF_NODE) + BP_BUFSIZ; npackets++; } if (DEBUG_OPTION_1) { printf ("bp: number of %d byte packets is %d\n", BP_BUFSIZ, npackets); printf ("bp: %d bytes unused from 0x%x to 0x%x\n", (int) (pMemEnd - pMem), (int) vir2phys (pMem), (int) vir2phys (pMemEnd)); } /* mark bp as ready */ if (bpTasOK) pHdr->hdr_ready = pBpAnchor->an_ready = BP_HTONL(BP_READY); else pHdr->hdr_ready = pBpAnchor->an_ready = BP_HTONL(BP_READY_SOFT_TAS); /* start heartbeat */ bpHeartbeatRate = hz;#ifdef UNIX timeout (bpHeartbeat, (caddr_t) pAnchor, bpHeartbeatRate);#else /* UNIX */ /* create watchdog timer for heartbeat */ if ((pBpAnchor->an_wdog = wdCreate ()) == NULL) return (ERROR); wdStart (pBpAnchor->an_wdog, bpHeartbeatRate, (FUNCPTR) bpHeartbeat, (int) pAnchor);#endif /* UNIX */ return (OK); }/********************************************************************************* bpReset - mark a bp inactive** called from reboot and panic*/LOCAL void bpReset ( FAST int unit ) { FAST BP_SOFTC *bs; FAST BUF_NODE *pBufNode;#ifdef UNIX FAST struct mb_device *md; if (unit >= NBP || (md = bpinfo[unit]) == 0 || md->md_alive == 0) return;#endif /* UNIX */ bs = BP_SOFTC_P [unit]; if (bs != NULL && bs->bs_pHdr != NULL) { /* turn off active flag in our CPU descriptor in the * shared header, then throw away anything on our input ring */ bs->bs_pHdr->hdr_cpuDesc[bs->bs_procNum].cd_active = FALSE; while ( (pBufNode = (BUF_NODE *)ringget ( (RING *)bs->bs_pInputRing))) (void)ringput ( (RING *)bs->bs_pFreeRing, (int)pBufNode); } }/********************************************************************************* bpAlive - check for throbbing heartbeat** This routine is called for CPU 0 (master) as well as the rest.* The timeout is quick if the master can't see its own ticker.** RETURNS: OK or ERROR if unable to find anchor after 10 minutes*/LOCAL STATUS bpAlive ( BP_SOFTC *bs ) { int readyValue; int heartbeat; FAST unsigned int oldBeat = 0; FAST int countdown = 10 * 60 * hz; /* wait 10 minutes */ FAST BP_ANCHOR *pAnchor = bs->bs_pAnchor;#ifdef UNIX int level = spl3 (); /* find out priority level */ splx (level);#endif /* UNIX */ if (bs->bs_procNum == 0) countdown = 2 * hz; /* don't wait around for self if master CPU */ while (--countdown > 0) { /* probe test: * 1) anchor must be readable (memory must be visable to us), * 2) anchor ready value must be BP_READY or BP_READY_SOFT_TAS, * 3) anchor heartbeat must be increasing. */#ifdef UNIX if (peek ((short *) &pAnchor->an_ready) != -1 && peek ((short *) &pAnchor->an_heartbeat) != -1) { readyValue = BP_NTOHL(pAnchor->an_ready); heartbeat = (UINT)BP_NTOHL(pAnchor->an_heartbeat);#else /* UNIX */ if (vxMemProbe ((char *) &pAnchor->an_ready, O_RDONLY, 4, (char *) &readyValue) == OK && vxMemProbe ((char *) &pAnchor->an_heartbeat, O_RDONLY, 4, (char *) &heartbeat) == OK) { readyValue = BP_NTOHL(readyValue); heartbeat = (UINT)BP_NTOHL(heartbeat);#endif /* UNIX */ if ((countdown % 10) == 6) { printf ("\nbp: bpAlive ready = 0x%x, heartbeat = %d\n", readyValue, heartbeat); } if (readyValue == BP_READY || readyValue == BP_READY_SOFT_TAS) { if (oldBeat == 0 || heartbeat <= oldBeat) oldBeat = heartbeat; else { /* heartbeat increased, passed test */ bpTasOK = readyValue == BP_READY; return (OK); } } } else if ((countdown % 10) == 8) printf ("\nbp: bpAlive bus error\n");#ifdef UNIX timeout (wakeup, (caddr_t)bs, 1); sleep (bs, level);#else /* UNIX */ taskDelay (hz);#endif /* UNIX */ }#ifndef UNIX (void) errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);#endif /* UNIX */ /* give up - didn't get initialized */ return (ERROR); }/********************************************************************************* bpIfInit - initialize interface** RETURNS: OK or ERROR*/LOCAL STATUS bpIfInit ( int unit ) { FAST CPU_DESC *pCpu; FAST BP_SOFTC *bs = BP_SOFTC_P [unit]; FAST BP_HEADER *pHdr; /* find the anchor and CPU descriptor */ pHdr = ItoKval (bs->bs_pAnchor->an_pHdr, BP_HEADER *, bs->bs_pAnchor); bs->bs_pHdr = pHdr;#ifdef UNIX /* wait for shared memory to be initialized */ if (!BP_MASTER && bpAlive (bs) == ERROR) return (ERROR);#endif /* UNIX */ pCpu = &pHdr->hdr_cpuDesc [bs->bs_procNum]; bs->bs_pFreeRing = ItoKval (pHdr->hdr_pFreeRing, RING *, bs->bs_pAnchor); bs->bs_pInputRing= ItoKval(pHdr->hdr_cpuDesc[bs->bs_procNum].cd_pInputRing, RING *, bs->bs_pAnchor); /* fill in Ethernet address, which is the backplane Ethernet address with * our processor number as the last byte. */#ifdef UNIX bcopy ((char *) pHdr->hdr_enetAdrs, (char *) bs->bs_enaddr.ether_addr_octet, 6); bs->bs_enaddr.ether_addr_octet [4] = unit; bs->bs_enaddr.ether_addr_octet [5] = (char) bs->bs_procNum;#else /* UNIX */ bcopy ((char *) pHdr->hdr_enetAdrs, (char *) bs->bs_enaddr, 6); bs->bs_enaddr [4] = unit; bs->bs_enaddr [5] = (char) bs->bs_procNum;#endif /* UNIX */ /* check that our input buffer was established * (in case NCPU < our cpu < MAXCPU) */ if (pCpu->cd_pInputRing == NULL) return (ERROR); /* fill in our info in the CPU descriptor in shared memory */ pCpu->cd_unit = unit; /* set our internal unit num */ /* tell others how to interrupt us */ pCpu->cd_intType = BP_HTONL(bs->bs_intType); pCpu->cd_intArg1 = BP_HTONL(bs->bs_intArg1); pCpu->cd_intArg2 = BP_HTONL(bs->bs_intArg2); pCpu->cd_intArg3 = BP_HTONL(bs->bs_intArg3); /* connect and enable our interprocessor interrupt */ if (DEBUG_OPTION_1) printf ("bp%d: connecting...\n", unit); if (bpConnect (bs, unit) != OK || bpIntEnable (bs) != OK) return (ERROR); /* tell others we're here now */ pCpu->cd_active = TRUE; if ((bs->bs_if.if_flags & IFF_RUNNING) == 0) bs->bs_if.if_flags |= IFF_UP | IFF_RUNNING; return (OK); }/********************************************************************************* bpintr - interrupt handler** RETURNS: N/A** NOMANUAL*/void bpintr ( int unit ) { FAST BP_SOFTC *bs = BP_SOFTC_P [unit]; if (bs != NULL && bs->bs_pInputRing != NULL) /* input ring exists? */ {#ifndef UNIX bpIntAck (bs);#endif /* UNIX */ if (!bs->bs_readPending) { bs->bs_readPending = TRUE;#ifdef UNIX bpReadAll (unit);#else /* UNIX */ (void) netJobAdd ((FUNCPTR)bpReadAll, unit, 0,0,0,0); /* read from input ring */#endif /* UNIX */ } } }/********************************************************************************* bpReadAll -*/LOCAL void bpReadAll ( int unit ) { FAST BP_SOFTC *bs = BP_SOFTC_P [unit]; FAST BUF_NODE *pBufNode; bs->bs_readPending = FALSE; while ((pBufNode = (BUF_NODE *) ringget ((RING *) bs->bs_pInputRing)) != 0) {#ifdef UNIX bpRead (bs, ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor)); (void) ringput (bs->bs_pFreeRing, (int) pBufNode);#else /* UNIX */ if (bpRead (bs, ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor), pBufNode) == OK) (void) ringput ((RING *) bs->bs_pFreeRing, (int) pBufNode);#endif /* UNIX */ } }/********************************************************************************* bpRead -** NOMANUAL*/#ifdef UNIXLOCAL void bpRead (bs, pBufNode) BP_SOFTC *bs; BUF_NODE *pBufNode;#else /* UNIX */LOCAL STATUS bpRead ( BP_SOFTC *bs, BUF_NODE *pBufNode, BUF_NODE *pBufNodeOrig )#endif /* UNIX */ { FAST struct ether_header *eh; FAST struct mbuf *m; int len; int off; FAST unsigned char *pData; STATUS retval;#ifdef BSD43_DRIVER u_short ether_type;#endif retval = OK; bs->bs_if.if_ipackets++; /* count input packets */ /* get length and pointer to packet */ len = (int) (BP_NTOHS (pBufNode->b_len)); eh = ItoKval (pBufNode->b_addr, struct ether_header *, bs->bs_pAnchor);#ifndef UNIX /* call input hook if any */ if ((etherInputHookRtn != NULL) && (* etherInputHookRtn) (&bs->bs_if, (char *)eh, BP_NTOHS(pBufNode->b_len))) return (retval); /* input hook has already processed packet */#endif /* UNIX */ len -= SIZEOF_ETHERHEADER; pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef UNIX check_trailer (eh, pData, &len, &off); if (len == 0) return; m = copy_to_mbufs (pData, len, off); if (m != NULL) do_protocol (eh, m, &bs->bs_ac, len); else bs->bs_if.if_ierrors++; /* bump error count */#else /* UNIX */#ifdef BSD43_DRIVER check_trailer (eh, pData, &len, &off, &bs->bs_if); if (len == 0) return (retval); ether_type = eh->ether_type;#endif m = copy_to_mbufs (pData, len, off, &bs->bs_if); if (m != NULL)#ifdef BSD43_DRIVER do_protocol_with_type (ether_type, m, &bs->bs_ac, len);#else do_protocol (eh, m, &bs->bs_ac, len);#endif else bs->bs_if.if_ierrors++; /* bump error count */ return (retval);#endif /* UNIX */ }/********************************************************************************* bpStart -** NOMANUAL*/#ifdef UNIXLOCAL void bpStart (dev) dev_t dev;#else /* UNIX */#ifdef BSD43_DRIVERLOCAL void bpStart ( int unit )#elseLOCAL void bpStart ( BP_SOFTC * bs )#endif /* BSD43_DRIVER */#endif /* UNIX */ {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -