




免费预览已结束,剩余26页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第二章 PCI设备初始化系统刚上电时,CPU从0xbfc0.0000开始执行。这个地址在Rom空间中,在完成TLB,Cache,UART等初始化后,CPU就将代码拷到0x8010.0000开始的RAM空间(这个地址是编译Pmon时分配符号_start的),然后跳转到initmips(),开始在内存空间的执行。执行initmips之前,CPU做的初始化只是初步的,其作用只是为CPU在内存中运行做一些必要的准备。主要的初始化工作:PCI设备的扫描、空间映射、资源分配都是initmips()函数所完成的。下面我们跟踪initmips的执行来观察系统初始化的过程。voidinitmips(unsigned int memsz)/* *Set up memory address decoders to map entire memory. *But first move away bootrom map to high memory. */memorysize=(memsz&0x0000ffff) 16) pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;pd-pa.pa_iot = pmalloc(sizeof(bus_space_tag_t);pd-pa.pa_iot-bus_reverse = 1;pd-pa.pa_iot-bus_base = BONITO_PCIIO_BASE_VA;/printf(pd-pa.pa_iot=%p,bus_base=0x%xn,pd-pa.pa_iot,pd-pa.pa_iot-bus_base);pd-pa.pa_memt = pmalloc(sizeof(bus_space_tag_t);pd-pa.pa_memt-bus_reverse = 1;pd-pa.pa_memt-bus_base = PCI_LOCAL_MEM_PCI_BASE;pd-pa.pa_dmat = &bus_dmamap_tag;pd-bridge.secbus = pb;_pci_head = pd;从上面可以看到,北桥的pa.pa_flags被设置成IO_ENABLED和MEM_ENABLED,这就表示可以进行IO和内存访问。Pa.pa_iot-bus_base被设置成BONITO_PCI_IO_BASE_VA,这个值被定义为0xbfd0.0000,它在CPU的Kseg1区间,因此是不经过TLB转换的。它的物理地址是0x1fd0.0000。Bontio规范中规定这个地址开始的M空间是PCI的IO空间。一个pci桥的配置体内有三个域和总线相关。分别是上游总线(Primary bus),下游总线(Secondary bus)和下级总线(Subordinate bus)。上游总线是和PCI桥相连的离较近的总线。下游总线是离CPU较远的总线。下级总线则是和PCI相连的总线号最大的总线。对于北桥来说,是没有上游总线的,而他的下游总线就是pcibus0,因此pd-bridge.secbus赋值为pb。pb-minpcimemaddr = PCI_MEM_SPACE_PCI_BASE+0x01000000; pb-nextpcimemaddr= PCI_MEM_SPACE_PCI_BASE+BONITO_PCILO_SIZE;pb-minpciioaddr = PCI_IO_SPACE_BASE+0x000a000;pb-nextpciioaddr =PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE;pb-pci_mem_base = BONITO_PCILO_BASE_VA;/对应256Mpb-pci_io_base = BONITO_PCIIO_BASE_VA;pb-max_lat = 255;pb-fast_b2b = 1;pb-prefetch = 1;pb-bandwidth = 4000000;pb-ndev = 1;_pci_bushead = pb;_pci_bus_max_pci_bus+ = pd;Pcibus的minimemaddr被设置PCI_MEM_SPACE_PCI_BASE+0x01000000。而PCI_MEM_SPACE_PCI_BASE被定义成,因此这个值就是16M.之所以这样做,是因为ISA设备只能使用最低16内存空间。为了保持兼容性,这里预留最低16M的空间给ISA。PCIbus0的nextpcimemadr被设置PCI_MEM_SPACE_PCI_BASE+BONITO_PCILO_SIZE。这个值是192。因此pci设备可用的空间就是16M到192。Pciioaddr的值是PCI_IO_SPACE_BASE+0XA000,Nextioaddr的值是PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE,也就是64k。因此pci设备可用的IO空间就是从地址40k到64k。bus_dmamap_tag._dmamap_offs = 0;/*set Bonito register*/BONITO_PCIMAP = BONITO_PCIMAP_WIN(0, PCI_MEM_SPACE_PCI_BASE+0x00000000) | BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x04000000) | BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x08000000) | BONITO_PCIMAP_PCIMAP_2;BONITO_PCIBASE0 = PCI_LOCAL_MEM_PCI_BASE;BONITO_PCIBASE1 = PCI_LOCAL_MEM_ISA_BASE;BONITO_PCIBASE2 = PCI_LOCAL_MEM_PCI_BASE + 0x10000000;return(1);为了说明上面代码,先要讲一下Bonito中几个寄存器的含义。为了让CPU访问PCI空间,需要将CPU空间映射到PCI空间。在内存空间256M上方有三个连续的大小均为64M的区间,分别称为PCI_Lo0, PCI_Lo1,PCI_Lo2。这三个区间可以被北桥映射到PCI以对齐的任意位置。映射的关系通过设置Bonito的PCIMAP寄存器。该寄存器的格式如下图。 17 12 11 6 5 0 Pci_lo0Pci_lo1 Pci_lo2Pci_map2PCIMAP寄存器Pci_lo0,pci_lo1,Pci_lo2分别是上面所说三个区间的高位地址(bit31-26),而Pci_map2是说明映射到以上的空间还是G以下的空间。因此上面给BONITO_PCIMAP赋值就将PCI_lo0,PCI_lo1,PCI_lo2分别映射到了PCI 空间的从0,64M,128M开始的地址。另外设备进行DMA时,还要提供一种机制将PCI地址转换成CPU地址。这是通过设置Base Address Register。Bonito中一共有三个这样的寄存器pcibas0-2。Pcibas0,pcibase1都可以映射多达256M的空间。具体映射的大小还取决于pcimembasecfg的设置。Pcibase2是映射Bonito的内部寄存器,映射区间为64k大小。寄存器pcimembasecfg在start.S中设置。我们先看它各个域的含义。Pcimembasecfg寄存器中的各个域各个域的含义解释如下:a) Io:说明示映射到IO空间还是内存空间。IO=0,则是映射到内存空间,IO=1,则映射的是IO空间。b) Cached:如果设置成则使用IOBC,这样可以提高性能c) Trans/mask各5位。用于决定pci地址的27-23位。一个pci地址,先要拿掉高三位,然后mask取反后和27-23位相与,再或上trans。在start.S中,pcimembasecfg的io位都为0,cached为都为1,因此pcibase寄存器映射的是内存空间,并且启用高速缓存。对于pcibase1,它的trans=00000b,mask=00000b,这样pcibase0映射的空间是256M,而pcibase0,它的trans=00000b,mask=11111b,这样pcibase0映射的空间是8M,以节省PCI空间。现在再来看上面给PCIBASE寄存器赋值的三个语句。PCIBASE0被赋值为PCI_LOCAL_MEM_PCI_BASE(被定义为0x8000.0000),PCIBASE1被赋值PCI_LOCAL_MEM_ISA_BASE(定义为0x00800000)。这样当PCI设备访问地址在0x8000.0000-0x8FFF.FFFF时这个地址会先减掉0x80000000变成要访问的内存地址。如果设备访问地址在0x0080.0000-0x008F.FFFF,经过地址转换后,会变成内存的低8M地址。PCIBASE2被赋值为PCI_LOCAL_MEM_PCI_BASE + 0x10000000(值为0x9000.0000)。因此根据pci地址值,能正确的决定要访问的空间。完成基本的地址映射后,就是初始化pci设备了:这包括设备的搜索和资源的分配。具体的工作在_pci_scan_dev和_setup_pcibuses完成的。_pci_scan_dev在_pci_businit中调用。下面是它的调用方式。for(i = 0, pb = _pci_head; i next) /_pci_scan_dev(pb, i, 0, init);_pci_scan_dev(pb, i, 8, init);/from 8+11, hu mingchang前面已经说过_pci_head是指向北桥的。Pci_roots在初始化北桥后被置成1,因此_pci_scan_dev在_pci_businit中只调用一次。再来看_pci_scan_devstatic void_pci_scan_dev(struct pci_device *dev, int bus, int device, int initialise) for(; device 19; device+) /to 19+11, hu mingchang _pci_query_dev (dev, bus, device, initialise);因此主要的函数就是_pci_query_dev。为了解释这个函数,先说一下PCI设备的相关知识。每个PCI设备都有一个256字节的配置头。这个配置头在任何时候都是可以被访问的。配置头的前16个字节对所有设备来说都是一样的。PCI设备配置头的前16个字节Vendor ID:厂家标识,有标准组织分配。Device ID:设备标识,由厂家自己分配。Class code: 设备类别,class code=0x060400表示pci桥。Header Type:定义了配置头中其他部分的内容。有些PCI设备是单功能的,还有些设备是多功能的。如果Header Type的bit7=1则表示该设备是多功能设备,否则是单功能设备。如果是普通pci设备则bit6-0=00,如果是pci桥则bit6-0=01;前面说过,CPU通过访问物理地址0x1fe8.0000 可以访问PCI设备的配置空间。一共有两种配置周期:Type 0和Type 1。配置周期的地址信息有特殊的格式。下面表示了Type0 和Type1配置周期的地址格式。配置周期的地址为了读写设备的配置头,程序还需事先设置pcimap_cfg寄存器的值。下面是它的格式: Pcimap_cfg的格式Type1指示配置周期的类别。AD16UP是高16位地址。结果是当CPU读写物理地址0x1FE8.0000到0x1FE.FFFC的区间时,在PCI地址总线会出现如下的地址;有了上述知识,再来看_pci_conf_readn;这个函数的作用就是读设备的配置头。虽然很简单,但是它在_pci_query_dev等几个主要的函数里都要用到。pcireg_t _pci_conf_readn(pcitag_t tag, int reg, int width) u_int32_t addr, type; pcireg_t data; int bus, device, function; if (reg & (width-1) | reg = 0x100) if (_pciverbose = 1) _pci_tagprintf (tag, _pci_conf_read: bad reg 0x%xn, reg);return 0; _pci_break_tag (tag, &bus, &device, &function); if (bus = 0) /* Type 0 configuration on onboard PCI bus */if (device 20 | function 7) return 0;/* device out of range */addr = (1 (device+11) | (function 255 | device 31 | function 7) return 0;/* device out of range */addr = (bus 16) | (device 11) | (function 16) | type;data = *(volatile pcireg_t *) PHYS_TO_UNCACHED (BONITO_PCICFG_BASE | (addr & 0xfffc); if (BONITO_PCICMD & PCI_STATUS_MASTER_ABORT) BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT;#if 0if (_pciverbose = 1) _pci_tagprintf (tag, _pci_conf_read: reg=%x master abortn, reg);#endifreturn 0; if (BONITO_PCICMD & PCI_STATUS_MASTER_TARGET_ABORT) BONITO_PCICMD |= PCI_STATUS_MASTER_TARGET_ABORT;if (_pciverbose = 1) _pci_tagprintf (tag, _pci_conf_read: target abortn);return 0; return data;可以看到该函数首先从参数tag中分离出bus no,device no和function no,然后根据总线号决定配置周期的类型,形成总线的高16位地址写入pcimap_cfg寄存器。最后就可以访问设配的配置块了。由于访问设备可能会有各种错误,这里主要是master abort和target abort,因此读前要清掉错误信息,读之后还要检查是否出错。另外,_pci_conf_write是用来设置pci配置头部的,它的过程和_pci_conf_read相类似。这里就不多说了。_pci_query_dev。static void_pci_query_dev (struct pci_device *dev, int bus, int device, int initialise)pcitag_t tag;pcireg_t id;pcireg_t misc;tag = _pci_make_tag(bus, device, 0);if (!_pci_canscan (tag)return;if (_pciverbose = 2)_pci_bdfprintf (bus, device, -1, probe.);/*读取pci设备的Vendor ID和Device ID。如果放回0或者全1,则说明插槽中没有设备*/id = _pci_conf_read(tag, PCI_ID_REG);if (_pciverbose = 2) PRINTF (completedn);if (id = 0 | id = 0xffffffff) return;/*现在确定找到一个设备了,读取它的Header Type,如果Header Type的bit7 *=1,则说明是多功能设备(功能位有3位,最多有8个功能)。*/ misc = _pci_conf_read(tag, PCI_BHLC_REG); if (PCI_HDRTYPE_MULTIFN(misc) int function;for (function = 0; function secbus)12) 分配一个pci_bus 的数据结构,由pd-bridge.secbus指向它。初始化这个数据结构。初始化的方法和_pci_hwinit中类似。13) 递归调用_pci_scan_dev,搜集该pci桥所有设备的资源请求信息(io空间大小,memory空间大小)。每个pci设备的IO请求信息和mem请求信息都有一个_pci_win来表示。从_pci_scan_dev返回后,所有子设备IO资源请求都链入了pd-bridge.iospace指向的有序单链表。所有子设备的Mem资源请求信息都联入了pd-bridge.memspace指向的有序单链表。14) 遍历iospace链表汇总所有的IO请求形成一个pci_win结构。遍历memspace链表汇总所有的memory请求也形成一个pci_win结构。将这两个结构插入当前pci桥的父设备的iospace和memspace链表。自此,当前pci桥及他的所有子设备的信息都已经搜集完毕。15) 如果设备是IDE存储设备并且ISA的IO空间可用则不需要分配资源。函数_pci_query_dev_func返回。否则往下执行。16) 现在确定设备是一个普通PCI设备。在PCI设备的配置头中从偏移地址0x10到0x24是6个基地址寄存器。他们代表了设备的IO/Memory资源请求信息。具体是IO请求还是Memory请求取决于寄存器德最低位。0x30处的寄存器代表了设备的ROM空间请求信息。确定地址空间范围的方法是向基地址寄存器中写入全1,然后读出来,无关的位会返回0,有用的位会返回1。比如基地址寄存器返回的值是0xFFF00000.则说明所需要的空间是1M。 内存基地址Bit0=0表示是内存基地址,bit3是否预取bit2-1=00:表示32位地址空间01: 应在1M以下空间分配10: 表示64位地址空间11: 保留IO基地址扩展Rom基地址寄存器Bit0是地址译码使能位设置好资源请求信息的pci_win结构并链入父设备PCI桥的memspace和iospace链表后,_pci_query_dev_func就结束返回到_pci_query_dev,最后返回到_pci_businit()。至此PCI设备的信息搜集完毕。现在内存中存在如下数据结构 Pci设备链表_pci_head,节点类型是pci_device。链表中第一个设备是北桥Bonito。 Pci总线链表_pci_bushead,节点类型是pci_bus。第一个节点是PCIbus0。 每个pci桥的子设备形成一个链表。可以通过pci桥的pci_device的bridge成员的child指针访问这个链表。每个pci设备的pci_device的parent指针指向父设备pci桥。 每个pci桥的对应两个资源请求链表:memspace和iospace。链表中每个节点是桥的子设备memory请求和IO请求。 下一步就是真正的为设备分配资源。这_setup_pcibuses()完成的。_setup_pcibuses()static void_setup_pcibuses(int initialise) struct pci_bus *pb; struct pci_device *pd; unsigned int def_ltim, max_ltim; int i; SBD_DISPLAY (PCIS, CHKPNT_PCIS); for(pb = _pci_bushead; pb != NULL; pb = pb-next) if (pb-ndev = 0) return; if (initialise) /* convert largest minimum grant time to cycle count */ /*XXX 66/33 Mhz */ max_ltim = pb-min_gnt * 33 / 4; /* now see how much bandwidth is left to distribute */ if (pb-bandwidth bus, -1, -1, WARN: total bandwidth exceededn); def_ltim = 1; else /* calculate a fair share for each device */ def_ltim = pb-bandwidth / pb-ndev; if (def_ltim pb-max_lat) /* would exceed critical time for some device */ def_ltim = pb-max_lat; /* convert to cycle count */ def_ltim = def_ltim * 33 / 4; /* most devices dont implement bottom three bits */ def_ltim = (def_ltim + 7) & 7; max_ltim = (max_ltim + 7) & 7; pb-def_ltim = MIN (def_ltim, 255); pb-max_ltim = MIN (MAX (max_ltim, def_ltim), 255); SBD_DISPLAY (PCIR, CHKPNT_PCIR); _pci_hwreinit (); /* setup the individual device windows */ SBD_DISPLAY (PCIW, CHKPNT_PCIW); for(i = 0, pd = _pci_head; i next) _pci_setup_windows (pd); 该函数前面部分主要检查总线所接设备的带宽是否超过总线允许带宽(pb-bandwidth是总线允许带宽剪掉它所连设备消耗后的剩余带宽)。至于min_gnt,max_lat前面已经提过,是与设备总线周期和访问总线频度相关的参数。函数中最主要的部分时后面的循环,它负责为总线上的所有设备分配IO和memory空间。static void_pci_setup_
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025榆林能源集团有限公司招聘工作人员(473人)笔试参考题库附带答案详解
- 2025广东清远市广佛产业园区运营管理有限公司招聘2人笔试参考题库附带答案详解
- 2025年湖南高速养护工程有限公司第二批招聘46人笔试参考题库附带答案详解
- 2025年江苏东信人力资源有限公司招聘笔试参考题库附带答案详解
- 2025年国网浙江省电力有限公司高校毕业生招聘(第二批)笔试参考题库附带答案详解
- 2025年合肥市浩悦环境工程有限公司招聘5人笔试参考题库附带答案详解
- 2025年中国东方食品投资有限公司校园招聘若干人笔试参考题库附带答案详解
- 2025山东烟台市蓬莱区城市建设投资集团有限公司招聘22人笔试参考题库附带答案详解
- 2025内蒙古土地资源收储投资(集团)招聘94名专业人员(第十一批)笔试参考题库附带答案详解
- 地铁培训安全知识课件
- 结肠癌肝转移护理查房课件
- 口腔预防保健课件
- 手机行业售后管理制度
- 肇庆端州正西社区评估报告
- 朝天椒栽培技术课件
- 科研伦理与学术规范-课后作业答案
- -首次执行衔接问题-行政
- 斯蒂芬金英语介绍
- 秋天的雨 省赛获奖
- JJF 1015-2014计量器具型式评价通用规范
- GB/T 8332-2008泡沫塑料燃烧性能试验方法水平燃烧法
评论
0/150
提交评论