📄 if_fei.c
字号:
{ /* This device was not the cause of the shared int */ return; } /* clear chip level interrupt pending */ pDrvCtrl->pCSR->scbStatus = (event&SCB_S_STATMASK); /* board level interrupt acknowledge */ BOARD_INT_ACK(unit);#ifdef FEI_DEBUG if (feiDebug) logMsg ("feiInt: event 0x%x, scbStatus 0x%x\n", event, pDrvCtrl->pCSR->scbStatus, 0, 0, 0, 0);#endif /* FEI_DEBUG */ /* handle receive interrupts */ if ( (event & SCB_S_FR) && !(pDrvCtrl->pCSR->scbCommand & SCB_C_M)) { I82557_INT_DISABLE; pDrvCtrl->rxHandle = TRUE; (void) netJobAdd ((FUNCPTR) feiHandleRecvInt, (int) pDrvCtrl, 0, 0, 0, 0); } } /********************************************************************************* feiHandleRecvInt - service task-level interrupts for receive frames** This routine is run in netTask's context. The ISR scheduled* this routine so that it could handle receive packets at task level.** RETURNS: N/A*/LOCAL void feiHandleRecvInt ( DRV_CTRL * pDrvCtrl ) { RFD * pRFD = pDrvCtrl->pRFD; RFD * pRFDNew; int unit = pDrvCtrl->idr.ac_if.if_unit; while (pRFD->rfdStatus & RFD_S_COMPLETE) /* while packets to process */ { pDrvCtrl->rxHandle = TRUE; /* interlock with eiInt() */ if (!(pRFD->rfdStatus & RFD_S_OK)) pDrvCtrl->idr.ac_if.if_ierrors++; else { if (feiReceive (pDrvCtrl, pRFD) == ERROR) { /* buffer loaning was done */ pRFDNew = pDrvCtrl->pRFDL; pDrvCtrl->pRFDL = pRFDNew->pPrev; LINK_WR (&pRFD->pPrev->link, LOCAL_TO_SYS_ADDR(unit,(UINT32)pRFDNew)); LINK_WR (&pRFDNew->link, LINK_RD (&pRFD->link)); pRFDNew->pPrev = pRFD->pPrev; pRFD = (RFD *) SYS_TO_LOCAL_ADDR(unit, (UINT32)LINK_RD (&pRFD->link)); pRFD->pPrev = pRFDNew; pRFD = pRFDNew; } } pRFD->rfdStatus = 0; pRFD->rfdCommand = RFD_C_EL; /* chip can have it.... */ pRFD->pPrev->rfdCommand &= ~RFD_C_EL; /* hook frame into CBL */ pRFD = (RFD *) SYS_TO_LOCAL_ADDR(unit,(UINT32)LINK_RD (&pRFD->link) ) ; /* bump to next RFD in ring */ pDrvCtrl->pCSR->scbStatus &= (SCB_S_FR | SCB_S_RNR); } pDrvCtrl->pRFD = pRFD; /* keep track of current RFD */ /* kick receiver (if needed) */ if ((pDrvCtrl->pCSR->scbStatus & SCB_S_RUMASK) != SCB_S_RURDY) { if (feiSCBCommand (pDrvCtrl, SCB_C_RUSTART, TRUE, (UINT32 *)LOCAL_TO_SYS_ADDR(unit, (UINT32)pRFD)) == ERROR) { pDrvCtrl->rxHandle = FALSE; return; } while ((pDrvCtrl->pCSR->scbCommand)&SCB_C_RUMASK) ; /* wait for RUSTART accept */ } pDrvCtrl->rxHandle = FALSE; /* re-enable receiver interrupts */ I82557_INT_ENABLE; }/********************************************************************************* feiReceive - pass a received frame to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol. The return value indicates if buffer loaning was used to hold* the data. A return value of OK means that loaning was not done.** RETURNS: OK, or ERROR if buffer-loaning the RFD.*/LOCAL STATUS feiReceive ( DRV_CTRL * pDrvCtrl, RFD * pRFD ) { struct ether_header * pEh; u_char * pData; int len; UINT16 etherType; MBUF * pMbuf = NULL; STATUS retVal = OK; len = pRFD->actualCnt & 0x3fff; /* get frame length */ pEh = (struct ether_header *)pRFD->enetHdr; /* get ptr to ethernet header */ pDrvCtrl->idr.ac_if.if_ipackets++; /* bump statistic */ /* call hook routine if one is connected */ if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, (char *) pEh, len))) return (OK); len -= EH_SIZE; if (len <= 0) { pDrvCtrl->idr.ac_if.if_ierrors++; /* bump error stat */ pDrvCtrl->idr.ac_if.if_ipackets--; /* fix statistic */ return (OK); } pData = (u_char *) pRFD->enetData; etherType = ntohs (pEh->ether_type); if ((pDrvCtrl->pRFDL != NULL) && (USE_CLUSTER (len)) && ((pMbuf = build_cluster (pData, len, (struct ifnet *) &pDrvCtrl->idr, MC_FEI, &pRFD->refCnt, (FUNCPTR) feiLoanFree, (int) pDrvCtrl, (int) pRFD, NULL)) != NULL)) retVal = ERROR; /* we loaned a frame */ else pMbuf = copy_to_mbufs (pData, len, 0, (struct ifnet *) &pDrvCtrl->idr); if (pMbuf != NULL) {#ifdef BSD43_DRIVER do_protocol_with_type (etherType, pMbuf, &pDrvCtrl->idr, len);#else do_protocol (pEh, pMbuf, &pDrvCtrl->idr, len);#endif } else { pDrvCtrl->idr.ac_if.if_ierrors++; /* bump error stat */ pDrvCtrl->idr.ac_if.if_ipackets--; /* fix statistic */ } return (retVal); }/********************************************************************************* feiLoanFree - return a loaned receive frame descriptor** This routine is called by the protocol code when it has completed use of* an RFD that we loaned to it.** RETURNS: N/A*/LOCAL void feiLoanFree ( DRV_CTRL * pDrvCtrl, RFD * pRFD ) { pRFD->refCnt = 0; /* should already be zero... */ pRFD->pPrev = pDrvCtrl->pRFDL; pDrvCtrl->pRFDL = pRFD; }/********************************************************************************* feiNOP - format and issue a NOP command** RETURNS: OK, or ERROR if the NOP command failed.*/LOCAL STATUS feiNOP ( int unit ) { if (!(feiAction (unit, CFD_C_NOP) & CFD_S_OK)) return (ERROR); return (OK); }/********************************************************************************* feiDiag - format and issue a diagnostic command** RETURNS: OK, or ERROR if the diagnostic command failed.*/LOCAL STATUS feiDiag ( int unit ) { UINT16 stat; if (((stat = feiAction (unit, CFD_C_DIAG)) & (CFD_S_OK | CFD_S_DIAG_F)) != CFD_S_OK) {#ifdef FEI_DEBUG if (feiDebug) printf ("if_fei.c: 82557 diagnostics failed, cfdStatus 0x%x\n", stat);#endif /* FEI_DEBUG */ return (ERROR); } return (OK); }/********************************************************************************* feiConfig - format and issue a config command** RETURNS: OK, or ERROR if the config command failed.*/LOCAL STATUS feiConfig ( int unit ) { DRV_CTRL * pDrvCtrl = & drvCtrl [unit]; CFD * pCFD = pDrvCtrl->pCFD; /* set to config values recommeded by the i82557 User's Manual */ pCFD->cfdConfig.ccByte0 = 0x16; pCFD->cfdConfig.ccByte1 = 0x88; /* 0x08; */ pCFD->cfdConfig.ccByte2 = 0x00; pCFD->cfdConfig.ccByte3 = 0x00; pCFD->cfdConfig.ccByte4 = 0x00; /* 0x00; */ pCFD->cfdConfig.ccByte5 = 0x00; /* 0x80; */ pCFD->cfdConfig.ccByte6 = 0x38; /* save bad frame,no TNO 0x3a; */ pCFD->cfdConfig.ccByte7 = 0x03; pCFD->cfdConfig.ccByte8 = 0x01; /* MII operation */ pCFD->cfdConfig.ccByte9 = 0x00; pCFD->cfdConfig.ccByte10 = 0x2e; pCFD->cfdConfig.ccByte11 = 0x00; pCFD->cfdConfig.ccByte12 = 0x60; pCFD->cfdConfig.ccByte13 = 0x00; pCFD->cfdConfig.ccByte14 = 0xf2; if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC) pCFD->cfdConfig.ccByte15 = 0x49; /* 0x49; */ else pCFD->cfdConfig.ccByte15 = 0x48; /* 0x49 PROMISC; */ pCFD->cfdConfig.ccByte16 = 0x00; pCFD->cfdConfig.ccByte17 = 0x40; pCFD->cfdConfig.ccByte18 = 0xf2;if (pDrvCtrl->board.phyDpx != PHY_HALF_DPX) pCFD->cfdConfig.ccByte19 = 0x80;else pCFD->cfdConfig.ccByte19 = 0x00; /*c0 force full deplex 0x80; */ pCFD->cfdConfig.ccByte20 = 0x3f; pCFD->cfdConfig.ccByte21 = 0x05; if (!(feiAction (unit, CFD_C_CONFIG) & CFD_S_OK)) return (ERROR); return (OK); }/********************************************************************************* feiIASetup - format and issue an interface address command** RETURNS: OK, or ERROR if the address command failed.*/LOCAL STATUS feiIASetup ( int unit ) { DRV_CTRL * pDrvCtrl = & drvCtrl [unit]; bcopy ((char *) pDrvCtrl->idr.ac_enaddr, (char *) pDrvCtrl->pCFD->cfdIASetup.ciAddress, 6); if (!(feiAction (unit, CFD_C_IASETUP) & CFD_S_OK)) return (ERROR); return (OK); }/********************************************************************************* feiAction - execute the specified action command** This routine executes the specified action** We do the command contained in the CFD synchronously, so that we know* it's complete upon return.** RETURNS: The status return of the action command, or 0 on failure.*/LOCAL UINT16 feiAction ( int unit, UINT16 action ) { DRV_CTRL * pDrvCtrl = & drvCtrl [unit]; CFD * pCFD = pDrvCtrl->pCFD; UINT16 retVal = 0; int ix; UINT8 state; if (!(pCFD->cfdStatus & CFD_S_COMPLETE)) /* next CFD free ? */ return (0); /* fill in CFD */ pCFD->cfdStatus = 0; /* clear status */ pCFD->cfdCommand = action | CFD_C_SUSP; /* fill in action */ pCFD->pPrev->cfdCommand &= ~CFD_C_SUSP; /* hook into CBL */ pDrvCtrl->pCFD = (CFD *) SYS_TO_LOCAL_ADDR(unit, (UINT32)LINK_RD(&pCFD->link) ); /* bump current CFD */ /* check CU operation -- kick if needed */ if ((((state = pDrvCtrl->pCSR->scbStatus) & SCB_S_CUMASK) != SCB_S_CUACTIVE) && (pCFD->cfdStatus == 0)) { if (state == SCB_S_CUIDLE) { if (feiSCBCommand (pDrvCtrl, SCB_C_CUSTART, TRUE, (UINT32 *) LOCAL_TO_SYS_ADDR(unit,(UINT32)pCFD) ) == ERROR) {#ifdef FEI_DEBUG if (feiDebug) printf ("feiAction: feiSCBCommand failed\n");#endif /* FEI_DEBUG */ goto errorAction; } } else { if (feiSCBCommand (pDrvCtrl, SCB_C_CURESUME, FALSE, 0x0) == ERROR) {#ifdef FEI_DEBUG if (feiDebug) printf ("feiAction: feiSCBCommand failed\n");#endif /* FEI_DEBUG */ goto errorAction; } } } /* wait for command to complete */ for (ix = (FEI_ACTION_TMO * feiClkRate); --ix;) { if ((retVal = pCFD->cfdStatus) & CFD_S_COMPLETE) break; taskDelay (1); } if (!ix) {#ifdef FEI_DEBUG printf ("feiAction: command 0x%x, CFD status 0x%x\n", action, pCFD->cfdStatus);#endif /* FEI_DEBUG */ retVal = 0; goto errorAction; } /* put CFD back to a TxCB - mirrors feiattach() */errorAction: pCFD->cfdStatus = CFD_S_COMPLETE | CFD_S_OK; LINK_WR (&pCFD->cfdTcb.pTBD, 0xffffffff); /* no TBDs used */ pCFD->cfdTcb.txThresh = pDrvCtrl->board.tcbTxThresh; pCFD->cfdTcb.tbdNum = 0; return (retVal); }/********************************************************************************* feiSCBCommand - deliver a command to the 82557 via the SCB** This function causes the device to execute a command. An error status is* returned if the command field does not return to zero, from a previous* command, in a reasonable amount of time.** RETURNS: OK, or ERROR if the command field appears to be frozen.*/LOCAL STATUS feiSCBCommand ( DRV_CTRL * pDrvCtrl, UINT8 cmd, BOOL addrValid, UINT32 * addr ) { int ix; for (ix = 0x8000; --ix;) { if ((pDrvCtrl->pCSR->scbCommand & SCB_CR_MASK) == 0) break; } if (!ix) {#ifdef FEI_DEBUG if (feiDebug) printf ("feiSCBCommand: command 0x%x failed, scb 0x%x\n", cmd, pDrvCtrl->pCSR->scbCommand);#endif /* FEI_DEBUG */ return (ERROR); } if (addrValid) /* optionally fill the GP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -