?? sngks32cend.c
字號:
/* Join the cluster to the MBlock */ if (netClBlkJoin (pClBlk, pData, SNGKS32C_CL_SIZE, NULL, 0, 0, 0) == NULL) { DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: netClBlkJoin failed\n", 0,0,0,0,0,0); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->end, &pDrvCtrl->lastError); goto cleanRXD; } if (netMblkClJoin (pMblk, pClBlk) == NULL) { DRV_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: netMblkClJoin failed\n", 0,0,0,0,0,0); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->end, &pDrvCtrl->lastError); goto cleanRXD; } /* 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; /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); pRxD->rxFrameData.frameDataPtr = (UINT32)pNewCluster; return (OK);cleanRXD: if (pClBlk != NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); } if (pNewCluster != NULL) { netClFree (pDrvCtrl->end.pNetPool, pNewCluster); pNewCluster = NULL; } if (pMblk != NULL) { netMblkFree (pDrvCtrl->end.pNetPool, pMblk); } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); 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) 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.*/LOCAL STATUS sngks32cEndPollStop ( END_DEVICE* pDrvCtrl /* device to be changed */ ) { BDMARXCON bdmaRxCon; BDMATXCON bdmaTxCon; MACCON macCon; *(UINT32 *)(&bdmaRxCon) = *(volatile UINT32 *)SNGKS32C_BDMARXCON; bdmaRxCon.rxCon_reg.enable = 0; *(volatile UINT32 *)SNGKS32C_BDMARXCON = *(UINT32 *)(&bdmaRxCon); *(UINT32 *)(&bdmaTxCon) = *(volatile UINT32 *)SNGKS32C_BDMATXCON; bdmaTxCon.txCon_reg.enable = 0; *(volatile UINT32 *)SNGKS32C_BDMATXCON = *(UINT32 *)(&bdmaTxCon); *(UINT32 *)(&macCon) = *(volatile UINT32 *)SNGKS32C_MACCON; macCon.macCon_reg.haltImm = 1; *(volatile UINT32 *)SNGKS32C_MACCON = *(UINT32 *)(&macCon); pDrvCtrl->flags &= ~LS_POLLING; pDrvCtrl->rxHandling = TRUE; /* * Restart in interrupt mode. Calling sngks32cEndConfig without clearing * IFF_RUNNING flag will result in calling sngks32cEndStart automatically */ netJobAdd ((FUNCPTR) sngks32cEndConfig, (int) pDrvCtrl, 0, 0, 0, 0); ENDLOGMSG (("Poll STOPPED\n", 1, 2, 3, 4, 5, 6)); return (OK); }/******************************************************************************** sngks32cEndPollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: OK upon success. EAGAIN is returned when no packet is available.*/LOCAL STATUS sngks32cEndPollRcv ( END_DEVICE *pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* ptr to buffer */ ) { BDMASTAT bdmaStat; char* pPacket; int len; STATUS retVal = EAGAIN;#ifdef ENDDEBUG if (endDebug) nvLogMsg ("sngks32cEndPollRcv\n", 1, 2, 3, 4, 5, 6);#endif /* ENDDEBUG */ bdmaStat.stat_resetval = *(volatile UINT32 *)SNGKS32C_BDMASTAT; if (pDrvCtrl->rxHandling) {#ifdef ENDDEBUG if (endDebug) nvLogMsg ("sngks32cEndPollRcv rxHandling\n", 1, 2, 3, 4, 5, 6);#endif /* ENDDEBUG */ return EAGAIN;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -