📄 sngks32cend.c
字号:
RECEIVE_FRAME_DESC *pRxD, /* frame descriptor */ UINT32 len ) { M_BLK_ID pMblk;#if (NEW_NET_BUF == 0) char *pNewCluster; CL_BLK_ID pClBlk; char *pData;#else /* NEW_NET_BUF != 0 */ M_BLK_ID pNewMblk; UINT32 count;#endif /* NEW_NET_BUF != 0 */#ifdef BUG_KS32C5000 sngks32cEndBugFix (pRxD); /* Support original KS32C5000 */#endif /*BUG_KS32C5000*/#if (NEW_NET_BUF == 0) if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: Out of M Blocks!\n", 0,0,0,0,0,0); goto sngks32cEndRecv_noMblk; } pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]); if (pNewCluster == NULL) { DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: Cannot loan!\n", 0,0,0,0,0,0); goto sngks32cEndRecv_noCluster; } /* Grab a cluster block to marry to the cluster we received. */ if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: Out of Cluster Blocks!\n", 0,0,0,0,0,0); goto sngks32cEndRecv_noClBlk; } pData = (char *)pRxD->rxFrameData.frameDataPtr; pData = END_CACHE_PHYS_TO_VIRT(pData); /* Note: we rely on the hardware to pad 2 bytes so we don't need to copy to * a new buffer to solve alignment problems */ /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pData, SNGKS32C_CL_SIZE, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pRxD->rxFrameData.frameDataPtr = (UINT32)pNewCluster;#else /* NEW_NET_BUF != 0 */ count = pRxD - (RECEIVE_FRAME_DESC *)pDrvCtrl->fdMem; pMblk = pDrvCtrl->rxMblkArray [count]; pNewMblk = SNG_TUPLE_GET (pDrvCtrl); if (pNewMblk == NULL) goto sngks32cEndRecv_noMblk; pDrvCtrl->rxMblkArray [count] = pNewMblk; pRxD->rxFrameData.frameDataPtr = (UINT32) END_CACHE_PHYS_TO_VIRT (pNewMblk->mBlkHdr.mData);#endif /* NEW_NET_BUF != 0 */ /* Should check if it's really unicast... */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* The ip structure is 14 bytes from the beginning of the valid frame data * yet it must be aligned on a word boundary. We have told the ethernet * controller to insert 2 bytes of garbage at the beginning of each frame * so now all we need to do is move our pointer to the frame data to the * real start of the frame causing the frame to be half-word aligned but * not word aligned. By counting 14 bytes from the beginning of the frame * to the ip, we arrive on a word boundary. */ pMblk->mBlkHdr.mData += SNGKS32C_DATA_OFFSET;#ifdef BUG_KS32C5000 if (gBugFixDone == TRUE) /* Only for old KS32C5000 version of the chip */ pMblk->mBlkHdr.mData += 4;#endif /*BUG_KS32C5000*/ pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = len; pMblk->mBlkPktHdr.len = len; /* * Ugh. * We should really invalidate the (cached) used address range of the * cluster here, but the invalidate routine is too expensive; and the * unified cache is sufficiently small that we're unlikely to get stale * data anyway. In the rare cases we do, rely on the network checksums. */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); return (OK);#if (NEW_NET_BUF == 0)sngks32cEndRecv_noClBlk: netClFree (pDrvCtrl->end.pNetPool, pNewCluster);sngks32cEndRecv_noCluster: netMblkFree (pDrvCtrl->end.pNetPool, pMblk);sngks32cEndRecv_noMblk:#else /* NEW_NET_BUF != 0 */sngks32cEndRecv_noMblk: DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: Out of M Blocks!\n", 0,0,0,0,0,0);#endif /* NEW_NET_BUF != 0 */ /* Should be 'discards', not 'errs'... */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->end, &pDrvCtrl->lastError); return (ERROR); }/******************************************************************************** sngks32cEndSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine. ** RETURNS: OK or ERROR.*/LOCAL STATUS sngks32cEndSend ( END_DEVICE *pDrvCtrl, /* device ptr */ M_BLK_ID pNBuff /* data to send */ ) { int len; int oldLevel; TRANSMIT_FRAME_DESC *pTxFd; BDMATXCON bdmaTxCon; MACTXCON macTxCon; *(UINT32 *)(&bdmaTxCon) = 0; *(UINT32 *)(&macTxCon) = 0; if (pDrvCtrl->resetting) { return ERROR; } /* Ownership with BDMA? */ if (pDrvCtrl->pTxFrameDesc->txFrameData.o_bit == OWNED_BY_BDMA) { /* * Ugh, we ought to return END_ERR_BLOCK and use unstall/ * muxTxRestart() logic. For now we just drop the packet. * The wire seems to be faster than the CPU, so we are unlikely to * hit too many of these unless that balance changes. */ ++ pDrvCtrl->txStalls; return ERROR; } pTxFd = pDrvCtrl->pTxFrameDesc; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); /* Set pointers in local structures to point to data. */ len = netMblkToBufCopy(pNBuff, (void *)pTxFd->txFrameData.frameDataPtr, NULL) ; *(UINT32 *)(&pTxFd->txControl) = 0; /* Reset control word */ pTxFd->txControl.t_bit = 1; pTxFd->txControl.a_bit = 1; pTxFd->txControl.l_bit = SNGEND_ENDIAN; pTxFd->txStatusLength.frameLength = len; pTxFd->txFrameData.o_bit = OWNED_BY_BDMA; /* place a transmit request */ oldLevel = intLock (); /* now sngks32cEndInt won't get confused */ /* initiate device transmit */ bdmaTxCon.txCon_resetval = *(volatile UINT32 *)SNGKS32C_BDMATXCON; bdmaTxCon.txCon_reg.enable = 1; *(volatile UINT32 *)SNGKS32C_BDMATXCON = bdmaTxCon.txCon_resetval; macTxCon.macTxCon_resetval = *(volatile UINT32 *)SNGKS32C_MACTXCON; macTxCon.macTxCon_reg.transmitEnable = 1; *(volatile UINT32 *)SNGKS32C_MACTXCON = macTxCon.macTxCon_resetval; intUnlock (oldLevel); /* now sngks32cEndInt won't get confused */ /* Advance our management index */ pDrvCtrl->pTxFrameDesc = pDrvCtrl->pTxFrameDesc->nextTxFrameDesc; END_TX_SEM_GIVE (&pDrvCtrl->end); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); /* * Cleanup. The driver must either free the packet now or * set up a structure so it can be freed later after a transmit * interrupt occurs. */ netMblkClChainFree (pNBuff); return (OK); }/******************************************************************************** sngks32cEndIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL int sngks32cEndIoctl ( END_DEVICE *pDrvCtrl, /* device receiving command */ int cmd, /* ioctl command code */ caddr_t data /* command argument */ ) { int error = 0; long value; DRV_LOG (DRV_DEBUG_IOCTL, "Ioctl unit=0x%x cmd=%d data=0x%x\n", pDrvCtrl->unit, cmd, (int)data, 0, 0, 0); switch ((unsigned int)cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end), END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCGADDR: if (data == NULL) return (EINVAL); bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data, END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = ~value; END_FLAGS_CLR (&pDrvCtrl->end, value); } else { END_FLAGS_SET (&pDrvCtrl->end, value); } sngks32cEndConfig (pDrvCtrl); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->end); break; case EIOCPOLLSTART: sngks32cEndPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: sngks32cEndPollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data, sizeof(pDrvCtrl->end.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) return (EINVAL); *(int *)data = 0; /**END_MIN_FBUF;**/ break; default: error = EINVAL; } return (error); }/******************************************************************************** sngks32cEndConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode** RETURNS: N/A.*/LOCAL void sngks32cEndConfig ( END_DEVICE *pDrvCtrl /* device to be re-configured */ ) { sngks32cEndReset(pDrvCtrl); /* reset the chip */ pDrvCtrl->rxHandling = FALSE; /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0) sngks32cEndAddrFilterSet (pDrvCtrl); if (pDrvCtrl->fdInitialized == TRUE) sngks32cEndFdFree(pDrvCtrl); /* Free the FDs */ /* Reinitialize FDs */ if (sngks32cEndFdInitialize(pDrvCtrl) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "sngks32cEndFdInitialize failed \n", 0, 0, 0, 0, 0, 0); return; } sngks32cEndMacInitialize(pDrvCtrl); /* Initialize MAC */ /* Was started before in interrupt mode? */ if ((END_FLAGS_GET(&pDrvCtrl->end) & IFF_RUNNING) && ((pDrvCtrl->flags & LS_POLLING) == 0)) sngks32cEndStart(pDrvCtrl); /* Start again */ return; }/******************************************************************************** sngks32cEndPollStart - start polled mode operations** RETURNS: OK or ERROR.*/LOCAL STATUS sngks32cEndPollStart ( END_DEVICE* pDrvCtrl /* device to be polled */ ) { int oldLevel; BDMARXCON bdmaRxCon; MACRXCON macRxCon; oldLevel = intLock (); /* disable ints during update */ intDisable (pDrvCtrl->ivecBdmaTx); intDisable (pDrvCtrl->ivecBdmaRx); intDisable (pDrvCtrl->ivecMacTx); intDisable (pDrvCtrl->ivecMacRx); pDrvCtrl->flags |= LS_POLLING; intUnlock (oldLevel); /* now sngks32cEndInt won't get confused */ ENDLOGMSG (("Poll STARTED\n", 1, 2, 3, 4, 5, 6)); sngks32cEndConfig (pDrvCtrl); /* reconfigure device */ /* Enable RX in BDMARXCON register */ *(UINT32 *) (&bdmaRxCon) = *(volatile UINT32 *)SNGKS32C_BDMARXCON; bdmaRxCon.rxCon_reg.enable = 1 ; *(volatile UINT32 *)SNGKS32C_BDMARXCON = bdmaRxCon.rxCon_resetval; /* Enable RX in MACRXCON register */ *(UINT32 *)(&macRxCon) = *(volatile UINT32 *)SNGKS32C_MACRXCON; macRxCon.macRxCon_reg.receiveEnable = 1; *(volatile UINT32 *)SNGKS32C_MACRXCON = macRxCon.macRxCon_resetval; /* Set the flags to indicate that the device is up */ END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING); return (OK); }/******************************************************************************** sngks32cEndPollStop - stop polled mode operations** This function terminates polled mode operation. The device returns to* interrupt mode.** The device interrupts are enabled, the current mode flag is switched* to indicate interrupt mode and the device is then reconfigured for* interrupt operation.** RETURNS: OK or ERROR.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -