📄 if_enp.c
字号:
DRV_CTRL *pDrvCtrl;#ifdef ENP_DEBUG printf ( "\nenp: attach: unit=%d, addr=%x, ivec=%d, ilevel=%d, Am=%d\n", unit, addr, ivec, ilevel, enpAddrAm );#endif /* Safety check unit number */ if (unit < 0 || unit >= MAX_UNITS) { errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT); return (ERROR); } /* Get pointer to our driver control structure */ pDrvCtrl = & drvCtrl [unit]; /* Check for multiple invocation per unit */ if (pDrvCtrl->attached) return (OK); /* Publish the interface data record */#ifdef BSD43_DRIVER ether_attach ( & pDrvCtrl->idr.ac_if, unit, "enp", (FUNCPTR) NULL, (FUNCPTR) enpIoctl, (FUNCPTR) enpOutput, (FUNCPTR) enpReset);#else ether_attach ( &pDrvCtrl->idr.ac_if, unit, "enp", (FUNCPTR)NULL, (FUNCPTR)enpIoctl, (FUNCPTR)ether_output, (FUNCPTR)enpReset ); pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)enpTxStartup;#endif#ifdef BSD43_DRIVER /* Create the transmit semaphore. */ pDrvCtrl->TxSem = semMCreate ( SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE ); if (pDrvCtrl->TxSem == NULL) {#ifdef ENP_DEBUG printf ("enp: error creating transmitter semaphore\n");#endif return (ERROR); }#endif /* Determine local address and AM codes to access the controller */ if (sysBusToLocalAdrs (enpAddrAm, addr, &enpBase) == ERROR) { errnoSet (EFAULT); return (ERROR); }#ifdef ENP_DEBUG printf ( "enp: attach: local addr=%x\n", enpBase );#endif pEnpDev = (ENPDEVICE *) enpBase; enpBase += 0x1000; /* memory is offset from board base address */ /* Connect the interrupt handler */ (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), (VOIDFUNCPTR)enpIntr, unit); /* wait for kernel reset to finish */ delay = 15 * sysClkRateGet (); while (1) { /* Test for response on the buss */ if ( vxMemProbe ( (char *) & pEnpDev->enp_status, O_RDONLY, sizeof (short), (char *) & status ) == OK ) { /* Check status word */ if ( (ntohs (status) & STS_READY) != 0 ) break; } /* Check for timeout */ if (--delay <= 0) { (void) errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT); return (ERROR); } taskDelay (sysClkRateGet() / 30); /* 1/30th of a second */ } /* start link level firmware */ pEnpDev->enp_intvector = htons (ivec); temp = htonl ((u_long) enpBase); WRITELONG (&pEnpDev->enp_base, temp);#if CPU_FAMILY==I960 pEnpDev->enp_mode = htons (0x0080);#endif /* CPU_FAMILY==I960 */ pEnpDev->enp_go = htons (GOVAL); CACHE_PIPE_FLUSH (); /* wait for the link level firmware to finish initialization */ delay = 15 * sysClkRateGet (); while ((ntohs (pEnpDev->enp_state) & S_ENPRUN) == 0) { if (--delay <= 0) { (void) errnoSet (S_ioLib_DEVICE_ERROR); return (ERROR); } taskDelay (sysClkRateGet() / 30); /* 1/30th of a second */ } pDrvCtrl->enpAddr = pEnpDev; pDrvCtrl->enpIntLevel = ilevel; pDrvCtrl->enpIntVec = ivec; enpgetaddr (unit); (void) sysIntEnable (ilevel); /* Raise the interface flags */ pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_MULTICAST; /* Set our success indicator */ pDrvCtrl->attached = TRUE; return (OK); }/********************************************************************************* enpReset - reset the interface*/LOCAL STATUS enpReset ( int unit ) { DRV_CTRL *pDrvCtrl; ENPDEVICE *pEnpDev;#ifdef ENP_DEBUG printf ( "enp: reset: unit=%d\n", unit );#endif /* Safety check unit number */ if (unit < 0 || unit >= MAX_UNITS) { errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT); return (ERROR); } pDrvCtrl = & drvCtrl[unit]; pEnpDev = pDrvCtrl->enpAddr; pDrvCtrl->idr.ac_if.if_flags = 0; RESET_ENP (pEnpDev); /* reset the status word that enpattach watches to know when enp is reset; * this is necessary because the enp doesn't clear this status immediately * on reset. Re-initializing the enp after a reset (i.e. in VxWorks * init after boot rom reset) could get fooled if we rely on enp to clear * the READY bit in this status. */ pEnpDev->enp_status = 0; CACHE_PIPE_FLUSH (); return (OK); }/********************************************************************************* enpIntr - the driver's interrupt handler** The ENP board will only interrupt us to notify us that there are packets* to be processed. The processing of each packet is done by netTask. This* routine simply queues our job for netTask.*/LOCAL void enpIntr ( int unit ) { DRV_CTRL *pDrvCtrl; /* Safety check unit number */ if (unit < 0 || unit >= MAX_UNITS) return; pDrvCtrl = & drvCtrl [unit]; sysBusIntAck (pDrvCtrl->enpIntLevel); if (!pDrvCtrl->taskLevelActive) { /* indicate that enpHandleInt is q'd */ pDrvCtrl->taskLevelActive = TRUE; (void) netJobAdd ((FUNCPTR)enpRxEvent, unit, 0,0,0,0); /* see comment in enpHandleInt */ } }/********************************************************************************* enpRxEvent - handler for receive events*/LOCAL void enpRxEvent ( int unit ) { DRV_CTRL *pDrvCtrl; ENPDEVICE *pDev; pDrvCtrl = & drvCtrl [unit]; pDev = pDrvCtrl->enpAddr; splx (0); /* Give up the spl semaphore taken for us by netTask. */ /* the following loop attempts to pull multiple buffers off of the * input queue; the boolean "taskLevelActive" is used to inform * the interrupt level code that we're already processing input * buffers, so there's no need to do a netJobAdd, thereby decreasing * the possibility of a net task ring buffer overflow. */ do { pDrvCtrl->taskLevelActive = TRUE; while (!enpringempty ((RING*) &pDev->enp_tohost)) { if ( enpRxPktProcess (unit) == ERROR ) { pDrvCtrl->taskLevelActive = FALSE; splimp (); /* Take the spl semaphore for netTask */ return; } } pDrvCtrl->taskLevelActive = FALSE; /* check once more after resetting taskLevelActive to avoid race */ } while (!enpringempty ((RING*) &pDev->enp_tohost)); splimp (); /* Take the spl semaphore for netTask */ }/********************************************************************************* enpRxPktProcess - process the next received packet** Copy packets from a BCB into an mbuf and hand it to the next higher layer.*/LOCAL STATUS enpRxPktProcess ( int unit ) { int len; int temp; DRV_CTRL *pDrvCtrl; ENET_HDR *pEnetHdr; MBUF *pMbuf; BCB *pBCB; ENPDEVICE *pDev; unsigned char *pData; /* Get control pointers */ pDrvCtrl = & drvCtrl [unit]; pDev = pDrvCtrl->enpAddr; /* Check ifnet flags. Return if incorrect. */ if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) return (ERROR); /* Get pointer to next packet */ pBCB = (BCB*) enpringget ((RING*) &pDev->enp_tohost); if (pBCB == NULL) /* unlikely error */ return (ERROR); /* Bump the incoming packet statistic */ pDrvCtrl->idr.ac_if.if_ipackets++; /* Get length of packet */ len = ntohs (pBCB->b_msglen); /* Get pointer to packet */ READLONG ((& pBCB->b_addr), &temp); pEnetHdr = (ENET_HDR *) ntohl (temp); /* call input hook if any */ if (etherInputHookRtn != NULL) { if ( (*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len) == 1 ) { (void) enpringput ((RING *)&pDev->enp_enpfree, pBCB); return (OK); } } /* Adjust length; subtract size of header */ len -= ENET_HDR_REAL_SIZ; /* Get pointer to data section of the packet */ pData = ((unsigned char *) pEnetHdr) + ENET_HDR_REAL_SIZ; /* copy data from enp to mbuf a word at a time */#if (CPU == MC68000) || (CPU == MC68010) || (CPU == CPU32) pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->idr.ac_if, 1);#else pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->idr.ac_if, 2);#endif /* (CPU == MC68000) || (CPU == MC68010) || (CPU == CPU32) */ if (pMbuf != NULL)#ifdef BSD43_DRIVER do_protocol_with_type ( ntohs (pEnetHdr->type), pMbuf, & pDrvCtrl->idr, len );#else do_protocol (pEnetHdr, pMbuf, &pDrvCtrl->idr, len);#endif else ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */ (void) enpringput ((RING *)&pDev->enp_enpfree, pBCB);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -