📄 ns83902end.c
字号:
LOCAL void ns83902ReadPort (NS83902_END_DEVICE* pDrvCtrl, char *pBuf, int len);LOCAL void ns83902WritePort (NS83902_END_DEVICE* pDrvCtrl, char *pBuf, int len);LOCAL STATUS ns83902InitParse (NS83902_END_DEVICE* pDrvCtrl, char * initString);LOCAL STATUS ns83902InitMem (NS83902_END_DEVICE* pDrvCtrl);LOCAL void ns83902EnetAddrGet (NS83902_END_DEVICE* pDrvCtrl, char* addr);LOCAL void ns83902RegSet (NS83902_END_DEVICE* pDrvCtrl, int reg, int value, int page);LOCAL UINT8 ns83902RegRead (NS83902_END_DEVICE* pDrvCtrl, int reg, int page);/* END Specific interfaces. */END_OBJ * ns83902EndLoad (char *initString);LOCAL STATUS ns83902Unload (NS83902_END_DEVICE* pDrvCtrl);LOCAL STATUS ns83902Start (NS83902_END_DEVICE* pDrvCtrl);LOCAL STATUS ns83902Stop (NS83902_END_DEVICE* pDrvCtrl);LOCAL int ns83902Ioctl (NS83902_END_DEVICE* pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS ns83902Send (NS83902_END_DEVICE* pDrvCtrl, M_BLK *pMblk);LOCAL STATUS ns83902MCastAddrAdd (NS83902_END_DEVICE *pDrvCtrl, char* pAddress);LOCAL STATUS ns83902MCastAddrDel (NS83902_END_DEVICE *pDrvCtrl, char* pAddress);LOCAL STATUS ns83902MCastAddrGet (NS83902_END_DEVICE *pDrvCtrl, MULTI_TABLE *pTable);LOCAL STATUS ns83902PollSend (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);LOCAL STATUS ns83902PollReceive (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);LOCAL STATUS ns83902PollStart (NS83902_END_DEVICE *pDrvCtrl);LOCAL STATUS ns83902PollStop (NS83902_END_DEVICE *pDrvCtrl);/* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS ns83902FuncTable = { (FUNCPTR)ns83902Start, /* Function to start the device. */ (FUNCPTR)ns83902Stop, /* Function to stop the device. */ (FUNCPTR)ns83902Unload, /* Unloading function */ (FUNCPTR)ns83902Ioctl, /* Ioctl function */ (FUNCPTR)ns83902Send, /* Send function */ (FUNCPTR)ns83902MCastAddrAdd, /* Multicast address add */ (FUNCPTR)ns83902MCastAddrDel, /* Multicast address delete */ (FUNCPTR)ns83902MCastAddrGet, /* Multicast table retrieve */ (FUNCPTR)ns83902PollSend, /* Polling send function */ (FUNCPTR)ns83902PollReceive, /* Polling receive function */ endEtherAddressForm, /* Put address info into a packet. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet, /* Get packet addresses. */ NULL /* Bind function */ };/******************************************************************************** ns83902EndLoad - initialize the driver and device** This routine initializes the driver and the device to the operational state.* All of the device-specific parameters are passed in <initString>.* This routine can be called in two modes. If it is called with an empty but* allocated string, it places the name of this device (that is, "ln") into * the <initString> and returns 0.** If the string is allocated and not empty, the routine attempts to load* the driver using the values specified in the string.** RETURNS: An END object pointer, or NULL on error, or 0 and the name of the* device if the <initString> was NULL.*/END_OBJ* ns83902EndLoad ( char* initString /* string to be parsed */ ) { NS83902_END_DEVICE *pDrvCtrl; DRV_LOG (NS83902_DEBUG_LOAD, "Loading ns83902End...\n", 1, 2, 3, 4, 5, 6); if (initString == NULL) return (NULL); if (initString[0] == '\0') { bcopy((char *)NS83902_DEV_NAME, initString, NS83902_DEV_NAME_LEN); return (0); } /* allocate the device structure */ pDrvCtrl = (NS83902_END_DEVICE *)calloc (sizeof (NS83902_END_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* parse the init string, filling in the device structure */ if (ns83902InitParse (pDrvCtrl, initString) == ERROR) goto errorExit; /* Have the BSP hand us our address. */ ns83902EnetAddrGet (pDrvCtrl, (char*) &(pDrvCtrl->enetAddr)); DRV_LOG (NS83902_DEBUG_LOAD, "ENET Addr: %x:%x:%x:%x:%x:%x \n", pDrvCtrl->enetAddr[0], pDrvCtrl->enetAddr[1], pDrvCtrl->enetAddr[2], pDrvCtrl->enetAddr[3], pDrvCtrl->enetAddr[4], pDrvCtrl->enetAddr[5]); /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, NS83902_DEV_NAME, pDrvCtrl->unit, &ns83902FuncTable, "ST-NIC Enhanced Network Driver") == ERROR || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], NS83902_EADR_LEN, ETHERMTU, NS83902_SPEED) == ERROR) goto errorExit; /* set buffer address; reserve 8 pages for TX */ pDrvCtrl->txStartPage = 0; pDrvCtrl->rxStartPage = pDrvCtrl->txStartPage + 8; pDrvCtrl->nextPage = pDrvCtrl->rxStartPage; /* size of the whole ring */ pDrvCtrl->rringSize = pDrvCtrl->rxStopPage - pDrvCtrl->rxStartPage + 1; /* Perform memory allocation */ if (ns83902InitMem (pDrvCtrl) == ERROR) { DRV_LOG (NS83902_DEBUG_LOAD, "Error in InitMem...\n", 1, 2, 3, 4, 5, 6); goto errorExit; } /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); DRV_LOG (NS83902_DEBUG_LOAD, "Done loading ns83902End...\n", 1, 2, 3, 4, 5, 6); /* save the device address */#ifdef NS83902_DEBUG ns83902EndDevice = pDrvCtrl; ns83902DmaSemId = pDrvCtrl->endObj.txSem;#endif return (&pDrvCtrl->endObj);errorExit: ns83902Unload (pDrvCtrl); return NULL; }/********************************************************************************* ns83902InitParse - parse the initialization string** Parse the input string and fill in values in the driver control structure.** RETURNS: OK, or ERROR if any arguments are invalid.*/LOCAL STATUS ns83902InitParse ( NS83902_END_DEVICE * pDrvCtrl, char * initString ) { char * tok; char * pHolder = NULL; long address; UINT8 options; /* Parse the initString */ /* Unit number. */ tok = strtok_r (initString, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); /* NIC address. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; address = strtoul (tok, NULL, 16); pDrvCtrl->pNic = (char*) address; /* Interrupt vector. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); /* Interrupt level. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ilevel = atoi (tok); /* Remote DMA I/O address. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ioPort = (char *) strtoul (tok, NULL, 16); /* Get ring buffer size in pages */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->rxStopPage = strtoul (tok, NULL, 16) / NS83902_PAGE_SIZE; /* Get target options */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; options = strtoul (tok, NULL, 16); pDrvCtrl->wide = options & NS83902_WIDE_MASK; pDrvCtrl->regInterval = 1 << ((options & NS83902_INTERVAL_MASK) >> 1); DRV_LOG (NS83902_DEBUG_LOAD, "Processed all arugments\n", 1, 2, 3, 4, 5, 6); DRV_LOG (NS83902_DEBUG_LOAD, "Address %p Lvl %u Vec %d Port %p Ring %p \n", (int)pDrvCtrl->pNic, pDrvCtrl->ilevel, pDrvCtrl->ivec, (int)pDrvCtrl->ioPort, pDrvCtrl->rxStopPage, 6); DRV_LOG (NS83902_DEBUG_LOAD, "Transfer width: %s \n", (int)(pDrvCtrl->wide ? "word":"byte"), 2, 3, 4, 5, 6); DRV_LOG (NS83902_DEBUG_LOAD, "Register interval: %d \n", pDrvCtrl->regInterval, 2, 3, 4, 5, 6); return OK; }/********************************************************************************* ns83902InitMem - initialize memory for NIC chip** Using data in the control structure, setup and initialize the memory* areas needed. If the memory address is not already specified, then allocate* cache safe memory.** RETURNS: OK or ERROR.*/LOCAL STATUS ns83902InitMem ( NS83902_END_DEVICE * pDrvCtrl /* device to be initialized */ ) { /* allocate netpool */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); /* Set number of M-Blks and CL-Blks*/ ns83902MclBlkConfig.mBlkNum = pDrvCtrl->rringSize; ns83902MclBlkConfig.clBlkNum= pDrvCtrl->rringSize / 2; ns83902ClDescTbl[0].clNum = ns83902MclBlkConfig.clBlkNum; /* Calculate the total memory for all the M-Blks and CL-Blks. */ ns83902MclBlkConfig.memSize = ns83902MclBlkConfig.mBlkNum * (MSIZE + sizeof (long)) + ns83902MclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)); /* allocate memory for M-Blks and CL-Blks */ ns83902MclBlkConfig.memArea = (char *) memalign (sizeof(long), ns83902MclBlkConfig.memSize); if (ns83902MclBlkConfig.memArea == NULL) return (ERROR); /* Calculate the memory size of all the clusters. */ ns83902ClDescTbl[0].clSize = NS83902_RX_BUF_SZ; ns83902ClDescTbl[0].memSize = sizeof(long) + ns83902ClDescTbl[0].clNum * (ns83902ClDescTbl[0].clSize + 8); /* Allocate memory for clusters */ ns83902ClDescTbl[0].memArea = (char *) memalign (sizeof(long), ns83902ClDescTbl[0].memSize); if (ns83902ClDescTbl[0].memArea == NULL) { DRV_LOG (NS83902_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Save clusters start address for later use */ pDrvCtrl->pCluster = (NS83902_CLUSTER) ns83902ClDescTbl[0].memArea; /* Initialize the net buffer pool with buffers */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &ns83902MclBlkConfig, &ns83902ClDescTbl[0], ns83902ClDescTblNumEnt, NULL) == ERROR) { DRV_LOG (NS83902_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, NS83902_RX_BUF_SZ, FALSE); if (pDrvCtrl->pClPoolId == NULL) return (ERROR);#ifdef NS83902_DEBUG ns83902NetPool = *pDrvCtrl->endObj.pNetPool; ns83902ClPoolId = pDrvCtrl->pClPoolId;#endif return (OK); }/********************************************************************************* ns83902Start - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS ns83902Start ( NS83902_END_DEVICE *pDrvCtrl ) { STATUS result; /* Clear statuses */ pDrvCtrl->rxHandling = FALSE; pDrvCtrl->txBlocked = FALSE; pDrvCtrl->rxOvw = FALSE; pDrvCtrl->txResend = FALSE; /* reset the device */ NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0); /* connect interrupt handler */ SYS_INT_CONNECT (pDrvCtrl, ns83902Int, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; DRV_LOG (NS83902_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); /* device config */ ns83902Config (pDrvCtrl); /* mark the interface -- up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); SYS_INT_ENABLE (pDrvCtrl); DRV_LOG (NS83902_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ns83902Config - configure the NIC chip and program address** This routine follows the algorythm in the ST-NIC manual for enabling* a NIC device on an active network. Essentially, this routine initializes* the NIC device.** RETURNS: N/A.*/LOCAL void ns83902Config ( NS83902_END_DEVICE * pDrvCtrl /* device to be configured */ ) { UCHAR* pEnetAddr = pDrvCtrl->enetAddr; UCHAR dcr; /* Page 0 */ NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0); /* Enable broadcast, Endian, Word Size */#if (_BYTE_ORDER == _BIG_ENDIAN) dcr = DCR_NOTLS | DCR_FIFO8 | DCR_BOS;#else dcr = DCR_NOTLS | DCR_FIFO8;#endif if (pDrvCtrl->wide == TRUE) dcr |= DCR_WTS; NS83902_REG_SET (pDrvCtrl, NS83902_DCR, dcr, CR_RPAGE0); /* Clear the remote byte count reg. */ NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0); /* Set to monitor and loopback mode */ NS83902_REG_SET (pDrvCtrl, NS83902_RCR, RCR_MON, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0); /* Accept Broadcast */ NS83902_REG_SET (pDrvCtrl, NS83902_RCR, (RCR_AB | RCR_AM), CR_RPAGE0); /* Set the transmit page and receive page */ NS83902_REG_SET (pDrvCtrl, NS83902_PSTART, pDrvCtrl->rxStartPage, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_PSTOP, pDrvCtrl->rxStopPage, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, pDrvCtrl->rxStopPage - 1, CR_RPAGE0); /* Clear the pending interrupts and mask. */ NS83902_REG_SET (pDrvCtrl, NS83902_ISR, 0xff, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0); /* set MAC Address */ NS83902_REG_SET (pDrvCtrl, NS83902_PAR0, pEnetAddr [0], CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_PAR1, pEnetAddr [1], CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_PAR2, pEnetAddr [2], CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_PAR3, pEnetAddr [3], CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_PAR4, pEnetAddr [4], CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_PAR5, pEnetAddr [5], CR_RPAGE1); /* Initialize the multicast list to accept all. */ NS83902_REG_SET (pDrvCtrl, NS83902_MAR0, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR1, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR2, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR3, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR4, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR5, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR6, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_MAR7, 0x00, CR_RPAGE1); NS83902_REG_SET (pDrvCtrl, NS83902_CURR, pDrvCtrl->rxStartPage, CR_RPAGE1); /* Page 0 */ NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0); /* set the interrupt mask */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -