PCIE设备扫描的过程_第1页
PCIE设备扫描的过程_第2页
PCIE设备扫描的过程_第3页
PCIE设备扫描的过程_第4页
PCIE设备扫描的过程_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PCIE设备扫描的过程初步理解完PCI总线原则之后,我们接下来正式开始PCIe设备的漫游之旅。从我们按下PC的电源按钮开始,BIOS就接管系统控制权开始工作,它会先进行某些内存和设备的初始化工作(固然,也涉及我们的PCI设备),由于商业上的因素,Phoenix等厂商的BIOS代码需要授权合同,在此,我们以另外一种款开源BIOS(openbios)为例,来剖析BIOS中,我们的PCIe设备是如何被找到以及初始化的。PCI设备的扫描是基于深度优先搜索HYPERLINK\o"算法与数据构造知识库"算法(DFS:DepthFirstSearch),也就是说,下级分支最多的PCI桥将最先完毕其子设备的扫描。下面我们以图片来具体阐明,BIOS是如何一步步完毕PCI设备扫描的。第一步:PCIHost主桥扫描Bus0上的设备(在一种解决器系统中,普通将与HOST主桥直接相连的PCI总线被命名为PCIBus0),系统首先会忽视Bus0上的D1,D2等不会挂接PCI桥的设备,主桥发现Bridge1后,将Bridge1下面的PCIBus定为Bus1,系统将初始化Bridge1的配备空间,并将该桥的PrimaryBusNumber和SecondaryBusNumber寄存器分别设立成0和1,以表明Bridge1的上游总线是0,下游总线是1,由于还无法拟定Bridge1下挂载设备的具体状况,系统先临时将SubordinateBusNumber设为0xFF。以下图所示:第二步:系统开始扫描Bus1,将会发现Bridge2。系统将Bridge2下面的PCIBus定为Bus2,并将该桥的PrimaryBusNumber和SecondaryBusNumber寄存器分别设立成1和2,和上一步同样临时把Bridge2的SubordinateBusNumber设为0xFF。以下图所示:第三步:系统继续扫描Bus2,将会发现Bridge4。系统将Bridge4下面的PCIBus定为Bus3,并将该桥的PrimaryBusNumber和SecondaryBusNumber寄存器分别设立成2和3,此后系统继续扫描后发现Bus3下面已经没有任何Bridge了,意味着该PCI总线下已经没有任何挂载下游总线了,因此Bridge4的SubordinateBusNumber的值已经能够拟定为3了。以下图所示:第四步:完毕Bus3的扫描后,系统返回到Bus2继续扫描,发现Bus2下面已经没有其它Bridge了。此时Bridge2的SubordinateBusNumber的值也已经能够拟定为3了。以下图所示:第五步:完毕Bus2的扫描后,系统返回到Bus1继续扫描,会发现Bridge3,系统将Bridge3下面的PCIBus定为Bus4。并将Bridge4的PrimaryBusNumber和SecondaryBusNumber寄存器分别设立成1和4,此后系统继续扫描后发现Bus4下面已经没有任何Bridge了,意味着该PCI总线下已经没有挂载任何下游总线了,因此Bridge3的SubordinateBusNumber的值已经能够拟定为4了。以下图所示:第六步:完毕Bus4的扫描后,系统返回到Bus1继续扫描,发现Bus1下面已经没有其它Bridge了。此时Bridge1的SubordinateBusNumber的值已经能够拟定为4,系统返回Bus0继续扫描(Bus0下如果有其它它Bridge,将重复上述的环节进行扫描)。至此,本例中的整个PCI的设备扫描已经完毕了。最后的设备和总线的扫描成果以下图所示。理解了上面PCI设备扫描的大概流程,我们接下来看看Bios代码中具体是如何实现这些扫描的。普通来说,我们能够通过两个寄存器来访问PCI的配备空间(寄存器CONFIG_ADDRESS与CONFIG_DATA),在x86体系下,这两个寄存器分别对应0xCF8和0xCFC端口,对配备空间的访问都是通过对这两个寄存器的读写来实现先。CONFIG_ADDRESS寄存器的具体位构成以下图所示:BusNumber:总线号(8bit),范畴0--255。DeviceNumber:设备号(5bit),范畴0--31。FunctionNumber:功效号(3bit),范畴0--7。RegisterNumber:寄存器号(6bit),范畴0--63(配备空间一共256个字节,分割成64个4字节的寄存器,从0--63编号)。每个PCI设备可根据上图所示的四个信息:BusNumber,DeviceNumber,FunctionNumber,RegisterNumber来进行具体设备的定位并对其配备空间访问。当我们要访问PCI设备的配备空间时,先根据以上格式设立CONFIG_ADDRESS寄存器,然后再读取CONFIG_DATA寄存器即可得到对应的配备空间寄存器的值。因此,BIOS中PCI配备空间的读写能够封装成下面的函数:[cpp]HYPERLINK\o"viewplain"viewplainHYPERLINK\o"copy"copystaticinlineuint32_tpci_config_read32(pci_addrdev,uint8_treg){outl(dev|reg,0xcf8);returninl(0xcfc|reg);}staticinlinevoidpci_config_write32(pci_addrdev,uint8_treg,uint32_tval){outl(dev|reg,0xcf8);outl(val,0xcfc);}总体来说。该BIOS扫描过程中调用以下几个重要的函数:ob_pci_init---->ob_scan_pci_bus---->pci_find_device---->ob_pci_configure下面我们来具体看看代码,首先BIOS执行ob_pci_init(void)函数[cpp]HYPERLINK\o"viewplain"viewplainHYPERLINK\o"copy"copyintob_pci_init(void){intbus;unsignedlongmem_base,io_base;char*path;#ifdefCONFIG_DEBUG_PCIprintk("InitializingPCIdevices...\n");#endif/*bruteforcebusscan*//*FindallPCIbridges*///获取系统指定的memeory与I/O空间的范畴,分派给PCIe设备。mem_base=arch->mem_base;/*I/Oportsunder0x400areusedbydevicesmappedatfixedlocation.*/io_base=arch->io_base+0x400;path=strdup("");/*遍历256条总线*/for(bus=0;bus<0x100;bus++){ob_scan_pci_bus(bus,&mem_base,&io_base,&path);}free(path);return0;}总线扫描具体实现:[cpp]HYPERLINK\o"viewplain"viewplainHYPERLINK\o"copy"copystaticvoidob_scan_pci_bus(intbus,unsignedlong*mem_base,unsignedlong*io_base,char**path){intdevnum,fn,is_multi,vid,did;unsignedinthtype;pci_addraddr;pci_config_tconfig;constpci_dev_t*pci_dev;uint32_tccode;uint8_tclass,subclass,iface,rev;activate_device("/");for(devnum=0;devnum<32;devnum++){is_multi=0;for(fn=0;fn==0||(is_multi&&fn<8);fn++){#ifdefCONFIG_XBOXif(pci_xbox_blacklisted(bus,devnum,fn))continue;#endifaddr=PCI_ADDR(bus,devnum,fn);/*获取设备配备空间地址*/vid=pci_config_read16(addr,PCI_VENDOR_ID);/*获取VendorID*/did=pci_config_read16(addr,PCI_DEVICE_ID);/*获取DeviceID*/if(vid==0xffff||vid==0)continue;ccode=pci_config_read16(addr,PCI_CLASS_DEVICE);class=ccode>>8;subclass=ccode;iface=pci_config_read8(addr,PCI_CLASS_PROG);rev=pci_config_read8(addr,PCI_REVISION_ID);pci_dev=pci_find_device(class,subclass,iface,/*具体设备查找以及初始化*/vid,did);#ifdefCONFIG_DEBUG_PCIprintk("%x:%x.%x-%x:%x-",bus,devnum,fn,vid,did);#endifhtype=pci_config_read8(addr,PCI_HEADER_TYPE);if(fn==0)is_multi=htype&0x80;if(pci_dev==NULL||pci_dev->name==NULL)snprintf(config.path,sizeof(config.path),"%s/pci%x,%x",*path,vid,did);elsesnprintf(config.path,sizeof(config.path),"%s/%s",*path,pci_dev->name);#ifdefCONFIG_DEBUG_PCIprintk("%s-",config.path);#endifconfig.dev=addr&0x00FFFFFF;REGISTER_NAMED_NODE(ob_pci_node,config.path);activate_device(config.path);ob_pci_configure(addr,&config,mem_base,io_base);/*配备设备的配备空间*/ob_pci_add_properties(addr,pci_dev,&config);if(class==PCI_BASE_CLASS_BRIDGE&&(subclass==PCI_SUBCLASS_BRIDGE_HOST||subclass==PCI_SUBCLASS_BRIDGE_PCI)){/*hostorbridge*/free(*path);*path=strdup(config.path);}}}device_end();}具体某条总线上的设备扫描由下列函数实现:[cpp]HYPERLINK\o"viewplain"viewplainHYPERLINK\o"copy"copy<prename="code"class="cpp">constpci_dev_t*pci_find_device(uint8_tclass,uint8_tsubclass,uint8_tiface,uint16_tvendor,uint16_tproduct){int(*config_cb)(constpci_config_t*config);constpci_class_t*pclass;constpci_subclass_t*psubclass;constpci_iface_t*piface;constpci_dev_t*dev;constvoid*private;pci_dev_t*new;constchar*name,*type;name="unknown";type="unknown";config_cb=NULL;private=NULL;if(class==0x00&&subclass==0x01){/*SpecialhackforoldstyleVGAdevices*/class=0x03;subclass=0x00;}elseif(class==0xFF){/*Specialcaseformiscdevices*/dev=misc_pci;gotofind_device;}if(class>(sizeof(pci_classes)/sizeof(pci_class_t))){name="invalidPCIdevice";type="invalid";gotobad_device;}pclass=&pci_classes[class];name=pclass->name;type=pclass->type;for(psubclass=pclass->subc;;psubclass++){if(psubclass->subclass==0xFF)gotobad_device;if(psubclass->subclass==subclass){if(psubclass->name!=NULL)name=psubclass->name;if(psubclass->type!=NULL)type=psubclass->type;if(psubclass->config_cb!=NULL){config_cb=psubclass->config_cb;}if(psubclass->private!=NULL)private=psubclass->private;if(psubclass->iface!=NULL)break;dev=psubclass->devices;gotofind_device;}}for(piface=psubclass->iface;;piface++){if(piface->iface==0xFF){dev=psubclass->devices;break;}if(piface->iface==iface){if(piface->name!=NULL)name=piface->name;if(piface->type!=NULL)type=piface->type;if(piface->config_cb!=NULL){config_cb=piface->config_cb;}if(piface->private!=NULL)private=piface->private;dev=piface->devices;break;}}find_device:if(dev==NULL)gotobad_device;for(;;dev++){if(dev->vendor==0xFFFF&&dev->product==0xFFFF){gotobad_device;}if(dev->vendor==vendor&&dev->product==product){if(dev->name!=NULL)name=dev->name;if(dev->type!=NULL)type=dev->type;if(dev->config_cb!=NULL){config_cb=dev->config_cb;}if(dev->private!=NULL)private=dev->private;new=malloc(sizeof(pci_dev_t));if(new==NULL)returnNULL;new->vendor=vendor;new->product=product;new->type=type;new->name=name;new->model=dev->model;new->compat=dev->compat;new->acells=dev->acells;new->scells=dev->scells;new->icells=dev->icells;new->config_cb=config_cb;new->private=private;returnnew;}}bad_device:printk("Cannotmanage'%s'PCIdevicetype'%s':\n%x%x(%x%x%x)\n",name,type,vendor,product,class,subclass,iface);returnNULL;}配备具体设备的配备空间staticvoidob_pci_configure(pci_addraddr,pci_config_t*config,unsignedlong*mem_base,unsignedlong*io_base){uint32_tsmask,omask,amask,size,reloc,min_align;unsignedlongbase;pci_addrconfig_addr;intreg;uint8_tirq_pin,irq_line;/*配备中断引脚与中断编号*/irq_pin=pci_config_read8(addr,PCI_INTERRUPT_PIN);if(irq_pin){config->irq_pin=irq_pin;irq_pin=(((config->dev>>11)&0x1F)+irq_pin-1)&3;irq_line=arch->irqs[irq_pin];pci_config_write8(addr,PCI_INTERRUPT_LINE,irq_line);config->irq_line=irq_line;}elseconfig->irq_line=-1;/*配备memory空间和I/O空间*/omask=0x00000000;for(reg=0;reg<7;reg++){config->assigned[reg]=0x00000000;config->sizes[reg]=0x00000000;if((omask&0x0000000f)==0x4){/*64bitsmemorymapping*/continue;}if(reg==6)config_addr=PCI_ROM_ADDRESS;elseconfig_addr=PCI_BASE_ADDR_0+reg*4;config->regions[reg]=pci_config_read32(addr,config_addr);/*getregionsize*/pci_config_write32(addr,config_addr,0xffffffff);smask=pci_config_read32(addr,config_addr);if(smask==0x00000000||

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论