VxWorks DM9000 驱动移植(3)

2019-07-13 17:45

111122-1257

2-3 dm9000FuncTable

这个结构体如下:

static NET_FUNCS dm9000FuncTable = {

(FUNCPTR) dm9000Start, /* Function to start the device. */ (FUNCPTR) dm9000Stop, /* Function to stop the device. */

(FUNCPTR) dm9000Unload, /* Unloading function for the driver. */ (FUNCPTR) dm9000Ioctl, /* Ioctl function for the driver. */ (FUNCPTR) dm9000Send, /* Send function for the driver. */ (FUNCPTR) dm9000MCastAdd, /* Multicast add function for the */ /* driver. */

(FUNCPTR) dm9000MCastDel, /* Multicast delete function for */ /* the driver. */

(FUNCPTR) dm9000MCastGet, /* Multicast retrieve function for */ /* the driver. */

(FUNCPTR) dm9000PollSend, /* Polling send function */ (FUNCPTR) dm9000PollRcv, /* Polling receive function */

endEtherAddressForm, /* put address info into a NET_BUFFER */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */ endEtherPacketAddrGet /* Get packet addresses. */ };

上面说过,这个结构体主要涉及dm9000Start,dm9000Ioctl,dm9000Send,其他的都好操作,而dm9000Ioctl关键,但是涉及的源码无需改动就可,通用的。

2-4.dm9000Start

源码如下:

static STATUS dm9000Start( END_DEVICE * pDrvCtrl ) /* device ID */ {

STATUS result;

unsigned char REG05; /*sailot test*/ cpuForDM9000Init(); /*sailor*/

DRV_LOG (DRV_DEBUG_LOAD, \ intConnect(INUM_TO_IVEC(pDrvCtrl->ivec),(VOIDFUNCPTR)dm9000Int,(int)(pDrvCtrl)) if (result == ERROR){ printf(\ return ERROR; } printf(\

11

111122-1257

result = intEnable((int)pDrvCtrl->ivec); if (result == ERROR){ printf(\ return ERROR; }

DRV_LOG (DRV_DEBUG_LOAD, \ /* Activate DM9000 */

iow(pDrvCtrl, 0x05, DM9000_REG05 ); /* RX enable */

iow(pDrvCtrl, 0xff, DM9000_REGFF ); /* Enable TX/RX interrupt mask */ DRV_LOG (DRV_DEBUG_LOAD, \ return (OK); }

其中cpuForDM9000Init(); /*sailor*/涉及对cpu中断寄存器的初始化,要根据硬件寄存器来设置

void cpuForDM9000Init(void){ immap = 0xe0000000; /*config the io pin to the interrupt*/ ic_sicrh = ( volatile unsigned int *)(immap + 0x118); *ic_sicrh &= ~0x4000; /*high-to-low gernerate the interrupt*/ ic_secnr = ( volatile unsigned int *)(immap + 0x73c); *ic_secnr |= 0x4000; /*unmask the interrupts*/ ic_semsr = ( volatile unsigned int *)(immap + 0x738); *ic_semsr |= 0x40000000; }

这个代码操作寄存器并把中断硬件层打卡,而在start函数中intEnable((int)pDrvCtrl->ivec)来打开操作系统软件层。

在start函数中把dm9000Int注册到系统中。这就是中断函数

2-5.dm9000Ioctl

这个函数无需修改,直接移植系统原来的就行

这个函数主要就是返回一些信息,包括网卡的mac地址,mblk信息等,无需修改就可移植到上面。

2.6. dm9000Send

static STATUS dm9000Send( END_DEVICE * pDrvCtrl, M_BLK_ID pMblk ) { int oldLevel = 0;

BOOL freeNow = TRUE; PKT skb; int len;

12

111122-1257

int i;

DRV_LOG (DRV_DEBUG_LOAD, \4, 5, 6);

END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); oldLevel = intLock (); /* protect dm9000Int */ /* TODO - initiate device transmit */

len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL); DRV_LOG (DRV_DEBUG_LOAD, \ SEND_DEBUG(\ for (i=0;i

SEND_DEBUG(\

len = max (len, ETHERSMALL);

skb.len = len; //后面数据部分的长度 skb.pData = (char*)pDrvCtrl->txBuf;

if( dmfe_start_xmit( &skb, pDrvCtrl ) ) {

DRV_LOG (DRV_DEBUG_STATUS, \ freeNow = FALSE; intUnlock (oldLevel); netMblkClChainFree (pMblk);

if (!((pDrvCtrl->flags) & DM9000_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->end); return(END_ERR_BLOCK); }

intUnlock (oldLevel);

END_TX_SEM_GIVE (&pDrvCtrl->end);

END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);

netMblkClChainFree (pMblk);

DRV_LOG (DRV_DEBUG_LOAD, \ return (OK); }

函数中len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL);把发送的信息从pMblk中给拷贝到pDrvCtrl->txBuf,而返回拷贝的大小len,后把这些信息付给skb,而skb是封装的临时结构体,如下: typedef struct {

int len;

char * pData;

13

111122-1257

} PKT; /* A dummy DMA data packet */

在调试的时候可以把打印信息放在这里,打印出发送的数据包,即上面代码的 for (i=0;i

如果程序没有错误,这个地方会出来打印信息,并且在用抓包工具可以抓到和打印信息相同的包信息,就说明发送成功了。

后面调用dmfe_start_xmit( &skb, pDrvCtrl ),把数据发送出去,这其中是最关键的代码,如下:

static int dmfe_start_xmit( PKT *skb, END_DEVICE *dev) {

char *data_ptr; int i, oldv;

unsigned char imr=0; int tmplen;

UWORD tmpdata; UCHAR regsave;

DRV_LOG (DRV_DEBUG_TX, \ DRV_LOG (DRV_DEBUG_TX, \ if( (skb->len == 0) || (skb->pData == NULL) ){

DRV_LOG (DRV_DEBUG_STATUS,\ return 2; }

/* Resource flag check *///这个部分是用来确定发送中断是否相应,如果连续2次没响应的话,发送就是错误,直接返回 if( dev->tx_pkt_cnt >= 2){

DRV_LOG (DRV_DEBUG_STATUS,\ regsave= ior( dev,2); return 1; }

/* Move data to DM9000 TX RAM */ data_ptr = (char *)skb->pData;

#if 0 //这个部分为调试信息,就是打印发送包的内容信息 SEND_DEBUG(\ for (i=0;ilen;i++){ SEND_DEBUG(\ if(((i+1) % 20)==0) SEND_DEBUG(\ } SEND_DEBUG(\#endif

outb( dev->io_addr,0xf8 );

14

111122-1257

if( dev->io_mode == 1 ) {

/* Byte mode */

for( i = 0; i < skb->len; i++ )

outb( dev->io_data,(data_ptr[i] & 0xff) ); }

Else //进入2,因为初始化时就设置为了0,为字传送,也就是2,依次接收2个字节 { SEND_DEBUG(\ /* Word mode */

tmplen = (skb->len + 1) / 2; for( i = 0; i < tmplen; i++ ){ outb( dev->io_data, SWAP16(((unsigned short *)data_ptr)[i])); if(((i+1) % 10)==0) SEND_DEBUG(\ } }

SEND_DEBUG(\

/* TX control: First packet immediately send, second packet queue */ if (dev->tx_pkt_cnt == 0) { /* First Packet */ dev->tx_pkt_cnt ++;//在这里应该把发送计数器++,在中断中来--,测试中断响应 /* Set TX length to DM9000 */ iow(dev, 0xfc, skb->len & 0xff );//把发送的数据长度写进dm9000对应的reg,这个地方,我感觉应该是在上面依次发送len长度,这时数据并没有发送出去,只是暂存在内部的缓冲区中,而这个地方是把长度放到寄存器中,然后dm9000来把缓冲区中的数据发送出去。 iow(dev, 0xfd, (skb->len >> 8) & 0xff ); /* Issue TX polling command */ iow(dev, 0x2, 0x01 ); /* Cleared after TX complete */ }

else /* Second packet */ //这是2个包处理的情况(一般不会发生) {

dev->queue_pkt_len = skb->len; dev->tx_pkt_cnt ++; } return 0; }

上面代码outb( dev->io_data, SWAP16(((unsigned short *)data_ptr)[i]));这部分很重要,主要是用来对发送的数据进行16位高低转换,也就是反序,代码如下: static __inline__ unsigned short SWAP16(unsigned short x) { unsigned short y; //SEND_DEBUG(\ y=(((x)&0xff)<<8)|(((x)&0xff00)>>8); //这个算法比较经典 SEND_DEBUG(\

15


VxWorks DM9000 驱动移植(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:指数函数、对数函数图像交点问题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: