📄 motcpmend.c
字号:
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); return (OK); }/********************************************************************************* motCpmEndIoctl - 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 motCpmEndIoctl ( 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(("motCpmEndIoctl with command = 0x%x \n", cmd, 0, 0, 0, 0, 0)); switch (cmd) { case EIOCSADDR: if (data == NULL) error = EINVAL; 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 = motCpmEndPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: error = motCpmEndPollStop (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; } return (error); }/********************************************************************************* motCpmEndMCastAddrAdd - 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 motCpmEndMCastAddrAdd ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddr /* Address to add to the table. */ ) { STATUS error; MOTCPMLOGMSG(("motCpmEndMCastAddrAdd %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 */ motCpmMCastFilterSet (pDrvCtrl, pAddr); error = OK; } return ((error == OK) ? OK : ERROR); }/********************************************************************************* motCpmEndMCastAddrDel - 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 motCpmEndMCastAddrDel ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddr /* Address to delete from the table. */ ) { STATUS error; MOTCPMLOGMSG(("motCpmEndMCastDel %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--; motCpmMCastConfig (pDrvCtrl); error = OK; } return ((error == OK) ? OK : ERROR); }/********************************************************************************* motCpmEndMCastAddrGet - get the current multicast address list** This routine returns the current multicast address list in <pTable>**/LOCAL STATUS motCpmEndMCastAddrGet ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ MULTI_TABLE *pTable /* table to fill in with addresses */ ) { MOTCPMLOGMSG(("motCpmEndMCastAddrGet \n", 0, 0, 0, 0, 0, 0)); return (etherMultiGet (&pDrvCtrl->endObject.multiList, pTable)); }/********************************************************************************* motCpmEndPollStart - 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 motCpmEndPollStart ( END_CTRL *pDrvCtrl /* pointer to END_CTRL structure */ ) { int intLevel; int txBdIndex; SCC_BUF * pTxBd; MOTCPMLOGMSG(("motCpmEndPollStart \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; motCpmTxRestart (pDrvCtrl); } /* increment txBdIndex */ txBdIndex = (txBdIndex + 1) % pDrvCtrl->ether.txBdNum; } /* free all transmit buffer and update transmit queue */ motCpmCleanTxBdQueue (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); return (OK); }/********************************************************************************* motCpmEndPollStop - 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 motCpmEndPollStop ( END_CTRL *pDrvCtrl /* pointer to END_CTRL structure */ ) { int intLevel; MOTCPMLOGMSG(("motCpmEndPollStop \n", 0, 0, 0, 0, 0, 0)); /* lock interrupt */ intLevel = intLock(); /* reset the SCC's interrupt status bit */ *CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask; /* enable this SCC's interrupt */ *CPM_CIMR(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); }/******************************************************************************** motCpmEndPollSend - transmit a packet in polled mode** This routine is called by a user to try and send a packet on the* device. It sends a packet directly on the network from the caller without* going through the normal processes of queuing a pacet on an output queue* and the waiting for the device to decide to transmit it.** If it detects a transmission error, the restart command is issued.** These routine should not call any kernel functions.** RETURNS: OK or EAGAIN*/LOCAL STATUS motCpmEndPollSend ( END_CTRL *pDrvCtrl, /* pointer to END_CTRL structure */ M_BLK_ID pMblk /* data to send */ ) { int length; SCC_BUF * pTxBd; u_char * pad; char * pBuf; MOTCPMLOGMSG(("motCpmEndPollSend \n", 0, 0, 0, 0, 0, 0)); if (pDrvCtrl->txStop) return (ERROR); /* get a free transmit frame descriptor */ pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext]; /* check if a transmit buffer descriptor is available */ if ((pTxBd->statusMode & SCC_ETHER_TX_BD_R) || (((pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum) == pDrvCtrl->txBdIndexC)) { motCpmCleanTxBdQueue (pDrvCtrl); return (EAGAIN); } /* fill the transmit frame descriptor */ pBuf = netClusterGet (pDrvCtrl->endObject.pNetPool, pDrvCtrl->pClPoolId); if (pBuf == NULL) { return (ERROR); } length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL); 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; 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; /* incr BD count */ pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum; /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); /* * Spin until we've sent it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -