就如一个驱动架构,2870的驱动结构也是init,exit,probe,下面就我们关注的probe函数进行说明
2820的probe函数rtusb_probe里面调用了rt2870_probe
在rt2870_probe函数里,
先完成一些互斥锁和同步信号量的分配
然后调用USBDevConfigInit完成了usb端点配置,就是一个输入端点和6个输出端点,控制端点呢?
然后调用RtmpPhyNetDevInit初始化一些和上层交互的接口
然后调用RTMP_DRIVER_MAC_ADDR_GET和RtmpOSNetDevAddrSet设置MAC地址
其他待分析
2012-04-30
rt2870_probe函数里
首先调用RTMPAllocAdapterBlock,由名字来看是分配一些适配器快,进入该函数,
首先是函数RtmpUtilInit,它初始化了一个Util的锁UtilSemLock,然后调用AdapterBlockAllocateMemory分配一个适配器pAd,该适配器是整个程序数据沟通的桥梁,查看它的结构struct _RTMP_ADAPTER,挺多的,我最关注的是USB配置的信息和上层网络交互的信息
{
...
/*****************************************************************************************/
/* USB related parameters */
/*****************************************************************************************/
/* struct usb_config_descriptor *config; */
VOID *config;
UINT BulkInEpAddr; /* bulk-in endpoint address */
UINT BulkOutEpAddr[6]; /* bulk-out endpoint address */
UINT NumberOfPipes;
USHORT BulkOutMaxPacketSize;
USHORT BulkInMaxPacketSize;
/*======Control Flags */
ULONG BulkFlags;
BOOLEAN bUsbTxBulkAggre; /* Flags for bulk out data priority */
/*======Cmd Thread */
/* CmdQ CmdQ; */
/* NDIS_SPIN_LOCK CmdQLock; // CmdQLock spinlock */
/* RTMP_OS_TASK cmdQTask; */
/*======Semaphores (event) */
RTMP_OS_SEM UsbVendorReq_semaphore;
RTMP_OS_SEM UsbVendorReq_semaphore2;
PVOID UsbVendorReqBuf;
/* wait_queue_head_t *wait; */
VOID *wait;
...
}
接着调用RTMPAllocTxRxRingMemory,分配发送发送和接收缓冲,进入该函数
调用NICInitTransmit分配发送urb,调用NICInitRecv分配接收urb
还调用了RTMP_AllocateFragPacketBuffer分配了一个skb,属于FRAGMENT_FRAME FragFrame; /* Frame storage for fragment frame */,做什么的呢?
接下来是函数USBDevConfigInit,就是设备配置初始化,无非是检查一些配置是否合理
然后是RtmpRaDevCtrlInit,这个函数也一些配置初始化
然后是RtmpPhyNetDevInit,这个函数比较关键,它初始化了变量pNetDevHook,它具有RTMP_OS_NETDEV_OP_HOOK结构,该结构定义
typedef struct _RTMP_OS_NETDEV_OP_HOOK_ {
void *open; //初始化为MainVirtualIF_open
void *stop;
void *xmit;
void *ioctl;
void *get_stats;
void *priv;
void *get_wstats;
void *iw_handler;
int priv_flags;
unsigned char devAddr[6];
unsigned char devName[16];
unsigned char needProtcted;
} RTMP_OS_NETDEV_OP_HOOK, *PRTMP_OS_NETDEV_OP_HOOK;
显然它提供了和上层交互的接口,其中open函数初始化为MainVirtualIF_open,这个函数是在启用该网卡设备时调用的,进入该函数
它调用VIRTUAL_IF_UP
__inline INT VIRTUAL_IF_UP(VOID *pAd)
{
RT_CMD_INF_UP_DOWN InfConf = { rt28xx_open, rt28xx_close };
if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP,
0, &InfConf, 0) != NDIS_STATUS_SUCCESS)
return -1;
return 0;
}
进入rt28xx_open函数,
里面调用rt28xx_init,
又调用RtmpNetTaskInit
NDIS_STATUS RtmpNetTaskInit(
IN RTMP_ADAPTER *pAd)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
/* Create receive tasklet */
RTMP_OS_TASKLET_INIT(pAd, &pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->mgmt_dma_done_task, rtusb_mgmt_dma_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->ac0_dma_done_task, rtusb_ac0_dma_done_tasklet, (unsigned long)pAd);
#ifdef RALINK_ATE
RTMP_OS_TASKLET_INIT(pAd, &pObj->ate_ac0_dma_done_task, rtusb_ate_ac0_dma_done_tasklet, (unsigned long)pAd);
#endif /* RALINK_ATE */
RTMP_OS_TASKLET_INIT(pAd, &pObj->ac1_dma_done_task, rtusb_ac1_dma_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->ac2_dma_done_task, rtusb_ac2_dma_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->ac3_dma_done_task, rtusb_ac3_dma_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->hcca_dma_done_task, rtusb_hcca_dma_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->null_frame_complete_task, rtusb_null_frame_done_tasklet, (unsigned long)pAd);
RTMP_OS_TASKLET_INIT(pAd, &pObj->pspoll_frame_complete_task, rtusb_pspoll_frame_done_tasklet, (unsigned long)pAd);
return NDIS_STATUS_SUCCESS;
}
查看下宏RTMP_OS_TASKLET_INIT
#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \
tasklet_init(__pTasklet, __pFunc, __Data)
是个tasklet,随便进入一个函数,如rtusb_ac3_dma_done_tasklet,里面调用RTUSBKickBulkOut
该函数正是提交urb的地方
今天到此