📄 dm9000xend.c
字号:
** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS dm9000Start ( DM9000_END_DEVICE *pDrvCtrl ) { /* connect interrupt handler */ *((UINT32*)0x080000d0) = 0; *((UINT32*)0x080000c0) = 0x00000008; /* *((UINT32*)0x080000d0) |= 0x04000000; */ (void) intConnect (INUM_TO_IVEC((UINT32)pDrvCtrl->irq), (VOIDFUNCPTR) dm9000Int, (int)pDrvCtrl); /* mark the interface -- up */ /* reset the device */ dmfe_open(pDrvCtrl); END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); intEnable (pDrvCtrl->irq); return (OK); }/********************************************************************************* ns83902Send - the driver's actual output routine** This routine accepts outgoing packets from the snd queue, and then * gains exclusive access to the DMA (through a mutex semaphore),* then calls ns83902Transmit() to send the packet out onto the interface.** RETURNS: OK, or ERROR if the packet could not be transmitted.*/LOCAL STATUS dm9000Send ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk ) { int status; if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) { return (ERROR); } /* send packet out over interface */ if ((status = dmfe_start_xmit (pMblk, pDrvCtrl)) == OK) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); } else { /* update statistics */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); } return status; }/********************************************************************************* ns83902Ioctl - the driver's I/O control routine** Perform device-specific commands.** RETURNS: 0, or EINVAL if the command 'cmd' is not supported.*/LOCAL int dm9000Ioctl ( DM9000_END_DEVICE* pDrvCtrl, int cmd, caddr_t data ) { int error = 0; long value; int saveFlags; switch ((UINT)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; value--; END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else { END_FLAGS_SET (&pDrvCtrl->endObj, value); } saveFlags = DRV_FLAGS_GET(); if (DRV_FLAGS_GET() != saveFlags && (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_UP)) { END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING); } break; case EIOCGFLAGS: if (data == NULL) error = EINVAL; else *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCMULTIADD: /* move to mux */ error = dm9000MCastAddrAdd (pDrvCtrl, (char *)data); break; case EIOCMULTIDEL: /* move to mux */ error = dm9000MCastAddrDel (pDrvCtrl, (char *)data); break; case EIOCMULTIGET: /* move to mux */ error = dm9000MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data); break; case EIOCPOLLSTART: /* move to mux */ error = dm9000PollStart (pDrvCtrl); break; case EIOCPOLLSTOP: /* move to mux */ error = dm9000PollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; default: error = EINVAL; } return (error); } /********************************************************************************* ns83902Stop - stop the device** This function calls BSP functions to disconnect interrupts and stop* the device from operating in interrupt mode.** RETURNS: OK or ERROR*/LOCAL STATUS dm9000Stop ( DM9000_END_DEVICE* pDrvCtrl ) { STATUS result = OK; dmfe_shutdown(pDrvCtrl); /* Disable LAN interrupts */ intDisable (pDrvCtrl->irq); return (result); }/******************************************************************************** ns83902Unload - 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.*/LOCAL STATUS dm9000Unload ( DM9000_END_DEVICE* pDrvCtrl ) { if (pDrvCtrl != NULL) { END_OBJECT_UNLOAD (&pDrvCtrl->endObj); /* free resources */ } return (OK); }/********************************************************************************* ns83902MCastAddrAdd - add a multicast address*** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS dm9000MCastAddrAdd ( DM9000_END_DEVICE* pDrvCtrl, char * pAddr ) { int retVal; retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr); return ((retVal == OK) ? OK : ERROR); }/********************************************************************************* ns83902MCastAddrDel - remove a multicast address*** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS dm9000MCastAddrDel ( DM9000_END_DEVICE* pDrvCtrl, char * pAddr ) { int retVal; retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);/*filter address if (retVal == ENETRESET) return dm9000AddrFilterSet (pDrvCtrl, pAddr, FALSE);*/ return ((retVal == OK) ? OK : ERROR); }/********************************************************************************* ns83902MCastAddrGet - retreive current multicast address list*** RETURNS: OK on success; otherwise ERROR.*/LOCAL STATUS dm9000MCastAddrGet ( DM9000_END_DEVICE* pDrvCtrl, MULTI_TABLE * pTable ) { return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable)); }/********************************************************************************* ns83902PollStart - starting polling mode** RETURNS: OK, always.*/LOCAL STATUS dm9000PollStart ( DM9000_END_DEVICE* pDrvCtrl ) { int intLevel; intLevel = intLock(); /* disable all interrupts */ iow(pDrvCtrl, DMFE_IMR, IMR_PAR); DRV_FLAGS_SET (DM9000_FLAG_POLL); intUnlock (intLevel); return (OK); }/********************************************************************************* ns83902PollStop - stop polling mode** RETURNS: OK, always.*/LOCAL STATUS dm9000PollStop ( DM9000_END_DEVICE* pDrvCtrl ) { int intLevel; intLevel = intLock(); /* enable interrupts */ iow(pDrvCtrl, DMFE_IMR, IMR_PAR | IMR_PTM | IMR_PRM); DRV_FLAGS_CLR(DM9000_FLAG_POLL); intUnlock (intLevel); return (OK); }/********************************************************************************* ns83902PollSend - send a packet in polled mode** RETURNS: OK on success, EAGAIN on failure*/LOCAL STATUS dm9000PollSend ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk ) { return (dm9000Send (pDrvCtrl, pMblk)); }/********************************************************************************* ns83902PollReceive - get a packet in polled mode** RETURNS: OK on success, EAGAIN on failure.*/LOCAL STATUS dm9000PollReceive ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk ) { STATUS nRetValue = OK; return nRetValue; }/********************************************************************************* ns83902Recv - read a packet off the interface ring buffer** ns83902Recv copies packets from local memory into an mbuf and hands it to* the next higher layer (IP or etherInputHook).** RETURNS: TRUE, or FALSE if the packet reception encountered errors.*/LOCAL void dm9000Recv ( DM9000_END_DEVICE* pDrvCtrl, void* pCluster, int RxLen ) { CL_BLK_ID pClBlk; M_BLK_ID pMblk; /* Process frame received */ if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } /* * OK we've got a spare, let's get an M_BLK_ID and marry it to the * one in the ring. */ if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, (char*)pCluster, RxLen, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mData = (char *)pCluster+2; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = RxLen; /* set the data len */ pMblk->mBlkPktHdr.len = RxLen; /* set the total len */ /* Call the upper layer's receive routine. */ /* printf("iplen = %d, %d, len = %d\n\r", pMblk->mBlkHdr.mData[18], pMblk->mBlkHdr.mData[19],pMblk->mBlkPktHdr.len);*/ END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);cleanRXD: return; }/********************************************************************************* ns83902Restart - restart chip after receive ring buffer overflow** This routine is called from an isr handler that deals with a receive DMA* overflow condition. It gets access to the remote DMA, cleans up NIC* registers and defers work to task context to empty the receive ring buffers.** RETURNS: N/A.*/LOCAL void dm9000Restart ( DM9000_END_DEVICE* pDrvCtrl, UINT8 cr ) { }/********************************************************************************* ns83902Int - The driver's interrupt handler** This function clears the cause of the device interrupt(s) and then acts* on the individual possible causes. The primary goal of this routine is to* minimize the time spent in it. This is accomplished by deferring processing* to the netTask via the netJobAdd() function.** Note that in case the receiver overruns, we promptly mark the interface as* "down" and leave error handling to task-level. This is in case netTask* is in the midst of DMA activity, we must allow it to complete. The receive* handler will give up when it discovers the interface is down, which will* then allow netTask to run our OVW handler. This provides orderly error * recovery.** RETURNS: N/A.*/LOCAL void dm9000Int ( DM9000_END_DEVICE* pDrvCtrl ){/* logMsg("enter intr\n\r",1,2,3,4,5,6); */ *((UINT32*)0x080000d0) = 0; *((UINT32*)0x080000c0) = 0x0; *((UINT32*)0x40e00048) = 0x1;/*清除沿检测状态位*/ dmfe_interrupt(pDrvCtrl); *((UINT32*)0x080000c0) = 0x00000008;}static voiddmfe_reset(DM9000_END_DEVICE *pDrvCtrl){ /* RESET device */ DM9000_outb(DMFE_NCR, pDrvCtrl->ioaddr);/*将控制和状态寄存器地址写入pDrvCtrl*/ taskDelay(1); /* delay 100us */ DM9000_outb(NCR_RST, pDrvCtrl->io_data);/*软件复位和自动清除写入pDrvCtrl*/ taskDelay(1); /* delay 100us */}/* Search DM9000 board, allocate space and register it*/static intdmfe_probe( DM9000_END_DEVICE *pDrvCtrl){ static int ret = OK; unsigned long base; UINT32 id_val; UINT16 i; pDrvCtrl->ioaddr = CONFIG_DM9K_BASE; pDrvCtrl->io_data = CONFIG_DM9K_BASE + 4; pDrvCtrl->irq = IRQ_DM9k; /*modify */ dmfe_reset(pDrvCtrl); base = CONFIG_DM9K_BASE; #if 1 /* try two times, DM9000 sometimes gets the first read wrong */ for (i = 0; i < 2; i++) { DM9000_outb(DMFE_VIDL, base);/*卖主ID低字节地址*/ id_val = DM9000_inb(base + 4); DM9000_outb(DMFE_VIDH, base);/*卖主ID高字节地址*/ id_val |= DM9000_inb(base + 4) << 8; DM9000_outb(DMFE_PIDL, base);/*产品ID的低字节*/ id_val |= DM9000_inb(base + 4) << 16; DM9000_outb(DMFE_PIDH, base);/*产品ID的高字节*/ id_val |= DM9000_inb(base + 4) << 24; if (id_val == DM9000_ID) break; printf("%s: Uhm, wrong id 0x%08x\n", CARDNAME, id_val); ret = ERROR; } if (id_val != DM9000_ID) { printf("%s: wrong id: 0x%08x\n", CARDNAME, id_val); ret = ERROR; } #endif return ret;}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -