USB-RNDIS

本文详细分析了USB-RNDIS设备驱动的初始化、中断服务程序及其处理流程,涉及PDD_Init、硬件初始化、中断响应及端点配置等关键环节。通过设置端点属性、中断配置和设备状态管理,实现USB设备与主机间的数据和控制通路。
摘要由CSDN通过智能技术生成
导读:
  RNDIS原理分析--PDD部分
  ---------------by nasiry
  转载请说明出处,并通知我
  
  1.初始化
  首先我们从PDD_Init开始。
  所谓初始化的动作通常包含对硬件设备的初始化,一般说来就是通过设置设备寄存器来对设备进行必要的配置,另外一个方面就是软件的初始化,包括全局数据变量的空间申请初始化,中断函数的挂接,其他函数指针的挂接。
  既然需要读写设备的状态寄存器设备的端口/地址就是必不可少的,首先PDD_init先检查有没有从MDD传过来的设备地址,如果没有,通过PciFind2890找一下我们需要的2980有没有在PCI以查卡的形式在某一个插槽上,如果继没有由MDD传递过来的设备地址,PCI插槽上也没有我们需要的2890,怎么办?还能怎么办,既然没有的话,我也干不下去了,return False算了,88下次再见:P
  如果在PCI插口上发现2890的话,就比较麻烦一点,因为需要去计算PCI总线上的设备偏移才能得到设备地址,不仅如次还要去摆弄一个叫9054的片子来符合和PCI的规范,其实我们要的只是一个地址和一个中断源,没有必要再PCI设备上搞来搞去,最简单的办法就是假设这个2890是直接挂在系统总线上的,事实上现在用得很普遍的ARM体系下通常都是没有PCI总线的,这样子我们就只用分析MDD直接传递了设备地址的情况,简单还不乏实用性。总之,我就是不分析PCI总线相关的部分,因为我不会。下面废话少说进入正题。
  PDD_init有两个参数第一个是一个结构指针原形如下:
  typedef struct _RNDIS_PDD_CHARACTERISTICS
  { PFN_PDD_SEND_RNDIS_MESSAGE SendRndisMessageHandler;
  PFN_PDD_SEND_RNDIS_PACKET SendRndisPacketHandler;
  PFN_PDD_INDICATE_RNDIS_PACKET_COMPLETE IndicateRndisPacketCompleteHandler;
  PFN_PDD_SET SetHandler;
  PFN_PDD_GET GetHandler;
  PFN_PDD_ISR ISRHandler;
  DWORD dwIRQ;
  DWORD dwMaxRx;
  DWORD dwBaseAddr;
  // BUS specific information
  // If it is PCI then this driver will be loaded by PCI enumerator through
  // NDIS.
  BOOL bPCIDevice;
  // These are only needed for PCI type device AND if the driver chooses
  // to use GIISR.DLL as default ISR.
  BOOL CheckPort; // If true, check port to see if device is asserting IRQ
  BOOL PortIsIO; // Port is IO port (possibly true only for x86)
  BOOL UseMaskReg; // If true, read from MaskAddr to obtain mask
  DWORD PortAddr; // Port Address
  DWORD PortSize; // Port data width in bytes
  DWORD Mask; // Mask to use on data port to determine if device is asserting IRQ
  DWORD MaskAddr; // Address of register to use as mask
  } RNDIS_PDD_CHARACTERISTICS, *PRNDIS_PDD_CHARACTERISTICS;
  这个结构包含了一系列的函数指针和地址,中断,和最大接收数等信息,没有提到的这些个结构成员都是PCI设备所需的,这里我们仅仅需要把bPCIDevice设置为False也就是说我们并没有使用PCI设备就可以了。注意这个参数的类型是OUT,MDD也就是通过这里得到设备的信息的。因此在这里需要填充该结构,然后完成对硬件的初始化。
  另外还有一个相当重要的结构,这个结构在全局范围内存在一个实例,是我们的PDD工作的中心,我们来看看这个结构的原形。
  typedef struct
  { volatile PUCHAR pucBaseAddress;
  volatile PUCHAR puc9054Address;
  ULONG ulIRQ;
  DWORD dwSysIntr;
  BOOL bConnected;
  BYTE bUsbAddress;
  // EP0 related operations..
  BOOL bSending;
  LIST_ENTRY listTxRndisMessageQueue;
  PDATA_WRAPPER pCurrentSendRndisMessage;
  PBYTE pbCurrentSend;
  DWORD dwCurrentSendSizeLeft;
  UCHAR ucScratchBuffer;
  
  BYTE pbEP0ReceiveBuffer[EP0_MAX_RECEIVE_BUFFER];
  DATA_WRAPPER EP0DataWrapper;
  DWORD dwExpectedRxSize;
  DWORD dwTotalReceived;
  PBYTE pbCurrentRx;
  // EP1 related operations..
  PDATA_WRAPPER pEP1DataWrapper;
  // EP2 related operations..
  PDATA_WRAPPER pEP2DataWrapper;
  PBYTE pbEP2CurrentSend;
  DWORD dwEP2TotalSent;
  BOOL bEP2ShortPacketSent;
  UCHAR MacAddress[6];
  }RNDIS_2890;
  pucBaseAddress是用于存放设备的基地址,puc9054Address仅仅是在使用PCI卡的时候使用,原因上面说过了。ulIRQ指硬件中断号,dwSysIntr
  也是在PCI模式下用,因为这种模式下我们只能使用"可安装"的中断(因为PCI查卡位置不同中断不同)。bConnected是连接状态的标示,bUsbAddress则是来自于USB协议本身的要求。
  硬件的初始化是在NET2890Init中完成的,进行的是一系列的寄存器操作以完成对USB各个ENDPoint的配置,如果对源码或者这个芯片本身有兴趣的话可以参考NET2890 USB Interface Controller For Revision 2 IC来看具体的代码,我这里仅仅将相应的配置总结出来如下:
  RNDIS 2890配置
  ENDPOINT
  EP0 control(IN/OUT) enable
  1.FIFO Valid Mode FIFO Flush
  2.EP0 Packet Size =8byte
  3.Handshake receive
  EP1(EPA)OUT enable
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值