111122-1257
NULL, /* pNext */
VXB_DEVID_DEVICE, /* devID */ VXB_BUSID_PLB, /* busID = PCI */ VXBUS_VERSION_3, /* vxbVersion */ ETH_NAME, /* drvName */ ðFuncs, /* pDrvBusFuncs */ //这个是最重要的 ethMethods, /* pMethods */ ethProbe, /* devProbe */
//ethParamDefaults /* pParamDefaults */ }, };
其中,前4个不用动,系统分配 #define ETH_NAME \
而ethMethods,涉及的是方法,我把其中只保留了一项,其实也可以全部屏了。 LOCAL struct vxbDeviceMethod ethMethods[] = {
//DEVMETHOD(miiRead, ethPhyRead), //DEVMETHOD(miiWrite, ethPhyWrite), //DEVMETHOD(miiMediaUpdate,ethLinkUpdate), DEVMETHOD(muxDevConnect, ethMuxConnect), //DEVMETHOD(vxbDrvUnlink, ethInstUnlink), { 0, 0 } };
LOCAL struct drvBusFuncs ethFuncs = {
ethInstInit, /* devInstanceInit */ ethInstInit2, /* devInstanceInit2 */ ethInstConnect /* devConnect */ };
这个结构体就是上面提到的调用关系
2.4. ethInstInit,ethInstInit2,
这2个函数,可以参照其他的驱动,在ethInstInit中 LOCAL void ethInstInit(VXB_DEVICE_ID pDev) {
struct hcfDevice *pHcf;
/* Always use the unit number allocated to us in the hwconf file. */ pHcf = (struct hcfDevice *)pDev->pBusSpecificDevInfo; if(OK != vxbInstUnitSet (pDev, pHcf->devUnit)) DRV_LOG (DRV_DEBUG_LOAD,\ else DRV_LOG (DRV_DEBUG_LOAD,\ return;
}可以完全不动,
26
111122-1257
而ethInstInit2
LOCAL void ethInstInit2(VXB_DEVICE_ID pDev) {
END_DEVICE * pDrvCtrl; #if 1
pDrvCtrl = malloc (sizeof(END_DEVICE));
bzero ((char *)pDrvCtrl, sizeof(END_DEVICE)); pDev->pDrvCtrl = pDrvCtrl; pDrvCtrl->ethDev = pDev; #endif return;
}里面可以任何事情都不做,不过你也可以把这里面的初始化放在后面endload里,有人说6.6的ethInstInit2+endload=5.5的endload。
2.5. ethInstConnect
LOCAL void ethInstConnect( VXB_DEVICE_ID pDev){ DRV_LOG (DRV_DEBUG_LOAD,\ taskDelay(3); ethMuxConnect(pDev,NULL); return; }
可以看出,只是调用了ethMuxConnect。
2.6. ethMuxConnect
LOCAL void ethMuxConnect(VXB_DEVICE_ID pDev,void * unused) {
END_DEVICE *pDrvCtrl; VXB_DEVICE_ID miiDev; char *miiIfName; int miiIfUnit;
DRV_LOG (DRV_DEBUG_LOAD,\ /* Save the cookie. */
pDrvCtrl->ethMuxDevCookie = muxDevLoad (pDev->unitNumber, DM9000EndLoad, \
if (pDrvCtrl->ethMuxDevCookie != NULL)
muxDevStart (pDrvCtrl->ethMuxDevCookie);
if (_func_m2PollStatsIfPoll != NULL)
endPollStatsInit (pDrvCtrl->ethMuxDevCookie,_func_m2PollStatsIfPoll);
27
111122-1257
DRV_LOG (DRV_DEBUG_LOAD,\ taskDelay(3); return; }
调用了2个经典的函数
之后就可以进入DM9000EndLoad了在这里面我们看到了,传输的参数是VXB_DEVICE_ID pDev,这是vxbus新的类型,我的做法是,在设备资源结构体中添加了这几个成员:
2.7.vxbus的 end_device
typedef struct end_device {
END_OBJ end; /* The class we inherit from. */ //add the vxbus's code VXB_DEVICE_ID ethDev; UINT32 ethMask; //这个也可以不用要,但另外2个必须要得 void *ethMuxDevCookie; //end
END_ERR err; UINT IOBase;
int unit; /* unit number */ int ivec; /* interrupt vector */ int ilevel; /* interrupt level */ long flags; /* Our local flags. */ UCHAR enetAddr[6]; /* ethernet address */
CACHE_FUNCS cacheFuncs; /* cache function pointers */ CL_POOL_ID pClPoolId; /* cluster pool */
BOOL rxHandling; /* rcv task is scheduled */
UCHAR io_mode; /* 0:word, 2:byte */ char tx_pkt_cnt;
char device_wait_reset; UWORD queue_pkt_len;
UCHAR reg0; /* registers saved */ UCHAR nic_type; /* NIC type */
UCHAR op_mode; /* PHY operation mode */
UCHAR mcastFilter[8]; /* multicast filter */ UCHAR dummyBytes[3]; /* dummyBytes, for 32-bit align */ UCHAR txBuf[ETHERMTU + EH_SIZE + 6 + 64 ]; unsigned int io_addr; /**/ unsigned int io_data; } END_DEVICE;
28
111122-1257
2.8. DM9000EndLoad
因为在init2中添加了初始化分配代码,所以,这个函数中可以省去这些 END_OBJ* DM9000EndLoad( char* initString, void *pArg ){ END_DEVICE *pDrvCtrl;
VXB_DEVICE_ID pDev; //主要增加了这1句, UINT32 dataVal; char tmp; int i;
VXB_INST_PARAM_VALUE val; STATUS r; int cnt; pDev = pArg; pDrvCtrl = pDev->pDrvCtrl; //还有这一句,就把VXB_DEVICE_ID和END_DEVICE绑在一起了 …….. }
上面个的这个参数pArg指向的是VXB_DEVICE_ID,而end里是END_DEVICE。 在后续的程序中都可以在开头加上和上面思想类似的两个操作,因为传输的参数类型变了由END_DEVICE到END_OB,如:
static STATUS dm9000Start(END_DEVICE * pEnd ) /* device ID */?end static STATUS dm9000Start( END_OBJ * pEnd ) /* device ID */-?vxbus 而对于这种,可以这样 END_DEVICE * pDrvCtrl; VXB_DEVICE_ID pDev;
pDrvCtrl = (END_DEVICE *)pEnd; pDev = pDrvCtrl->ethDev;
下面的操作就和end的一样了。
2.9.vxbus操作时使用vxbus独有特性探索之hwconf.c
从上面的移植中可以看到,虽然我们用了vxbus,但是我们只是用到了外壳,并没有用到里面一些实际的东西,经过分析,找到了一个可以用到的地方,就是注册中断的时候 原来的注册方法:
intConnect(INUM_TO_IVEC(pDrvCtrl->ivec), (VOIDFUNCPTR)dm9000Int, (int) (pDrvCtrl)); if (result == ERROR){ printf(\ return ERROR; }
printf(\result = intEnable((int)pDrvCtrl->ivec); if (result == ERROR){ printf(\
29
111122-1257
return ERROR; }
新的注册方法:
vxbIntConnect (pDev, 0, dm9000Int, pDrvCtrl); vxbIntEnable (pDev, 0, dm9000Int, pDrvCtrl);
但是要在一个文件中添加资源信息?hwconf.c,找到hcfDeviceList[]数组,在其中添加 #ifdef INCLUDE_DM9000A_VXB_END /* added, 20110820_0926 */ { \#endif
在文件的上面添加
#define INCLUDE_DM9000A_VXB_END #ifdef INCLUDE_DM9000A_VXB_END
#define DM9000A_MAC_BASE 0xd3000000 //资源的基地址 #define INUM_DM9000END0 17 //本次使用的中断号
const struct hcfResource ethDm9000aEnd0Resources[] = { { \ { \ { \ { \ //无需改动 { \ HCF_RES_STRING, { (void *)\ { \ HCF_RES_INT, { (void *)0 } }};
#define ethDm9000aEnd0Num NELEMENTS(ethDm9000aEnd0Resources) #endif
上面的{ \就照应这0?17,你能明白的。
三.移植过程中配到的困难
1.程序的流程,end和vxbus有很大不同,刚开始直接用vxbus,但是不了解,可以的去研究vxbus,导致浪费了时间,最后拐头使用end,成功后,移植到vxbus上。
2.主要是那个swap地方没有弄好,开始没有注意打印信息,后来发现接收和发送的数据全是空的,后来添加上打印信息,找到了错误的地方,但是已经浪费了很多时间 3.对mac和phy的不理解,并且对dm9000的数据手册不熟悉,没有过多的去参看数据手册。 4.对应在这次开发中涉及的重点和疑惑,最终我感觉上面列出的那几个接口函数都相当重要。如果让列出最终要的部分,是最底层的那几个:ior,iow,phy_read,phy_wirte这四个函数,特别是phy的操作,网上也少有涉及的,最后只能手写对它的操作。
30