111122-1257
return (y); }
2-7.dm9000int
dm9000int是在dm9000Start函数中被注册,里面主要处理recive中断和sent中断(这个主要是对计数器进行--,没别的涉及数据的操作)。
static void dm9000Int( END_DEVICE *pDrvCtrl ) /* interrupting device */ {
UCHAR stat, reg_save, isr_status, nsr_status; /* tx_status, */ UCHAR TX_comple_status;
/* Save previous register address */ DM9000_IN_ADDR( reg_save );
iow(pDrvCtrl, 0xff, DM9000_REGFF_OFF ); /*temp*/ stat = dm9000StatusRead (pDrvCtrl);
//INT_RECIVE_DEBUG(\ /* Clear ISR status */
isr_status=ior(pDrvCtrl,0xfe);
//INT_RECIVE_DEBUG(\ iow(pDrvCtrl, 0xfe, isr_status );
DRV_LOG (DRV_DEBUG_INT, \ /*
* enable interrupts, clear receive and/or transmit interrupts, and clear * any errors that may be set. */
/* Have netTask handle any input packets */
if( (isr_status & 1 )&&(stat & DM9000_RXON) ) {
DRV_LOG (DRV_DEBUG_INT, \ if ( pDrvCtrl->rxHandling != TRUE ){ pDrvCtrl->rxHandling = TRUE; /*dm9000HandleRcvInt(pDrvCtrl);*/ #ifdef DRV_DEBUG g_IntrNum++;
#endif //添加接收中断处理函数
netJobAdd ((FUNCPTR)dm9000HandleRcvInt, (int)pDrvCtrl,0,0,0,0); } }
/* TODO - handle transmit interrupts */ if( isr_status & 2 ) { //发送中断处理
DRV_LOG (DRV_DEBUG_INT, \
16
111122-1257
4, 5, 6);
TX_comple_status=ior(pDrvCtrl,0x1); if (TX_comple_status & 0xc){ /* One packet sent complete */ pDrvCtrl->tx_pkt_cnt--; //处理一个发送中断 INT_DEBUG(\ /* Queue packet check & send */
if (pDrvCtrl->tx_pkt_cnt > 0){ //处理第二个中断 iow(pDrvCtrl, 0xfc, pDrvCtrl->queue_pkt_len & 0xff ); iow(pDrvCtrl, 0xfd, (pDrvCtrl->queue_pkt_len >> 8) & 0xff ); iow(pDrvCtrl, 0x2, 0x01 ); } } } intRet:
/* Re-enable interrupt mask */
iow(pDrvCtrl, 0xff, DM9000_REGFF ); /* Restore previous register address */ DM9000_OUT_ADDR( reg_save ); }
注意事项,其中对发送中断时的2步处理是考虑到中断可能有时候没有来得及相应(情况很多),这时已经发送了2个包了,而此时就要对2次包进行处理了,也就是说发送了2个包,但是只响应了一次中断。
接收中断处理函数netJobAdd ((FUNCPTR)dm9000HandleRcvInt, (int)pDrvCtrl,0,0,0,0);分析: static void dm9000HandleRcvInt( END_DEVICE *pDrvCtrl ) /* interrupting device */ {
char* pData; int i;
unsigned short tmp3;
pDrvCtrl->rxHandling = TRUE;
DRV_LOG (DRV_DEBUG_INT, \ while (OK==dm9000PacketGet (pDrvCtrl)) { if(dm9000Recv (pDrvCtrl, (char*)NULL ) == ERROR) break; }
pDrvCtrl->rxHandling = FALSE; }
pDrvCtrl->rxHandling就是用来标记接收中断是否处理完成的,就是一个接收中断标志函数中涉及dm9000PacketGet()和dm9000Recv(),先看dm9000PacketGet() STATUS dm9000PacketGet( END_DEVICE *pDrvCtrl ) {
UCHAR rxbyte;
rxbyte=ior(pDrvCtrl,0xf0); rxbyte=ior(pDrvCtrl,0xf0);
/* packet ready to receive check */ if( rxbyte == DM9000_PKT_RDY )
17
111122-1257
{
DRV_LOG (DRV_DEBUG_LOAD, \ return OK; }
DRV_LOG (DRV_DEBUG_LOAD, \ return ERROR; }
此函数主要检测dm9000接收寄存器是否准备好 下面分析dm9000PacketGet()函数
static STATUS dm9000Recv( END_DEVICE *pDrvCtrl, /* device structure */ char* pData ) /* packet to process */ {
char* pClusterData; M_BLK_ID pMblk; char* pNewCluster; CL_BLK_ID pClBlk; PKT skb; int i;
DRV_LOG (DRV_DEBUG_LOAD, \#ifdef DRV_DEBUG g_RecvNumError++; #endif
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pNewCluster == NULL) {
DRV_LOG (DRV_DEBUG_RX, \ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; }
/* Grab a cluster block to marry to the cluster we received. */
if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) {
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, \ END_ERR_ADD (&pDrvCtrl->end, 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->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) {
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, \ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
18
111122-1257
goto cleanRXD; }
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* align IP header at 32-bit boundary, this is reqired by VxWorks ** TCP/IP stack*/
pClusterData = (char*)((((unsigned long)pNewCluster + 1) & (~1)) | 2 ); /* move packet from Ethernet on-board SRAM to the mbuf pre-allocated ** in system memory */
skb.pData = pClusterData;
skb.len = 0;
//下面的这个函数是重点
if( dmfe_packet_receive( (PKT*)(&skb), pDrvCtrl ) ) {
mBlkFree (pDrvCtrl->end.pNetPool, pMblk); netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, \ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; }
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pNewCluster, skb.len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mData = pClusterData; pMblk->mBlkHdr.mLen = skb.len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = skb.len;
#if 0 //用来验证数据是否接收出来,用来和抓包工具的数据进行比照 for(i=0;i<(skb.len +1 )/2;i++){ INT_RECIVE_DEBUG(\ if(((i+1) % 20)==0) INT_RECIVE_DEBUG(\}
INT_RECIVE_DEBUG(\#endif
/* make the packet data coherent */
END_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, skb.len); /* Call the upper layer's receive routine. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
DRV_LOG (DRV_DEBUG_INT, \#ifdef DRV_DEBUG g_RecvNum++;
19
111122-1257
g_RecvNumError--; #endif
return (OK); cleanRXD:
return (ERROR); }
对于上面这个函数中的一些步骤,无需多管,这个函数是vxworks封装好的一个标准接收处理函数,思路是依次创建Cluster,clblk,mblk,然后把这3者给联系起来,而把接收得数据使用这个函数dmfe_packet_receive(),把dm9000缓冲池中的数据取出来,放到Cluster里面,然后把mblk的指针返回给上层mux层,接收驱动就算完成了。下面分析dmfe_packet_receive()函数:
static int dmfe_packet_receive( PKT *skb, END_DEVICE *dev ) {
UCHAR tmp1,tmp2; UWORD tmp3; UCHAR rxbyte; UCHAR *rdptr;
UWORD i, RxStatus, RxLen, GoodPacket, tmplen; int oldv;
UWORD RxStatus_tmp,data_tmp;
DRV_LOG (DRV_DEBUG_NO, \ rxbyte=ior(dev,0xf0); rxbyte=ior(dev,0xf0);
/* Status check: this byte must be 0 or 1 */
if( rxbyte > DM9000_PKT_RDY )//仍然是检测是否准备好,这个地方可以去掉 {
iow(dev, 0x05, DM9000_REG05_OFF); /* Stop Device */ iow(dev, 0xff, DM9000_REGFF_OFF); /* Stop Device */ DRV_LOG (DRV_DEBUG_RX,\ dm9000Reset( dev ); dm9000Config( dev ); return 2; }
/* packet ready to receive check */ if( rxbyte == DM9000_PKT_RDY ) {
/* A packet ready now & Get status/length */ GoodPacket = 1;
if( dev->io_mode == 1 ) //字节处理模式,和下面单字节接收对应 { tmp1=ior(dev,0xf2); tmp2=ior(dev,0xf2);
RxStatus = tmp1 + (tmp2 << 8); //读取状态 tmp1=ior(dev,0xf2); tmp2=ior(dev,0xf2);
20