现在的位置: 首页 > 综合 > 正文

DOS 下枚举USB设备是否存在

2013年10月22日 ⁄ 综合 ⁄ 共 7313字 ⁄ 字号 评论关闭

http://hi.baidu.com/litomboy/blog/item/9b04387330baca0a8601b00b.html

编程思路:遍历PCI 设备,根据设备的ClassCode 找到USB设备,根据PCI空间定义找到USB设备的MEM_BASE,根据MEM_BASE 找到各个port

的接口状态,首先说明下HR平台下port口的状态跟SPEC不同,是根据RW观察出来的,代码如下:

/*

 File:      usbport.c
 Name:      访问CF8h、CFCh端口来枚举PCI 中的USB 设备
 Author:    James  lee
 Blog:       http://hi.baidu.com/litomboy
 Version:   V1.0
 Updata:    2011-04-19
 
*/
#include <dos.h> 
#include <stdio.h>
#include <conio.h>

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

/* PCI设备索引。bus/dev/func 共16位,为了方便处理可放在一个WORD中 */

#define PDI_BUS_SHIFT     8
#define PDI_BUS_SIZE       8
#define PDI_BUS_MAX       0xFF
#define PDI_BUS_MASK     0xFF00

#define PDI_DEVICE_SHIFT    3
#define PDI_DEVICE_SIZE      5
#define PDI_DEVICE_MAX      0x1F
#define PDI_DEVICE_MASK    0x00F8

#define PDI_FUNCTION_SHIFT   0
#define PDI_FUNCTION_SIZE     3
#define PDI_FUNCTION_MAX     0x7
#define PDI_FUNCTION_MASK    0x0007

#define MK_PDI(bus,dev,func) (WORD)((bus&PDI_BUS_MAX)<<PDI_BUS_SHIFT | (dev&PDI_DEVICE_MAX)<<PDI_DEVICE_SHIFT | (func&PDI_FUNCTION_MAX) )

/* PCI配置空间寄存器 */

#define PCI_CONFIG_ADDRESS      0xCF8
#define PCI_CONFIG_DATA           0xCFC

 

/* 填充PCI_CONFIG_ADDRESS */

#define MK_PCICFGADDR(bus,dev,func) (DWORD)(0x80000000L | (DWORD)MK_PDI(bus,dev,func)<<8)
#define KeyWait()   {while(inportb(0x64)&2);}   

unsigned long   GDT_Table[]=  
{  
    0,0,                //NULL   - 00H   
    0x0000FFFF,0x00CF9A00,      //Code32 - 08H Base=0 Limit=4G-1 Size=4G   
    0x0000FFFF,0x00CF9200       //Data32 - 10H Base=0 Limit=4G-1 Size=4G   
};  
unsigned char   OldIDT[6]={0};      //Save The IDTR before Enter Protect Mode.   
unsigned char   pdescr_tmp[6]={0};  //NULL The IDTR,IDTR's Limit=0 will   
//disable all Interrupts,include NMI.   
  

void    A20Enable(void)  
{  
    KeyWait();  
    outportb(0x64,0xD1);  
    KeyWait();  
    outportb(0x60,0xDF);    //Enable A20 with 8042.   
    KeyWait();  
    outportb(0x64,0xFF);  
    KeyWait();  
}  
void    LoadFSLimit4G(void)  
{  
    A20Enable();        //Enable A20   
    //**************************************   
    //*       Disable ints & Null IDT      *   
    //**************************************   
   
    asm {  
        CLI                 //Disable inerrupts   
        SIDT    OldIDT      //Save OLD IDTR   
        LIDT    pdescr_tmp  //Set up empty IDT.Disable any interrupts,   
        }           //Include NMI.   
   
    //***************************************   
    //*         Load GDTR       *   
    //***************************************   
    asm { //The right Code is Real,But BC++'s Linker NOT Work with 32-bits Code.   
        db  0x66        //32 bit Operation Prefix in 16 Bit DOS.   
        MOV CX,DS               //MOV   ECX,DS   
        db  0x66                //Get Data segment physical Address   
        SHL CX,4                //SHL   ECX,4   
        MOV word ptr pdescr_tmp[0],(3*8-1)  //MOV   word ptr pdescr_tmp[0],(3*8-1)   
        db  0x66  
        XOR AX,AX               //XOR   EAX,EAX   
        MOV AX,offset GDT_Table     //MOV   AX,offset GDT_Table   
        db  0x66  
        ADD AX,CX               //ADD   EAX,ECX   
        MOV word ptr pdescr_tmp[2],AX   //GDTR Base high16 bits   
        db  0x66  
        SHR AX,16               //SHR   EAX,16   
        MOV word ptr pdescr_tmp[4],AX   //GDTR Base high16 bits   
        LGDT    pdescr_tmp          //Load GDTR   
        }  
    //**************************************   
    //*  Enter 32 bit Flat Protected Mode  *   
    //**************************************   
    //  Set CR0 Bit-0 to 1 Enter 32 Bit Protection   
    //Mode,And NOT Clear machine perform cache,It Meaning   
    //the after Code HAD Ready To RUN in 32 Bit Flat Mode,   
    //Then Load Flat Selector to FS and Description into it's   
    //Shadow register,After that,ShutDown Protection Mode   
    //And ReEnter Real Mode immediately.   
    //  The FS holds Base=0 Size=4G Description and   
    //it can Work in Real Mode as same as Pretect Mode,   
    //untill FS be reloaded.   
    //  In that time All the other Segment Registers are   
    //Not Changed,except FS.(They are ERROR Value holded in CPU).   
    asm {  
        MOV DX,0x10         //The Data32 Selector   
        db  0x66,0x0F,0x20,0xC0 //MOV   EAX,CR0   
        db  0x66  
        MOV BX,AX           //MOV   EBX,EAX   
        OR  AX,1  
        db  0x66,0x0F,0x22,0xC0 //MOV   CR0,EAX //Set Protection enable bit   
        JMP Flush  
        }               //Clear machine perform cache.   
    Flush:  //Now In Flat Mode,But The CS is Real Mode Value.   
    asm {   //And it's attrib is 16-Bit Code Segment.   
        db  0x66  
        MOV AX,BX           //MOV   EAX,EBX   
        db  0x8E,0xE2       //MOV   FS,DX   //Load FS now   
        db  0x66,0x0F,0x22,0xC0 //MOV   CR0,EAX //Return Real Mode.Now FS's Base=0 Size=4G   
        LIDT    OldIDT          //LIDT  OldIDT  //Restore IDTR   
        STI             //STI       //Enable INTR   
        }  
}  
//With FS can Access All 4G Memory Now.But if FS be reloaded in Real Mode   
//It's Limit will Be Set to FFFFh(Size=64K),then Can not used it to Access   
//4G bytes Memory Again,Because FS is Segment:Offset Memory type after that.   
//If Use it to Access large than 64K will generate Execption 0D.   
unsigned char   ReadByte(unsigned long Address)  
{  
    asm db  0x66  
    asm mov di,word ptr Address //MOV   EDI,Address   
    asm db  0x67            //32 bit Address Prefix   
    asm db  0x64            //FS:   
    asm mov al,byte ptr [BX]    //=MOV AL,FS:[EDI]   
    return  _AL;  
}  
unsigned char   WriteByte(unsigned long Address)  
{  
    asm db  0x66  
    asm mov di,word ptr Address //MOV   EDI,Address   
    asm db  0x67            //32 bit Address Prefix   
    asm db  0x64            //FS:   
    asm mov byte ptr [BX],al    //=MOV FS:[EDI],AL   
    return  _AL;  

/* 读32位端口 */

DWORD inpd(int portid)
{
 DWORD dwRet;
 asm mov dx, portid;
 asm lea bx, dwRet;
 __emit__(
 0x66,0x50,              /* push EAX*/
 0x66,0xED,              /*in EAX,DX*/
 0x66,0x89,0x07,       /* mov [BX],EAX*/
 0x66,0x58);             /*pop EAX*/
 return dwRet;
 }
 
/* 写32位端口 */
void outpd(int portid, DWORD dwVal)
 {
  asm mov dx, portid;
  asm lea bx, dwVal;
  __emit__(
  0x66,0x50,              /* push EAX */
  0x66,0x8B,0x07,      /*mov EAX,[BX]*/
  0x66,0xEF,             /*out DX,EAX*/
  0x66,0x58);           /*pop EAX*/
  return;
 }
 
 int main(void)
 {
  int bus, dev, func;
  int i,j;
  unsigned char index;
  DWORD dwAddr;
  DWORD dwData;
  FILE* hF;
  char szFile[0x10];
  LoadFSLimit4G();
  printf("\n");
  //printf("Bus#\tDevice#\tFunc#\tVendor\tDevice\tClass\tIRQ\tIntPin\n");
    /* 枚举PCI设备 */
  j=0;
  for(bus = 0; bus <= PDI_BUS_MAX; ++bus)
  {
   for(dev = 0; dev <= PDI_DEVICE_MAX; ++dev)
   {
    for(func = 0; func <= PDI_FUNCTION_MAX; ++func)
    {
     /* 计算地址 */
     dwAddr = MK_PCICFGADDR(bus, dev, func);
     /* 获取厂商ID */
     outpd(PCI_CONFIG_ADDRESS, dwAddr);
     dwData = inpd(PCI_CONFIG_DATA);
     /* 判断设备是否存在。FFFFh是非法厂商ID */
     if ((WORD)dwData != 0xFFFF)
      {
       /* Class Code    USB Host Controller的Class Code是0x0c03  */    
       outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x8);    
       dwData = inpd(PCI_CONFIG_DATA);
       if((dwData>>16)==0x0c03)
       {
        if(((dwData>>8)&0xff)==0x00)
        {
         printf("Find UHCI USB \n");
        }
        if(((dwData>>8)&0xff)==0x10)
        {
         printf("Find OHCI USB \n");
        }
        if(((dwData>>8)&0xff)==0x20)
        {
         //printf("Find EHCI USB \n");
         outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x10);
         dwData = inpd(PCI_CONFIG_DATA);
         dwData=dwData+0XF0;
         //printf("%lX\n",dwData);
         for(i=0;i<=6;i++)
         {
              //dwData++;
          //printf("%lX\n",dwData);
          index=ReadByte(dwData);
          dwData++;
          //printf("Find %d EHCI USB:%02X \n",i+1,index);
          if((index==0x18)||(index==0x10))
          {
           j++;
           printf("Find %d EHCI USB\n",j);
           }
         }
         //printf("%lX\n",dwData);
        }
        }
       
      }
    }
   }
  }
  return 0;
 }

抱歉!评论已关闭.