111122-1257
RxLen = tmp1 + (tmp2<<8); //读取数据长度 }
Else //world模式,是这个程序的默认模式,为2字节,程序进入这里 { outb(dev->io_addr, 0xf2); RxStatus = SWAP16(inb(dev->io_data)); //这个16为2交换很重要 RxLen = inb(dev->io_data); }
if( RxLen < 0x40) //下面3个if都是错误检测 {
DRV_LOG (DRV_DEBUG_RX, \ GoodPacket = 0; }
if( RxLen > DM9000_PKT_MAX ) {
DRV_LOG (DRV_DEBUG_RX, \ dm9000Reset( dev ); dm9000Config( dev ); return 2; }
if( RxStatus & 0xbf) {
GoodPacket = 0;
/*if( RxStatus & 0x100 ) fifo error */ /*if( RxStatus & 0x200 ) crc error */ /*if( RxStatus & 0x8000 ) length error */
DRV_LOG (DRV_DEBUG_RX, \ }
/* Move data from DM9000 */ skb->len = 0;
if( GoodPacket && (skb != NULL) ) { /* good packet*/ skb->len = RxLen; rdptr = skb->pData;
/* Read received packet from RX SARM */ if (dev->io_mode == 1) { /* Byte mode */
for( i=0; i rdptr[i]=dm9k_inb(dev->io_data); } else {/* Word mode */ //程序会进入这个地方 tmplen = (RxLen + 1) / 2; for( i = 0; i < tmplen; i++ ) { 21 111122-1257 data_tmp=inb(dev->io_data); ((unsigned short *)rdptr)[i] = SWAP16(data_tmp); } } return 0; } else //这就是坏包,处理方式是只是用临时变量来接收,但不提交。 { /* bad packet*/ /* Without buffer or error packet */ if( dev->io_mode == 1 ) { /* Byte mode */ for( i = 0; i < RxLen; i++ ) tmp1=dm9k_inb(dev->io_data); } else { /* Word mode */ tmplen = (RxLen + 1) / 2; for( i = 0; i < tmplen; i++ ) (unsigned short )tmp3 = SWAP16(inb(dev->io_data)); } return 1; } } DRV_LOG (DRV_DEBUG_RX, \ return 1; } 上面这个函数解析很清楚,在调试的时候可以在里面添加打印信息,打印接收包的数据,看是否和抓包工具抓到的相同,由于是在中断中处理的,打印信息时要用log_msg()函数。 2-8. dm9000McastAdd dm9000MCastDel dm9000McastGet dm9000PollSend dm9000PollRcv等解析 这几个函数比较简单,并且在数据传输上一般不过多处理,可以不写(函数内部写空)或者使用原先的,而对于endEtherAddressForm,endEtherPacketDataGet,endEtherPacketAddrGet这3个函数完全不用动,内部调用的是系统函数。不过dm9000PollSend dm9000PollRcv函数需要在进行处理一下,还得和sent,Rcv差不多,我把代码贴在下面 static STATUS dm9000PollSend( END_DEVICE *pDrvCtrl,M_BLK_ID pMblk) { int len; u_short stat; PKT skb; int oldv; 22 111122-1257 DRV_LOG (DRV_DEBUG_POLL_TX, \ /* TODO - test to see if tx is busy */ stat = dm9000StatusRead (pDrvCtrl); /* dummy code */ if ((stat & (DM9000_TINT|DM9000_TFULL)) == 0) return ((STATUS) EAGAIN); /* TODO - transmit packet */ len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL); len = max (len, ETHERSMALL); skb.len = len; skb.pData = (char*)pDrvCtrl->txBuf; oldv = intLock(); dmfe_start_xmit( &skb, pDrvCtrl );//可以看到,内部仍然调用了dmfe_start_xmit() intUnlock( oldv ); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); /* Free the data if it was accepted by device */ netMblkClFree (pMblk); DRV_LOG (DRV_DEBUG_POLL_TX, \ return (OK); } //可以看出,poolsend和send没有区别,我有点怀疑我基于原先的包是不是有问题 static STATUS dm9000PollRcv( END_DEVICE *pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk ) /* ptr to buffer */ { u_short stat; char* pPacket; int len; PKT skb; DRV_LOG (DRV_DEBUG_POLL_RX, \ stat = dm9000StatusRead (pDrvCtrl); /* TODO - If no packet is available return immediately */ if( !(stat&DM9000_RXRDY) ) { DRV_LOG (DRV_DEBUG_POLL_RX, \ return (EAGAIN); } pPacket = NULL; /* DUMMY CODE */ len = 64; /* DUMMY CODE */ /* Upper layer must provide a valid buffer. */ if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT))) { DRV_LOG (DRV_DEBUG_POLL_RX, \ return (EAGAIN); 23 111122-1257 } /* TODO - Check packet and device for errors */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* TODO - Process device packet into net buffer */ skb.len = 0; skb.pData = pMblk->m_data; if( dmfe_packet_receive( &skb, pDrvCtrl ) ) //调用了dmfe_packet_receive() { DRV_LOG (DRV_DEBUG_POLL_RX, \ return (EAGAIN); } /* bcopy (pPacket, pMblk->m_data, len); */ pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ /* TODO - Done with packet, clean up and give it to the device. */ DRV_LOG (DRV_DEBUG_POLL_RX, \ DRV_LOG (DRV_DEBUG_POLL_RX, \ return (OK); } 可以看出,poollRcv和普通的Rcv也没太大的区别,只是普通的是要自己申请Cluster和Mblk等,而pooll是上层直接传递下来了。 二.Dm9000-vxwork6.6-vxbus模型移植 1. 前言: Dm9000-vxwork6.6-vxbus模型移植在我的移植方法里面基本上没有太多的设计vxbus的操作,也是我对vxbus不太了解,在这次的移植过程中,基本上只是用了vxbus的外壳,没做其他事情。Vxbus和end的注册方法不一样,end是在configNet.h中添加资源和入口函数,而vxbus是在usrAppinit.c中添加自己的入口函数(我的方法是这样的),而注册方法也不是很一样,依次设计:ethRegister()?vxbDevRegister ((struct vxbDevRegInfo *)ðDevPlbRegistration)? drvBusFuncs ethFuncs?ethInstInit?ethInstInit2?ethInstConnect? ethMuxConnect?muxDevLoad?muxDevStart.最后2个函数应该是大家比较熟悉的,在end模型中也是这样调用的。而设计的资源文件为:hwconf.c,可以使用,也可以不使用,后续将会设计到,下面涉及源码 24 111122-1257 2.涉及代码 2-1.usrAppinit.c的void usrAppInit(void)函数 void usrAppInit(void) { #ifdef USER_APPL_INIT USER_APPL_INIT; /* for backwards compatibility */ #endif flashStart(); ethRegister(); //这就是入口函数 #if 1 taskDelay(5); //下面这几个是网卡初始化,驱动写好后添加的网卡设置 ipAttach(0,\ taskDelay(3); ifconfig(\ taskDelay(3); ifconfig(\ taskDelay(3); ifconfig(\#endif } 2.2. ethRegister void ethRegister(void) { map_op(); //这个函数对应于end中的dm9000ConfigInit(),不多介绍 vxbDevRegister ((struct vxbDevRegInfo *)ðDevPlbRegistration); DRV_LOG (DRV_DEBUG_LOAD,\ taskDelay(3); return; } vxbDevRegister ((struct vxbDevRegInfo *)ðDevPlbRegistration) 会把 ethDevPlbRegistration给注册进去 2.3.ethDevPlbRegistration LOCAL struct vxbPlbRegister ethDevPlbRegistration = { { 25