DOS下检索XHCI下所有的USB设备,并显示出设备接在哪个端口上,以及该USB device的speed。

来源:互联网 发布:阿里云 自定义端口 编辑:程序博客网 时间:2024/06/05 07:09

                XHCI:即可扩展的主机控制器接口,目前主要是面向USB3.0设备的,同时它也支持USB2.0及以下的设备。其中USB2.0使用的是EHCI,USB1.1使用的是OHCI。

          为了实现在DOS下检索XHCI下所有的USB设备,并显示出设备接在哪个端口上,并读出该USB device的speed。文章分为4步实现:

1.通过检索PCI设备,找到USB Controller,也可以通过RU.exe找到USB Controller对应的地址,对应的bus# = 0,device# = 0x10,function# = 0,ofs = 0x10。这样就可以得到Capability Register Base Address。在此基础上可以进一步得到Operational Register Base Address。如图4.1所示:

图 4.1

其中Capability Register是在对USB controller初始化时使用,而Operational Register则是在USB controller运行时使用,比如当USB device被检测到的时候。(注1:图4.1中的Base即capability register base address)

2. 对USB host controller 初始化。初始化首先将USB controller 停止工作(stop)。就是将图4.2中的R/S位置0。因为Software停止有一定的延迟,通过USB状态寄存器中的HCH位(如图4.3所示)判断,可以得到当前USB controller 具体的状态,当HCH = 1时,表示Host Controller 被挂起,USB Controller处于停止状态,反之,则USB Controller处于工作状态。等到USB Controller 停止后,对其进行initialization操作。

图 4.2

 

图 4.3

3.初始化后,运行(Run)USB host controller。同样的,也要通过状态寄存器对当前USB controller 状态控制器中的HCH位判断。

4.当USB controller Run起来后,对所有USB 端口进行遍历(注2:端口数目可以通过图4.4中bit31:24得到),当发现对应端口的状态为为Attach时,表明该端口有接设备,如图4.5所示,当bit0为1时,表示USB设备处于Attach状态。由于USB2.0设备和USB3.0设备的区别,USB3.0设备能够自动上电,而USB2.0则需要给其一个上升沿脉冲才可以上电,可以通过图4.5中bit1来判断,若bit1 = 1则表示该设备为USB3.0设备,反之则为USB2.0设备。若为USB2.0设备,通过bit4给其一个上升沿脉冲,使其能够上电。当上电后,就可以对该USB device的Speed进行读取操作了,USB device的speed可以在图4.5中的bit13:10获取到。

图 4.4

图 4.5

代码如下:
#include <stdio.h>#include <PCI_Acc.h>#include <MEM_Acc.h>#include <dos.h>typedef unsigned long DWORD;typedef unsigned int  WORD;typedef unsigned char uchar;/* Stop USB host controller */void Stop_XHCI(DWORD Ope_reg_bas){uchar USBCMD = Read_Mem_Byte(Ope_reg_bas + 0);USBCMD = USBCMD&0xFE;Write_Mem_Byte(Ope_reg_bas + 0,USBCMD);uchar HCH = Read_Mem_Byte(Ope_reg_bas + 0x04)&0x1;while(HCH!=1){HCH = Read_Mem_Byte(Ope_reg_bas + 0x04)&0x1;delay(1);}printf("XHCI Controller is stop!\n");}/* Reset USB host controller */void Reset_XHCI(DWORD Ope_reg_bas){uchar USBCMD = Read_Mem_Byte(Ope_reg_bas + 0);USBCMD = USBCMD|0x02;                                /* HCRST = 1 */Write_Mem_Byte(Ope_reg_bas + 0,USBCMD);uchar HCRST = (Read_Mem_Byte(Ope_reg_bas + 0)>>1)&0x1;while(HCRST!=0){HCRST = (Read_Mem_Byte(Ope_reg_bas + 0)>>1)&0x1;delay(1);}printf("XHCI Controller is Reset!\n");}/* Run USB host controlle */void Run_XHCI(DWORD Ope_reg_bas){uchar USBCMD = Read_Mem_Byte(Ope_reg_bas + 0);USBCMD = USBCMD|0x1;Write_Mem_Byte(Ope_reg_bas + 0,USBCMD);uchar HCH = Read_Mem_Byte(Ope_reg_bas + 0x04)&0x1;while(HCH!=0){HCH = Read_Mem_Byte(Ope_reg_bas + 0x04)&0x1;delay(1);}printf("XHCI Controller is run!\n");}/* Scan port and get speed */void Scan_detect(DWORD Cap_reg_bas,DWORD Ope_reg_bas){/* MaxPorts */uchar MaxPorts = Read_Mem_Dword(Cap_reg_bas + 0x04)>>24;printf("MaxPorts = %d\n",MaxPorts);uchar portsc;uchar ccs;WORD port_speed;for(int i=1;i<=MaxPorts;i++){uchar bit1;DWORD ofs_addr = 0x400 + (0x10)*(i-1);uchar ccs = Read_Mem_Byte(Ope_reg_bas + ofs_addr)&0x1;if (1==ccs){printf("The port number is %d\n",i);/* set 0 */portsc = Read_Mem_Byte(Ope_reg_bas + ofs_addr);portsc = portsc&0xEF;Write_Mem_Byte(Ope_reg_bas + ofs_addr,portsc);/* set 1 */portsc = Read_Mem_Byte(Ope_reg_bas + ofs_addr);portsc = portsc|0x10;Write_Mem_Byte(Ope_reg_bas + ofs_addr,portsc);bit1 = Read_Mem_Byte(Ope_reg_bas + ofs_addr)&0x02;while(bit1==0){delay(100);bit1 = Read_Mem_Byte(Ope_reg_bas + ofs_addr)&0x02;}port_speed = (Read_Mem_Dword(Ope_reg_bas + ofs_addr)>>10)&0xF;printf("port_speed = %x\n",port_speed);}}}int main(){Enter_Big_Real_Mode();WORD bus,devc,func,ofs;bus = 0x00; devc = 0x10; func = 0x00; ofs = 0x10;DWORD Cap_reg_bas = Read_PCI_Dword(bus,devc,func,ofs)&0xFFFFFFF8;printf("Cap_reg_bas = %lx\n", Cap_reg_bas);DWORD Ope_reg_bas = Read_Mem_Byte(Cap_reg_bas + 0) + Cap_reg_bas;printf("Ope_reg_bas = %lx\n", Ope_reg_bas);Stop_XHCI(Ope_reg_bas);Reset_XHCI(Ope_reg_bas);Run_XHCI(Ope_reg_bas);Scan_detect(Cap_reg_bas,Ope_reg_bas);Exit_Big_Real_Mode();return 0;}