📄 dm9kend.c
字号:
}/********************************************************************************* dm9kMemInit - initialize memory.** 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.*/STATUS dm9kMemInit ( DM9K_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { int i; char * bufPtr; pDrvCtrl->rringSize = DM9K_N_RX_BUF; pDrvCtrl->tringSize = DM9K_N_TX_BUF; /* allocate pool structure for mblks, clBlk, and clusters */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); /* number of clusters is passed in by the endLoadString */ pDrvCtrl->clDesc.clNum = pDrvCtrl->rringSize * 2; pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum; pDrvCtrl->mClCfg.mBlkNum = pDrvCtrl->mClCfg.clBlkNum * 2; /* total memory size for mBlks and clBlks */ pDrvCtrl->mClCfg.memSize = (pDrvCtrl->mClCfg.mBlkNum * (MSIZE + sizeof (long))) + (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long))); /* total memory for mBlks and clBlks */ if ((pDrvCtrl->mClCfg.memArea = (char *) memalign (sizeof(long), pDrvCtrl->mClCfg.memSize)) == NULL) return (ERROR); /* total memory size for all clusters */ pDrvCtrl->clDesc.clSize = DM9K_BUFSIZ; pDrvCtrl->clDesc.memSize = (pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + 8)) + sizeof(int); /* Allocate cluster memory */ pDrvCtrl->clDesc.memArea = malloc (pDrvCtrl->clDesc.memSize); if (pDrvCtrl->clDesc.memArea == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* initialize the device net pool */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &(pDrvCtrl->mClCfg), &(pDrvCtrl->clDesc), 1, NULL) == ERROR) { DRV_LOG (DRV_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. */ if ( ( pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, DM9K_BUFSIZ, FALSE)) == NULL ) return ERROR; tableList = cacheDmaMalloc (4 + DM9K_N_RX_BUF*sizeof (dm9kS_TdDescriptor)); tableList= ROUND_UP(tableList,4); bufPtr = malloc(DM9K_BUFSIZ *(pDrvCtrl->rringSize) + 4); pDrvCtrl->pRxMemBase = bufPtr; /* Base address of receive buffers */ /* Initialise tdList descriptor. This descriptor must be WORD aligned*/ for (i = 0; i < pDrvCtrl->rringSize; ++i) { tableList[i].addr = ROUND_UP(bufPtr, 4); tableList[i].size = 0; bufPtr+= DM9K_BUFSIZ; } /* Set the WRAP bit at the end of the list descriptor*/ tableList[DM9K_N_RX_BUF-1].addr |= 0x02; bufPtr = malloc(DM9K_BUFSIZ * (pDrvCtrl->tringSize) + 4); pDrvCtrl->pTxMemBase = bufPtr; for (i = 0; i < pDrvCtrl->tringSize; ++i) { pDrvCtrl->pTxMem[i] = ROUND_UP(bufPtr, 4); bufPtr+= DM9K_BUFSIZ; } return (OK); }void PhyReset( DM9K_DRV_CTRL * pDrvCtrl){ return;}unsigned int PhyStatus( DM9K_DRV_CTRL * pDrvCtrl){ unsigned int Status; unsigned int r = 0, count=0; unsigned int i; return OK;}/******************************************************************** * Name: * dm9kGetLinkSpeed * Description: * Link parallel detection status of MAC is checked and set in the * MAC configuration registers * Arguments: * pEmac - pointer to MAC * Return value: * TRUE - if link status set succesfully * FALSE - if link status not set */// unsigned short aa[26];STATUS dm9kGetLinkSpeed ( DM9K_DRV_CTRL * pDrvCtrl /* device to be initialized */){ return TRUE; }/********************************************************************************* dm9kStart - 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 dm9kStart ( DM9K_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { STATUS result; int i; UINT32 * pReg=NULL; INT32 status; pDrvCtrl->txCleaning = FALSE; pDrvCtrl->txBlocked = FALSE; pDrvCtrl->tmdIndex = 0; /*set at91rm9200 AIC_SMR[27] mode */ pReg = (UINT32*)0xfffff06c; *pReg = 0x03; /*low-level sensitive */ regWriteByte(DM9K_MDWAL,0x0); regWriteByte(DM9K_MDWAH,0x0); SYS_INT_CONNECT (pDrvCtrl, dm9kInt, (int)pDrvCtrl, &result); DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); if (result == ERROR) return ERROR; /* mark the interface as up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); if(intEnable(DM9K_IRQ)==0); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); /* Activate DM9000A/DM9010 */ regWriteByte(DM9KS_RXCR,0x2f); /* RX enable */ regWriteByte(DM9KS_IMR, DM9KS_REGFF); // Enable TX/RX interrupt mask return (OK); }/********************************************************************************* dm9kInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/ void dm9kInt ( DM9K_DRV_CTRL * pDrvCtrl ) { UINT8 reg_save; int int_status,i; reg_save = regReadByte(DM9KS_ADDR_PORT); /* Disable all interrupt */ regWriteByte(DM9KS_IMR, DM9KS_DISINTR); /* Got DM9000A/DM9010 interrupt status */ int_status = regReadByte(DM9KS_ISR); /* Got ISR */ regWriteByte(DM9KS_ISR, int_status); /* Clear ISR status */ /* Link status change */ if (int_status & DM9KS_LINK_INTR) { dm9kGetLinkSpeed(pDrvCtrl);// logMsg("link status change!\n",1,2,3,4,5,6); } /* Received the coming packet */ if (int_status & DM9KS_RX_INTR) { netJobAdd ((FUNCPTR)dm9kRecv ,(int)pDrvCtrl, 0, 0, 0, 0); } /* Trnasmit Interrupt check */ if (int_status & DM9KS_TX_INTR) /* maybe should be modified */ { DRV_LOG(DRV_DEBUG_TX,"packet transmitted!\n",1,2,3,4,5,6); pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) & (pDrvCtrl->tringSize - 1); } if (pDrvCtrl->txBlocked == TRUE) { DRV_LOG(DRV_DEBUG_TX,"packet blocked!\n",1,2,3,4,5,6); pDrvCtrl->txBlocked = FALSE; netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0); } /* Re-enable interrupt mask */ regWriteByte(DM9KS_IMR, DM9KS_REGFF); /* Restore previous register address */ writeWord(reg_save); return; }/********************************************************************************* dm9kRecv - process the next incoming packet** RETURNS: OK/ERROR*/LOCAL STATUS dm9kRecv ( DM9K_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { int len; M_BLK_ID pMblk; char * pCluster; char * pBuf; CL_BLK_ID pClBlk; int lineCount,residual,rmdIndex; int oldlevel; /* current interrupt level mask */ int i,j; UINT16 MDRAH,MDRAL,tmplen; UINT8 rxbyte; rx_t rx; UINT16 * ptr = (UINT16*)℞ UINT8* rdptr; BOOL GoodPacket;do{ /*store the value of Memory Data Read address register*/ MDRAH=regReadByte(DM9KS_MDRAH); MDRAL=regReadByte(DM9KS_MDRAL); /* Dummy read */ regReadByte(DM9KS_MRCMDX); /* * Read the rx indication. Note that the implicit u8 cast * actually get the first byte of RX SRAM */ rxbyte = IN_WORD(DM9KS_DATA_PORT); /* Got most updated data */ /* packet ready to receive check */ if(rxbyte != 0x01) break; /* A packet ready now & Get status/length */ GoodPacket = TRUE; OUT_WORD(DM9KS_ADDR_PORT, DM9KS_MRCMD); /* Select MRCMD to enable address increment (by HL) */ /* Read packet status & length */ *ptr = IN_WORD(DM9KS_DATA_PORT); *(ptr+1) = IN_WORD(DM9KS_DATA_PORT); /* already bswap by hw */ /* Packet status check */ if (rx.desc.status & 0xbf) { GoodPacket = FALSE; if (rx.desc.status & 0x01) { DRV_LOG (DRV_DEBUG_LOAD, "<RX FIFO error>\n", 1, 2, 3, 4, 5, 6); } if (rx.desc.status & 0x02) { DRV_LOG (DRV_DEBUG_LOAD, "<RX CRC error>\n", 1, 2, 3, 4, 5, 6); } if (rx.desc.status & 0x80) { DRV_LOG (DRV_DEBUG_LOAD, "<RX Length error>\n", 1, 2, 3, 4, 5, 6); } if (rx.desc.status & 0x08) DRV_LOG (DRV_DEBUG_LOAD, "<Physical Layer error>\n", 1, 2, 3, 4, 5, 6); } if (!GoodPacket) { // drop this packet!!! tmplen = (rx.desc.length + 1) / 2; DRV_LOG (DRV_DEBUG_LOAD, "drop this packet!\n", 1, 2, 3, 4, 5, 6); for (i = 0; i < tmplen; i++) { IN_WORD(DM9KS_DATA_PORT); } continue; } len = rx.desc.length; pBuf = (char *)pDrvCtrl->pRxMemBase; if (pBuf == NULL ) { DRV_LOG (DRV_DEBUG_LOAD, "KERN_WARNING: Memory squeeze.\n", 1, 2, 3, 4, 5, 6); /*re-load the value into Memory data read address register*/ regWriteByte(DM9KS_MDRAH,MDRAH); regWriteByte(DM9KS_MDRAL,MDRAL); return; } else { /* Read received packet from RX SARM */ tmplen = (rx.desc.length + 1) / 2; for (i = 0; i < tmplen; i++) { ((UINT16 *)pBuf)[i] = IN_WORD(DM9KS_DATA_PORT); } } /* If error flag OR if packet is not completely in one buffer */ if (!len) { DRV_LOG (DRV_DEBUG_RX, "RMD error!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; /* skip to clean up */ } /* If we cannot get a buffer to loan then bail out. */ pCluster = netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId); if (pCluster == NULL) { DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError); goto cleanRXD; } if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->endObj.pNetPool, pCluster); DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError); 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, pCluster); DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); CACHE_DMA_INVALIDATE(pCluster + pDrvCtrl->offset, len); bcopy (pBuf, pCluster + pDrvCtrl->offset, len); /* offset must be 0x02 to align */ CACHE_DMA_FLUSH(pCluster + pDrvCtrl->offset, len); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mData += pDrvCtrl->offset; pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* Advance our management index */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk); return (OK); }while((rxbyte & 0x01) == DM9KS_PKT_RDY);cleanRXD: DRV_LOG (DRV_DEBUG_RX, "cleanRXD....dm9kRecv clean index\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* dm9kSend - 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. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine. ** RETURNS: OK or ERROR.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -