📄 motcpmend.c
字号:
*/ while (pTxBd->statusMode & SCC_ETHER_TX_BD_R) ; if (pTxBd->statusMode & (SCC_ETHER_TX_BD_RL | SCC_ETHER_TX_BD_UN | SCC_ETHER_TX_BD_CSL | SCC_ETHER_TX_BD_LC)) { /* An error has occured, restart the transmitter */ pDrvCtrl->txStop = TRUE; motCpmTxRestart (pDrvCtrl); } /* * we are allow to do this because transmit queue is empty when we * start polling mode. */ netClFree (pDrvCtrl->endObject.pNetPool, pBuf); pDrvCtrl->txBdIndexC = pDrvCtrl->ether.txBdNext; return (OK); }/********************************************************************************* motCpmEndPollReceive - receive a packet in polled mode** This routine is called by a user to try and get a packet from the* device. It returns EAGAIN if no packet is available. The caller must* supply a M_BLK_ID with enough space to contain the receiving packet. If* enough buffer is not available then EAGAIN is returned.** These routine should not call any kernel functions.** RETURNS: OK or EAGAIN*/LOCAL STATUS motCpmEndPollReceive ( END_CTRL *pDrvCtrl, /* pointer to END_CTRL structure */ M_BLK_ID pMblk ) { SCC_BUF * pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext]; int length; int status = EAGAIN; MOTCPMLOGMSG(("motCpmEndPollReceive \n", 0, 0, 0, 0, 0, 0)); /* if we have not received packets, leave immediatly */ if (pRxBd->statusMode & SCC_ETHER_RX_BD_E) return (EAGAIN); /* check packets for errors */ if (((pRxBd->statusMode & (SCC_ETHER_RX_BD_F | SCC_ETHER_RX_BD_L)) == (SCC_ETHER_RX_BD_F | SCC_ETHER_RX_BD_L)) && !(pRxBd->statusMode & (SCC_ETHER_RX_BD_CL | SCC_ETHER_RX_BD_OV | SCC_ETHER_RX_BD_CR | SCC_ETHER_RX_BD_SH | SCC_ETHER_RX_BD_NO | SCC_ETHER_RX_BD_LG))) { /* adjust length to data only */ length = pRxBd->dataLength; if ((length - SIZEOF_ETHERHEADER) <= 0) { /* bump input error packet counter */ END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1); goto cleanRxBd; } /* * Upper layer provides the buffer. * If buffer is not large enough, we return. */ /* copy data */ if ((pMblk->mBlkHdr.mLen < length) || (!(pMblk->mBlkHdr.mFlags & M_EXT))) { goto cleanRxBd; } bcopy ((char *) pRxBd->dataPointer, (char *)pMblk->mBlkHdr.mData, length); pMblk->mBlkHdr.mLen = length; pMblk->mBlkPktHdr.len = length; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* bump input packet counter */ END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_UCAST, +1); status = OK; } else { /* bump input error packet counter */ END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1); }cleanRxBd: motCpmCleanRxBd (pDrvCtrl, pRxBd); /* reset buffer descriptor as empty */ return (status); }/********************************************************************************* motCpmIntr - network interface interrupt handler** This routine gets called at interrupt level. It handles work that * requires minimal processing. Interrupt processing that is more * extensive gets handled at task level. The network task, netTask(), is * provided for this function. Routines get added to the netTask() work * queue via the netJobAdd() command.** RETURNS: N/A*/LOCAL void motCpmIntr ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { BOOL rxHandle = FALSE; BOOL txbHandle = FALSE; /* check for spurious interrupt -> initialized ? */ if (!pDrvCtrl->endObject.attached) { pDrvCtrl->ether.pSccReg->scce = 0xffff; *CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask; return; } /* handle receive events */ if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_RXF) && (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_RXF)) { (void) netJobAdd ((FUNCPTR) motCpmHandleInt, (int) pDrvCtrl, 0, 0, 0, 0); /* turn off receive interrupts for now - motCpmHandleIt turns back on */ pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_RXF; rxHandle = TRUE; } /* check for output errors */ if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXE) { /* clean the transmit buffer descriptor queue */ /* NOTE: HBC error not supported -> always RESTART Tx here */ (void) netJobAdd ((FUNCPTR) motCpmTxRestart, (int) pDrvCtrl, 0, 0, 0, 0); pDrvCtrl->txStop = TRUE; } /* handle transmitter events - BD full condition -> ever happen ? */ if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_TXB) && (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXB)) { txbHandle = TRUE; } /* check for input busy condition */ if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_BSY) pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_BSY; /* acknowledge all other interrupts - ignore events */ pDrvCtrl->ether.pSccReg->scce = (pDrvCtrl->ether.pSccReg->scce & ~(SCC_ETHER_SCCX_RXF | SCC_ETHER_SCCX_TXE | SCC_ETHER_SCCX_TXB | SCC_ETHER_SCCX_BSY)); /* * clean the transmit buffer descriptor queue if we have * received a transmit interrupt and if we are not already * cleaning this transmit queue. */ if ((pDrvCtrl->txStop || txbHandle) && !pDrvCtrl->txCleaning) { motCpmCleanTxBdQueue (pDrvCtrl); if (pDrvCtrl->txBlocked) { pDrvCtrl->txBlocked = FALSE; (void) netJobAdd ((FUNCPTR) muxTxRestart, (int)&pDrvCtrl->endObject, 0, 0, 0, 0); } } /* acknowledge interrupts */ if (rxHandle) pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_RXF; if (pDrvCtrl->txStop) pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXE; if (txbHandle) pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXB; *CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask; }/********************************************************************************* motCpmMCastFilterSet - set the group addres filter for a multicast addresse.** To add an address in the processor group address hash filter, we use* the SET GROUP ADDRESS command. This command can be executed at any * time, regadless of whether the Ethernet channel is enabled.** RETURNS : N/A **/LOCAL void motCpmMCastFilterSet ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddress /* Address to delete from the table. */ ) { MOTCPMLOGMSG(("motCpmMCastFilterSet \n", 0, 0, 0, 0, 0, 0)); /* add multicast address */ ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_h = (pAddress[5] << 8) + pAddress[4]; ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_m = (pAddress[3] << 8) + pAddress[2]; ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_l = (pAddress[1] << 8) + pAddress[0]; /* issue the set group address command to the CP */ while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); *CPM_CPCR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) | CPM_CR_SCC_SET_GROUP | CPM_CR_FLG; while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); }/********************************************************************************* motCpmMCastConfig - reconfigure the interface under us.** Reconfigure the interface changing the multicast interface list.** In order to delete an address from the hash tabke, the Ethernet channel* should be disabled, the hash table registers should be cleared, and * the SET GROUP ADDRESS command must be executed for the remaining * desired addresses. This is required because the hash table may have mapped* multiple addresses to the same hash table bit.** RETURNS : N/A */LOCAL void motCpmMCastConfig ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { ETHER_MULTI * pCurr; MOTCPMLOGMSG(("motCpmMCastConfig \n",0,0,0,0,0,0)); /* disable the ethernet channel */ motCpmReset (pDrvCtrl); /* clear hash table group registers */ ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr1 = 0x0000; ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr2 = 0x0000; ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr3 = 0x0000; ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr4 = 0x0000; /* restore remaining addresses */ for (pCurr = END_MULTI_LST_FIRST(&pDrvCtrl->endObject); pCurr != NULL; pCurr = (ETHER_MULTI *)lstNext(&pCurr->node)) { /* add multicast address */ motCpmMCastFilterSet (pDrvCtrl, pCurr->addr); } /* restart the ethernet channel */ motCpmRestart (pDrvCtrl); }/********************************************************************************* motCpmRestart - network interface restart routine** This routine restarts the device. This includes enabling interrupts, * starting the transmitter and receiver, and calling the bsp-specific* LAN enable routine to do any target specific enabling.** This routine follows the instructions in MC68EN360/MPC821 Users's Manual :* "Disabling the SCCs on the Fly"** The complement of this routine is motCpmReset(). Once a unit is reset by* motCpmReset(), it may be re-initialized to a running state by this routine.** RETURNS: N/A*/LOCAL STATUS motCpmRestart ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { /* enable Ethernet interrupts */ *CPM_CIMR(pDrvCtrl->regBase) |= pDrvCtrl->ether.intMask; /* call the BSP to do any other initialization (e.g., connecting clocks) */ SYS_ENET_ENABLE; /* enable the transmitter */ pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENT; /* issue the restart transmitter command to the CP */ while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); *CPM_CPCR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) | CPM_CR_SCC_RESTART | CPM_CR_FLG; while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); /* issue the enter hunt mode command to the CP */ while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); *CPM_CPCR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) | CPM_CR_SCC_HUNT | CPM_CR_FLG; while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); /* enable the receiver */ pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENR; return (OK); }/********************************************************************************* motCpmReset - network interface reset routine** This routine resets the device. This includes disabling interrupts, * stopping the transmitter and receiver, and calling the bsp-specific* LAN disable routine to do any target specific disabling.** This routine follows the instructions in MC68EN360/MPC821 Users's Manual :* "Disabling the SCCs on the Fly"** The complements of this routine are motCpmEndStart() and motCpmRestart(). * Once a unit is reset in this routine, it may be re-started with parameters* reinitialized with motCpmEndStart() or re-started with current parameteres * with motCpmRestart().** RETURNS: N/A*/LOCAL void motCpmReset ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { int counter = 0xffff; /* disable the SCC interrupts */ *CPM_CIMR(pDrvCtrl->regBase) &= ~pDrvCtrl->ether.intMask; /* issue the CP graceful stop command to the transmitter if necessary */ if (pDrvCtrl->ether.pSccReg->gsmrl & SCC_GSMRL_ENT) { while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); *CPM_CPCR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) | CPM_CR_SCC_GRSTOP | CPM_CR_FLG; while (*CPM_CPCR(pDrvCtrl->regBase) & CPM_CR_FLG); /* wait for graceful stop to register */ while ((counter--) && (!(pDrvCtrl->ether.pSccReg->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -