📄 m8260sccend.c
字号:
intUnlock(s); return(END_ERR_BLOCK); } /* fill the transmit frame descriptor */ pBuf = NULL; pBuf = netClusterGet(pDrvCtrl->endObject.pNetPool, pDrvCtrl->pClPoolId); if (pBuf == NULL) { END_TX_SEM_GIVE (&pDrvCtrl->endObject); netMblkClChainFree(pMblk); return(ERROR); } length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL); netMblkClChainFree(pMblk); pTxBd->dataPointer = (u_char *) pBuf; /* padding mechanism in Rev A is buggy - do in software */ if (length < FRAME_MIN) { pad = pTxBd->dataPointer + length; for (; length != FRAME_MIN; length++, pad++) *pad = 0x88; } pTxBd->dataLength = length; oldLevel = intLock (); /* disable ints during update */ if (pTxBd->statusMode & SCC_ETHER_TX_BD_W) pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD | SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC | SCC_ETHER_TX_BD_W | SCC_ETHER_TX_BD_R; else pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD | SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC | SCC_ETHER_TX_BD_R; pDrvCtrl->freeRtn[pDrvCtrl->ether.txBdNext] = (FUNCPTR) netClFree; pDrvCtrl->freeData[pDrvCtrl->ether.txBdNext].arg1 = pDrvCtrl->endObject.pNetPool; pDrvCtrl->freeData[pDrvCtrl->ether.txBdNext].arg2 = pBuf; /* incr BD count */ pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum; /* Unlock interrupts */ intUnlock (oldLevel); /* release semaphore */ END_TX_SEM_GIVE (&pDrvCtrl->endObject); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); return(OK); }/********************************************************************************* motSccEndIoctl - network interface control routine** This routine implements the network interface control functions.* It handles EIOCSIFADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS,* EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 and EIOCGFBUF commands.** RETURNS: OK if successful, otherwise EINVAL.*/LOCAL int motSccEndIoctl ( END_CTRL * pDrvCtrl,/* pointer to END_CTRL structure */ int cmd, /* command to process */ caddr_t data /* pointer to data */ ) { int error = 0; /* error value */ long value; END_OBJ * pEndObj = &pDrvCtrl->endObject; MOTCPMLOGMSG(("motSccEndIoctl with command = 0x%x \n", cmd, 0, 0, 0, 0, 0)); switch ((UINT32) cmd) { case EIOCSADDR: if (data == NULL) error = EINVAL; else bcopy ((char *)data, (char *)END_HADDR(pEndObj), END_HADDR_LEN(pEndObj)); break; case EIOCGADDR: if (data == NULL) error = EINVAL; else bcopy ((char *)END_HADDR(pEndObj), (char *)data, END_HADDR_LEN(pEndObj)); break; case EIOCSFLAGS: value = (long) data; if (value < 0) { value = -value; value--; END_FLAGS_CLR (pEndObj, value); } else END_FLAGS_SET (pEndObj, value); /* set promisc bit off flags */ if (END_FLAGS_GET(pEndObj) & IFF_PROMISC) pDrvCtrl->ether.pSccReg->psmr |= SCC_ETHER_PSMR_PRO; else pDrvCtrl->ether.pSccReg->psmr &= ~SCC_ETHER_PSMR_PRO; break; case EIOCGFLAGS: if (data == NULL) error = EINVAL; else *(int *)data = END_FLAGS_GET(pEndObj); break; case EIOCPOLLSTART: error = motSccEndPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: error = motSccEndPollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) error = EINVAL; else bcopy((char *)&pDrvCtrl->endObject.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObject.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) error = EINVAL; else *(int *)data = LENGTH_MIN_FBUF; break; default: error = EINVAL; } MOTCPMLOGMSG(("motSccEndIoctl: DONE status %x \n", error, 0, 0, 0, 0, 0)); return(error); }/********************************************************************************* motSccEndMCastAddrAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for. ** 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 : OK or ERROR*/LOCAL STATUS motSccEndMCastAddrAdd ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddr /* Address to add to the table. */ ) { STATUS error; MOTCPMLOGMSG(("motSccEndMCastAddrAdd %x:%x:%x:%x:%x:%x \n", pAddr[5], pAddr[4], pAddr[3], pAddr[2], pAddr[1], pAddr[0])); error = etherMultiAdd (&pDrvCtrl->endObject.multiList, pAddr); if (error == ENETRESET) { pDrvCtrl->endObject.nMulti++; /* Set the multicast address */ motSccMCastFilterSet (pDrvCtrl, pAddr); error = OK; } return((error == OK) ? OK : ERROR); }/********************************************************************************* motSccEndMCastAddrDel - delete a multicast address for the device** This routine deletes a multicast address from the current list of* multicast addresses.** RETURNS : OK or ERROR*/LOCAL STATUS motSccEndMCastAddrDel ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddr /* Address to delete from the table. */ ) { STATUS error; MOTCPMLOGMSG(("motSccEndMCastDel %x:%x:%x:%x:%x:%x \n", pAddr[5], pAddr[4], pAddr[3], pAddr[2], pAddr[1], pAddr[0])); error = etherMultiDel (&pDrvCtrl->endObject.multiList, pAddr); if (error == ENETRESET) { pDrvCtrl->endObject.nMulti--; motSccMCastConfig (pDrvCtrl); error = OK; } return((error == OK) ? OK : ERROR); }/********************************************************************************* motSccEndMCastAddrGet - get the current multicast address list** This routine returns the current multicast address list in <pTable>**/LOCAL STATUS motSccEndMCastAddrGet ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ MULTI_TABLE * pTable /* table to fill in with addresses */ ) { MOTCPMLOGMSG(("motSccEndMCastAddrGet \n", 0, 0, 0, 0, 0, 0)); return (etherMultiGet (&pDrvCtrl->endObject.multiList, pTable)); }/********************************************************************************* motSccEndPollStart - start polling mode** This routine starts polling mode by disabling ethernet interrupts and* setting the polling flag in the END_CTRL stucture.** It is necessary to empty transmit queue before entering polling mode* because M_BLK_ID free routine used in interrupt mode could be unusable * in this mode (could use kernel calls). ** RETURNS: OK or ERROR if already in polling mode.*/LOCAL STATUS motSccEndPollStart ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { int intLevel; int txBdIndex; SCC_BUF * pTxBd; MOTCPMLOGMSG(("motSccEndPollStart \n", 0, 0, 0, 0, 0, 0)); /* Lock interrupts */ intLevel = intLock(); /* clean transmit queue */ txBdIndex = pDrvCtrl->txBdIndexC; while (txBdIndex != pDrvCtrl->ether.txBdNext) { pTxBd = & pDrvCtrl->ether.txBdBase[txBdIndex]; /* Spin until frame buffer is sent */ while (pTxBd->statusMode & SCC_ETHER_TX_BD_R) ; /* Check for transmit errors */ 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; motSccTxRestart (pDrvCtrl); } /* increment txBdIndex */ txBdIndex = (txBdIndex + 1) % pDrvCtrl->ether.txBdNum; } /* free all transmit buffer and update transmit queue */ motSccCleanTxBdQueue (pDrvCtrl); /* Now, transmit queue is empty. We can enter polling mode. */ /* mask off the receive and transmit interrupts */ pDrvCtrl->ether.pSccReg->sccm = 0; /* Set the polling flag */ pDrvCtrl->polling = TRUE; /* Unlock interrupts */ intUnlock (intLevel); MOTCPMLOGMSG(("motSccEndPollStart OK\n", 0, 0, 0, 0, 0, 0)); return(OK); }/********************************************************************************* motSccEndPollStop - stop polling mode** This routine stops polling mode by enabling ethernet interrupts and* resetting the polling flag in the END_CTRL structure.** RETURNS: OK always*/LOCAL STATUS motSccEndPollStop ( END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */ ) { int intLevel; MOTCPMLOGMSG(("motSccEndPollStop \n", 0, 0, 0, 0, 0, 0)); /* lock interrupt */ intLevel = intLock(); /* reset the SCC's interrupt status bit */ *M8260_SIPNR_L(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask; /* enable this SCC's interrupt */ *M8260_SIMR_L(pDrvCtrl->regBase) |= pDrvCtrl->ether.intMask; /* reset the status bits */ pDrvCtrl->ether.pSccReg->scce = 0xffff; /* enables the receive and transmit interrupts */ pDrvCtrl->ether.pSccReg->sccm = SCC_ETHER_SCCX_RXF | SCC_ETHER_SCCX_TXE | SCC_ETHER_SCCX_TXB; /* reset the polling flag */ pDrvCtrl->polling = FALSE; /* unlock interrupt */ intUnlock (intLevel); return(OK); }/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -