📄 elt3c509end.c
字号:
* the device from operating in interrupt mode.** RETURNS: OK or ERROR.*/LOCAL STATUS elt3c509Stop ( void * pEnd /* device to be stopped */ ) { STATUS result = OK; ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); elt3c509Reset(pDrvCtrl); SYS_INT_DISCONNECT (pDrvCtrl, elt3c509Int, (int)pDrvCtrl, &result); if (result == ERROR) { ENDLOGMSG (("Could not diconnect interrupt!\n", 1, 2, 3, 4, 5, 6)); } SYS_INT_DISABLE (pDrvCtrl); END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING); return (result); }/******************************************************************************** elt3c509Unload - 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 elt3c509Unload ( void * pEnd /* device to be unloaded */ ) { ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); END_OBJECT_UNLOAD (&pDrvCtrl->endObj); if (pDrvCtrl->endClDesc.memArea != NULL) free (pDrvCtrl->endClDesc.memArea); if (pDrvCtrl->endClConfig.memArea != NULL) free ( pDrvCtrl->endClConfig.memArea); if (pDrvCtrl->endObj.pNetPool != NULL) free (pDrvCtrl->endObj.pNetPool); return (OK); }/********************************************************************************* elt3c509Ioctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, OK or ERROR or EINVAL.*/LOCAL int elt3c509Ioctl ( void * pEnd, /* device ptr*/ int cmd, /* ioctl command code */ caddr_t data /* command argument */ ) { int error = 0; long value; ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); 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); END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else { END_FLAGS_SET (&pDrvCtrl->endObj, value); } elt3c509Config (pDrvCtrl); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCPOLLSTART: error = elt3c509PollStart(pDrvCtrl); break; case EIOCPOLLSTOP: error = elt3c509PollStop(pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: return (EINVAL); /* no scatter gather supported for the chip */ break; case EIOCGMWIDTH: if (data == NULL) return (EINVAL); break; case EIOCGHDRLEN: if (data == NULL) return (EINVAL); *(int *)data = EH_SIZE; break; default: error = EINVAL; } return (error); }/********************************************************************************* elt3c509Send - 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.** RETURNS: OK or END_ERR_BLOCK or ERROR.*/LOCAL STATUS elt3c509Send ( void * pEnd, /* device ptr */ M_BLK_ID pMblk /* data to send */ ) { int len; int * pLenMask; char * pBuf; int intLevel; ELT3C509_DEVICE * pDrvCtrl; UINT16 tempData; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); /* change this drv flag set */ if (pDrvCtrl->flags & ELT3C_POLLING) return (ERROR); /* check if transmitter ready */ SYS_IN_WORD (pDrvCtrl, pDrvCtrl->port + TX_FREE_BYTES, tempData); if (tempData >= TX_IDLE_COUNT) { pBuf = pDrvCtrl->pTxCluster; /* pointer to the transmit cluster */ pLenMask = (UINT32 *)pBuf; /* allow space for the preamble the trasmit buffer is 1520 */ pBuf += sizeof(UINT32); len = netMblkToBufCopy (pMblk, pBuf, NULL); /* free the mblk chain */ netMblkClChainFree (pMblk); len = max(len, ETHERSMALL); /* set the packet size */ *pLenMask = len | TX_F_INTERRUPT; /* set the preamble */ len = (len + TX_F_PREAMBLE_SIZE + 3) & TX_F_DWORD_MASK; /* place a transmit request */ SYS_OUT_WORD_STRING (pDrvCtrl, pDrvCtrl->port + DATA_REGISTER, (short *)pLenMask, len / 2); } else { intLevel = intLock(); pDrvCtrl->txBlocked = TRUE; intUnlock (intLevel); ENDLOGMSG(("Error in Send, not enough TxFreeBytes\n",1,2,3,4,5,6)); return (END_ERR_BLOCK); } /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); ENDLOGMSG (("Send complete\n",1,2,3,4,5,6)); return (OK); }/******************************************************************************* elt3c509MCastAdd - 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 elt3c509MCastAdd ( void * pEnd, /* device pointer */ char * pAddress /* new address to add */ ) { int error; ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddress)) == ENETRESET) elt3c509Config (pDrvCtrl); return (OK); }/******************************************************************************* elt3c509MCastDel - 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 elt3c509MCastDel ( void * pEnd, /* device pointer */ char * pAddress /* address to be deleted */ ) { int error; ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList, (char *)pAddress)) == ENETRESET) elt3c509Config (pDrvCtrl); return (OK); }/******************************************************************************* elt3c509MCastGet - 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 elt3c509MCastGet ( void * pEnd, /* device pointer */ MULTI_TABLE * pTable /* address table to be filled in */ ) { ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable)); }/********************************************************************************* elt3c509Int - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void elt3c509Int ( ELT3C509_DEVICE * pDrvCtrl /* interrupting device */ ) { UINT16 status; UINT16 statusDiag; UINT8 statusTx; int port; BOOL needTxStart = FALSE; port = pDrvCtrl->port; ENDLOGMSG (("Got an interrupt!\n", 1, 2, 3, 4, 5, 6));#ifdef ELT_TIMING { int time; SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + TIMER, time); if (time> pDrvCtrl->elt3c509Stat.maxIntLatency) pDrvCtrl->elt3c509Stat.maxIntLatency = time; if (pDrvCtrl->interruptTime == -1) pDrvCtrl->interruptTime = time; else if (pDrvCtrl->interruptTime >= 0) pDrvCtrl->interruptTime = -1; }#endif /* ELT_TIMING */ SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + ELT3C509_STATUS, status); status &= 0x00ff; if ((status & INTERRUPT_LATCH) == 0) { ++pDrvCtrl->elt3c509Stat.strayint; return; } else ++pDrvCtrl->elt3c509Stat.interrupts; /* Handle adapter failure first in case other conditions mask it */ if ((status & ADAPTER_FAILURE) != 0) { SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_DIAGNOSTIC); SYS_IN_WORD (pDrvCtrl, port + FIFO_DIAGNOSTIC, statusDiag); SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_OPERATING); if ((statusDiag & FD_TX_OVERRUN) != 0) { ++pDrvCtrl->elt3c509Stat.txoverruns; SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, TX_RESET); elt3c509TxStart (pDrvCtrl); } if ((status & FD_RX_UNDERRUN) != 0) { ++pDrvCtrl->elt3c509Stat.rxunderruns; SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, RX_RESET); elt3c509RxStart (pDrvCtrl); } } if (status & (RX_COMPLETE | RX_EARLY)) { if ((status & RX_EARLY) != 0) ++pDrvCtrl->elt3c509Stat.rxearly; if (netJobAdd ((FUNCPTR)elt3c509HandlePktsRcv, (int) pDrvCtrl, 0, 0, 0, 0) == OK) { pDrvCtrl->intMask &= ~(RX_COMPLETE | RX_EARLY); #ifdef ELT_TIMING if((int)++pDrvCtrl->elt3c509Stat.taskQRxOuts > (int)pDrvCtrl->elt3c509Stat.maxRxTaskQ) { pDrvCtrl->elt3c509Stat.maxRxTaskQ = pDrvCtrl->elt3c509Stat.taskQRxOuts; }#endif /* ELT_TIMING */ } else logMsg ("elt: netJobAdd (elt3c509HandlePktsRcv) failed\n", 0, 0, 0, 0, 0, 0); } /* Handle transmitter interrupts */ if ((status & TX_COMPLETE) != 0) { SYS_IN_BYTE (pDrvCtrl, port+TX_STATUS, statusTx); if ((statusTx & TX_S_COMPLETE) != 0) { SYS_OUT_BYTE (pDrvCtrl,port + TX_STATUS, 0); /* clear old status */ /* * other errors are tabulated by reading the statistics registers */ if ((statusTx & TX_S_MAX_COLL) != 0) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +16); if ((statusTx & TX_S_JABBER) != 0) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); if ((statusTx & (TX_S_JABBER | TX_S_MAX_COLL | TX_S_UNDERRUN)) != 0) { needTxStart = TRUE; /* restart transmitter */ /* packet not sent */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -