📄 ultraend.c
字号:
/* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Transfer to the device and mark TX in progress. */ oldLevel = intLock (); SYS_OUT_BYTE (pDrvCtrl, LAN_TSTART, transmitPage); SYS_OUT_BYTE (pDrvCtrl, LAN_TCNTH, len >> 8); SYS_OUT_BYTE (pDrvCtrl, LAN_TCNTL, len & 0xff); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_TXP); pDrvCtrl->transmitCnt++; pDrvCtrl->flags |= ULTRA_TX_IN_PROGRESS; intUnlock (oldLevel); /* update statistics */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); /* Release semaphore */ if (!(pDrvCtrl->flags & ULTRA_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (OK); } /******************************************************************************** ultraIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL int ultraIoctl ( void * pObj, /* device receiving command */ int cmd, /* ioctl command code */ caddr_t data /* command argument */ ) { long value; int error = 0; ULTRA_DEVICE * pDrvCtrl = pObj; /* device receiving command */ switch (cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj), END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCGADDR: if (data == NULL) return (EINVAL); bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data, END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -(value - 1); END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else { END_FLAGS_SET (&pDrvCtrl->endObj, value); } ultraConfig (pDrvCtrl); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCPOLLSTART: /* Begin polled operation */ ultraPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: /* Ultra polled operation */ ultraPollStop (pDrvCtrl); break; case EIOCGMIB2: /* return MIB information */ if (data == NULL) return (EINVAL); bcopy ((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: /* return minimum First Buffer for chaining */ if (data == NULL) return (EINVAL); *(int *)data = ULTRA_MIN_FBUF; break; case EIOCGHDRLEN: if (data == NULL) return (EINVAL); *(int *)data = SIZEOF_ETHERHEADER; break; default: error = EINVAL; } return (error); }/******************************************************************************** ultraAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the ultraMCastAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A.*/void ultraAddrFilterSet ( ULTRA_DEVICE * pDrvCtrl /* device pointer */ ) { int len; int count; u_char c; u_char * pCp; u_long crc; ETHER_MULTI * pCurr; pDrvCtrl->mcastFilter[0] = 0x00; pDrvCtrl->mcastFilter[1] = 0x00; pDrvCtrl->mcastFilter[2] = 0x00; pDrvCtrl->mcastFilter[3] = 0x00; pDrvCtrl->mcastFilter[4] = 0x00; pDrvCtrl->mcastFilter[5] = 0x00; pDrvCtrl->mcastFilter[6] = 0x00; pDrvCtrl->mcastFilter[7] = 0x00; for (pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj); pCurr != NULL; pCurr = END_MULTI_LST_NEXT(pCurr)) { /* * AUTODIN-II, adapted for ethernet (bit reversed), * taken from the ln7990End.c driver */ pCp = (unsigned char *)&pCurr->addr; crc = 0xffffffff; for (len = 6; --len >= 0;) { c = *pCp++; for (count = 0; count < 8; count++) { if ((c & 0x01) ^ (crc & 0x01)) { crc >>= 1; crc = crc ^ 0xedb88320; } else { crc >>= 1; } c >>= 1; } } /* Just want the 6 most significant bits. */ crc = crc >> 26; /* Turn on the corresponding bit in the filter. */ pDrvCtrl->mcastFilter [crc >> 3] |= (1 << (crc & 0x07)); } }/******************************************************************************* ultraMCastAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS ultraMCastAdd ( void * pObj, /* device pointer */ char * pAddress /* new address to add */ ) { ULTRA_DEVICE * pDrvCtrl = pObj; /* device pointer */ DRV_LOG (DRV_DEBUG_LOAD, "%s%d: ultraMCastAdd\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); if (etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddress) == ENETRESET) ultraConfig (pDrvCtrl); return (OK); }/******************************************************************************* ultraMCastDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS ultraMCastDel ( void * pObj, /* device pointer */ char * pAddress /* address to be deleted */ ) { ULTRA_DEVICE * pDrvCtrl = pObj; /* device pointer */ DRV_LOG (DRV_DEBUG_LOAD, "%s%d: ultraMCastDel\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); if (etherMultiDel (&pDrvCtrl->endObj.multiList, pAddress) == ENETRESET) ultraConfig (pDrvCtrl); return (OK); }/******************************************************************************* ultraMCastGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK or ERROR.*/LOCAL STATUS ultraMCastGet ( void * pObj, /* device pointer */ MULTI_TABLE * pTable /* address table to be filled in */ ) { ULTRA_DEVICE * pDrvCtrl = pObj; /* device pointer */ return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable)); }/******************************************************************************** ultraUnload - unload a driver from the system** This function first brings down the device, and then frees any* stuff that was allocated by the driver in the load function.** RETURNS: OK or ERROR.*/LOCAL STATUS ultraUnload ( void * pObj /* device to be unloaded */ ) { ULTRA_DEVICE * pDrvCtrl = pObj; /* device to be unloaded */ DRV_LOG (DRV_DEBUG_LOAD, "%s%d: ultraUnload\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); END_OBJECT_UNLOAD (&pDrvCtrl->endObj); return (OK); }/******************************************************************************** ultraPollStart - start polled mode operations** RETURNS: OK or ERROR.*/LOCAL STATUS ultraPollStart ( ULTRA_DEVICE * pDrvCtrl ) { int oldLevel; DRV_LOG (DRV_DEBUG_POLL, "%s%d: ultraPollStart\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); oldLevel = intLock (); SYS_OUT_BYTE (pDrvCtrl, LAN_INTMASK, 0x00); pDrvCtrl->flags |= ULTRA_POLLING; intUnlock (oldLevel); return (OK); }/******************************************************************************** ultraPollStop - 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 ultraPollStop ( ULTRA_DEVICE * pDrvCtrl ) { int oldLevel; DRV_LOG (DRV_DEBUG_POLL, "%s%d: ultraPollStop\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); oldLevel = intLock (); SYS_OUT_BYTE (pDrvCtrl, LAN_INTMASK, IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE); pDrvCtrl->flags &= ~ULTRA_POLLING; intUnlock (oldLevel); return (OK); }/******************************************************************************** ultraPollRcv - 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 ultraPollRcv ( void * pObj, /* device to be polled */ M_BLK_ID pMblk /* ptr to buffer */ ) { int len; ULTRA_DEVICE * pDrvCtrl = pObj; /* device to be polled */ /* Don't call DRV_LOG until past the busy-wait */ /* If no packet is available, return immediately */ SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_PS0); SYS_IN_BYTE (pDrvCtrl, LAN_CURR, &pDrvCtrl->current); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, 0); if (pDrvCtrl->nextPacket == pDrvCtrl->current) return (EAGAIN); DRV_LOG (DRV_DEBUG_POLL_RX, "%s%d: ultraPollRcv\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); /* Upper layer must provide a valid buffer. */ if ((pMblk->mBlkHdr.mLen < ULTRA_MAX_SIZE) || !(pMblk->mBlkHdr.mFlags & M_EXT)) { DRV_LOG (DRV_DEBUG_POLL_RX, "%s%d: ultraPollRecv: bad mblk, mLen=%d mFlags=%x\n", (int) DEV_NAME, pDrvCtrl->unit, pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 5, 6); return (EAGAIN); } /* Process device packet into net buffer */ pMblk->mBlkHdr.mData += pDrvCtrl->offset; len = ultraPacketGet (pDrvCtrl, pMblk->mBlkHdr.mData); pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ DRV_LOG (DRV_DEBUG_POLL_RX, "%s%d: ultraPollRcv done, len=%d\n", (int) DEV_NAME, pDrvCtrl->unit, len, 4, 5, 6); return (OK); }/******************************************************************************** ultraPollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device. As this is a single-transmit device, we actually wait* for the previous transmit to complete, otherwise parts of the* packet may be dropped.** RETURNS: OK upon success. EAGAIN if device is busy.*/LOCAL STATUS ultraPollSend ( void * pObj, /* device to be polled */ M_BLK_ID pMblk /* packet to send */ ) { UCHAR cmdStat; int len; UINT transmitPage; UCHAR * pBuf; ULTRA_DEVICE * pDrvCtrl = pObj; DRV_LOG (DRV_DEBUG_POLL_TX, "%s%d: ultraPollSend\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); /* Wait for the last transmit to complete */ do SYS_IN_BYTE (pDrvCtrl, LAN_CMD, &cmdStat); while (cmdStat & CMD_TXP); /* Process the net buffer into a device transmit packet */ transmitPage = pDrvCtrl->transmitPage [pDrvCtrl->transmitCnt & 1]; pBuf = (UCHAR *)(pDrvCtrl->memAddr + (transmitPage << 8)); len = netMblkToBufCopy (pMblk, pBuf, NULL); netMblkClChainFree (pMblk); len = max (len, ETHERSMALL); DRV_LOG (DRV_DEBUG_POLL_TX, "%s%d: ultraPollSend: len=%d\n", (int) DEV_NAME, pDrvCtrl->unit, len, 4, 5, 6); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Transfer to the device */ SYS_OUT_BYTE (pDrvCtrl, LAN_TSTART, transmitPage); SYS_OUT_BYTE (pDrvCtrl, LAN_TCNTH, len >> 8); SYS_OUT_BYTE (pDrvCtrl, LAN_TCNTL, len & 0xff); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_TXP); pDrvCtrl->transmitCnt++; /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); DRV_LOG (DRV_DEBUG_POLL_TX, "%s%d: ultraPollSend: done\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -