Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15537304
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

PCI

分类: 嵌入式

2009-09-03 21:08:07


Peripheral Component Interconnect (PCI), as its name implies is a standard that describes how to connect the peripheral components of a system together in a structured and controlled way. The standard describes the way that the system components are electrically connected and the way that they should behave. This chapter looks at how the Linux kernel initializes the system's PCI buses and devices.


Figure 6.1: Example PCI Based System

Figure  is a logical diagram of an example PCI based system. The PCI buses and PCI-PCI bridges are the glue connecting the system components together; the CPU is connected to PCI bus 0, the primary PCI bus as is the video device. A special PCI device, a PCI-PCI bridge connects the primary bus to the secondary PCI bus, PCI bus 1. In the jargon of the PCI specification, PCI bus 1 is described as being downstream of the PCI-PCI bridge and PCI bus 0 is up-stream of the bridge. Connected to the secondary PCI bus are the SCSI and ethernet devices for the system. Physically the bridge, secondary PCI bus and two devices would all be contained on the same combination PCI card. The PCI-ISA bridge in the system supports older, legacy ISA devices and the diagram shows a super I/O controller chip, which controls the keyboard, mouse and floppy.

PCI Address Spaces

The CPU and the PCI devices need to access memory that is shared between them. This memory is used by device drivers to control the PCI devices and to pass information between them. Typically the shared memory contains control and status registers for the device. These registers are used to control the device and to read its status. For example, the PCI SCSI device driver would read its status register to find out if the SCSI device was ready to write a block of information to the SCSI disk. Or it might write to the control register to start the device running after it has been turned on.

The CPU's system memory could be used for this shared memory but if it were, then every time a PCI device accessed memory, the CPU would have to stall, waiting for the PCI device to finish. Access to memory is generally limited to one system component at a time. This would slow the system down. It is also not a good idea to allow the system's peripheral devices to access main memory in an uncontrolled way. This would be very dangerous; a rogue device could make the system very unstable.

Peripheral devices have their own memory spaces. The CPU can access these spaces but access by the devices into the system's memory is very strictly controlled using DMA (Direct Memory Access) channels. ISA devices have access to two address spaces, ISA I/O (Input/Output) and ISA memory. PCI has three; PCI I/O, PCI Memory and PCI Configuration space. All of these address spaces are also accessible by the CPU with the the PCI I/O and PCI Memory address spaces being used by the device drivers and the PCI Configuration space being used by the PCI initialization code within the Linux kernel.

The Alpha AXP processor does not have natural access to addresses spaces other than the system address space. It uses support chipsets to access other address spaces such as PCI Configuration space. It uses a sparse address mapping scheme which steals part of the large virtual address space and maps it to the PCI address spaces.

PCI Configuration Headers


Figure 6.2: The PCI Configuration Header

Every PCI device in the system, including the PCI-PCI bridges has a configuration data structure that is somewhere in the PCI configuration address space. The PCI Configuration header allows the system to identify and control the device. Exactly where the header is in the PCI Configuration address space depends on where in the PCI topology that device is. For example, a PCI video card plugged into one PCI slot on the PC motherboard will have its configuration header at one location and if it is plugged into another PCI slot then its header will appear in another location in PCI Configuration memory. This does not matter, for wherever the PCI devices and bridges are the system will find and configure them using the status and configuration registers in their configuration headers.

Typically, systems are designed so that every PCI slot has it's PCI Configuration Header in an offset that is related to its slot on the board. So, for example, the first slot on the board might have its PCI Configuration at offset 0 and the second slot at offset 256 (all headers are the same length, 256 bytes) and so on. A system specific hardware mechanism is defined so that the PCI configuration code can attempt to examine all possible PCI Configuration Headers for a given PCI bus and know which devices are present and which devices are absent simply by trying to read one of the fields in the header (usually the Vendor Identification field) and getting some sort of error. The describes one possible error message as returning 0xFFFFFFFF when attempting to read the Vendor Identification and Device Identification fields for an empty PCI slot.

Figure  shows the layout of the 256 byte PCI configuration header. It contains the following fields:

Vendor Identification
A unique number describing the originator of the PCI device. Digital's PCI Vendor Identification is 0x1011 and Intel's is 0x8086.
Device Identification
A unique number describing the device itself. For example, Digital's 21141 fast ethernet device has a device identification of 0x0009.
Status
This field gives the status of the device with the meaning of the bits of this field set by the standard. .
Command
By writing to this field the system controls the device, for example allowing the device to access PCI I/O memory,
Class Code
This identifies the type of device that this is. There are standard classes for every sort of device; video, SCSI and so on. The class code for SCSI is 0x0100.
Base Address Registers
These registers are used to determine and allocate the type, amount and location of PCI I/O and PCI memory space that the device can use.
Interrupt Pin
Four of the physical pins on the PCI card carry interrupts from the card to the PCI bus. The standard labels these as A, B, C and D. The Interrupt Pin field describes which of these pins this PCI device uses. Generally it is hardwired for a pariticular device. That is, every time the system boots, the device uses the same interrupt pin. This information allows the interrupt handling subsystem to manage interrupts from this device,
Interrupt Line  引发此次中断的中断源-会有很多种中断源
The Interrupt Line field of the device's PCI Configuration header is used to pass an interrupt handle between the PCI initialisation code, the device's driver and Linux's interrupt handling subsystem. The number written there is meaningless to the the device driver but it allows the interrupt handler to correctly route an interrupt from the PCI device to the correct device driver's interrupt handling code within the Linux operating system. See Chapter  on page  for details on how Linux handles interrupts.

=================================

PCI based systems are much more dynamic than ISA based systems. The interrupt pin that an ISA device uses is often set using jumpers on the hardware device and fixed in the device driver. On the other hand, PCI devices have their interrupts allocated by the PCI BIOS or the PCI subsystem as PCI is initialized when the system boots. Each PCI device may use one of four interrupt pins, A, B, C or D. This was fixed when the device was built and most devices default to interrupt on pin A. The PCI interrupt lines A, B, C and D for each PCI slot are routed to the interrupt controller. So, Pin A from PCI slot 4 might be routed to pin 6 of the interrupt controller, pin B of PCI slot 4 to pin 7 of the interrupt controller and so on.

How the PCI interrupts are routed is entirely system specific and there must be some set up code which understands this PCI interrupt routing topology. On Intel based PCs this is the system BIOS code that runs at boot time but for system's without BIOS (for example Alpha AXP based systems) the Linux kernel does this setup.

The PCI set up code writes the pin number of the interrupt controller into the PCI configuration header for each device. It determines the interrupt pin (or IRQ) number using its knowledge of the PCI interrupt routing topology together with the devices PCI slot number and which PCI interrupt pin that it is using. The interrupt pin that a device uses is fixed and is kept in a field in the PCI configuration header for this device. It writes this information into the interrupt line field that is reserved for this purpose. When the device driver runs, it reads this information and uses it to request control of the interrupt from the Linux kernel.

There may be many PCI interrupt sources in the system, for example when PCI-PCI bridges are used. The number of interrupt sources may exceed the number of pins on the system's programmable interrupt controllers. In this case, PCI devices may share interrupts, one pin on the interrupt controller taking interrupts from more than one PCI device. Linux supports this by allowing the first requestor of an interrupt source declare whether it may be shared. Sharing interrupts results in several irqaction data structures being pointed at by one entry in the irq_action vector vector. When a shared interrupt happens, Linux will call all of the interrupt handlers for that source. Any device driver that can share interrupts (which should be all PCI device drivers) must be prepared to have its interrupt handler called when there is no interrupt to be serviced.

=================================

PCI I/O and PCI Memory Addresses

These two address spaces are used by the devices to communicate with their device drivers running in the Linux kernel on the CPU. For example, the DECchip 21141 fast ethernet device maps its internal registers into PCI I/O space. Its Linux device driver then reads and writes those registers to control the device. Video drivers typically use large amounts of PCI memory space to contain video information.

Until the PCI system has been set up and the device's access to these address spaces has been turned on using the Command field in the PCI Configuration header, nothing can access them. It should be noted that only the PCI configuration code reads and writes PCI configuration addresses; the Linux device drivers only read and write PCI I/O and PCI memory addresses.

PCI-ISA Bridges

These bridges support legacy ISA devices by translating PCI I/O and PCI Memory space accesses into ISA I/O and ISA Memory accesses. A lot of systems now sold contain several ISA bus slots and several PCI bus slots. Over time the need for this backwards compatibility will dwindle and PCI only systems will be sold. Where in the ISA address spaces (I/O and Memory) the ISA devices of the system have their registers was fixed in the dim mists of time by the early Intel 8080 based PCs. Even a $5000 Alpha AXP based computer systems will have its ISA floppy controller at the same place in ISA I/O space as the first IBM PC. The PCI specification copes with this by reserving the lower regions of the PCI I/O and PCI Memory address spaces for use by the ISA peripherals in the system and using a single PCI-ISA bridge to translate any PCI memory accesses to those regions into ISA accesses.

PCI-PCI Bridges

PCI-PCI bridges are special PCI devices that glue the PCI buses of the system together. Simple systems have a single PCI bus but there is an electrical limit on the number of PCI devices that a single PCI bus can support. Using PCI-PCI bridges to add more PCI buses allows the system to support many more PCI devices. This is particularly important for a high performance server. Of course, Linux fully supports the use of PCI-PCI bridges.

PCI-PCI Bridges: PCI I/O and PCI Memory Windows

PCI-PCI bridges only pass a subset of PCI I/O and PCI memory read and write requests downstream. For example, in Figure  on page , the PCI-PCI bridge will only pass read and write addresses from PCI bus 0 to PCI bus 1 if they are for PCI I/O or PCI memory addresses owned by either the SCSI or ethernet device; all other PCI I/O and memory addresses are ignored. This filtering stops addresses propogating needlessly throughout the system.[有效的阻止了bus0总线上发往非bus1的其他设备(比如6-1图中的Video和PCI-ISA Bridge上的操作指令)i/o或者memory的读写操作指令luther.gliethttp] To do this, the PCI-PCI bridges must be programmed with a base and limit for PCI I/O and PCI Memory space access that they have to pass from their primary bus onto their secondary bus. Once the PCI-PCI Bridges in a system have been configured then so long as the Linux device drivers only access PCI I/O and PCI Memory space via these windows, the PCI-PCI Bridges are invisible. This is an important feature that makes life easier for Linux PCI device driver writers. However, it also makes PCI-PCI bridges somewhat tricky for Linux to configure as we shall see later on.

PCI-PCI Bridges: PCI Configuration Cycles and PCI Bus Numbering


Figure 6.3: Type 0 PCI Configuration Cycle


Figure 6.4: Type 1 PCI Configuration Cycle

So that the CPU's PCI initialization code can address devices that are not on the main PCI bus, there has to be a mechanism that allows bridges to decide whether or not to pass Configuration cycles from their primary interface to their secondary interface. A cycle is just an address as it appears on the PCI bus. The PCI specification defines two formats for the PCI Configuration addresses; Type 0 and Type 1; these are shown in Figure  and Figure  respectively. Type 0 PCI Configuration cycles do not contain a bus number and these are interpretted by all devices as being for PCI configuration addresses on this PCI bus. Bits 31:11 of the Type 0 configuraration cycles are treated as the device select field. One way to design a system is to have each bit select a different device. In this case bit 11 would select the PCI device in slot 0, bit 12 would select the PCI device in slot 1 and so on. Another way is to write the device's slot number directly into bits 31:11. Which mechanism is used in a system depends on the system's PCI memory controller.

Type 1 PCI Configuration cycles contain a PCI bus number and this type of configuration cycle is ignored by all PCI devices except the PCI-PCI bridges. All of the PCI-PCI Bridges seeing Type 1 configuration cycles may choose to pass them to the PCI buses downstream of themselves. Whether the PCI-PCI Bridge ignores the Type 1 configuration cycle or passes it onto the downstream PCI bus depends on how the PCI-PCI Bridge has been configured. Every PCI-PCI bridge has a primary bus interface number and a secondary bus interface number. The primary bus interface being the one nearest the CPU and the secondary bus interface being the one furthest away. Each PCI-PCI Bridge also has a subordinate bus number and this is the maximum bus number of all the PCI buses that are bridged beyond the secondary bus interface. Or to put it another way, the subordinate bus number is the highest numbered PCI bus downstream of the PCI-PCI bridge. When the PCI-PCI bridge sees a Type 1 PCI configuration cycle it does one of the following things:

  • Ignore it if the bus number specified is not in between the bridge's secondary bus number and subordinate bus number (inclusive),

  • Convert it to a Type 0 configuration command if the bus number specified matches the secondary bus number of the bridge,

  • Pass it onto the secondary bus interface unchanged if the bus number specified is greater than the secondary bus number and less than or equal to the subordinate bus number.

So, if we want to address Device 1 on bus 3 of the topology Figure  on page  we must generate a Type 1 Configuration command from the CPU. Bridge1 passes this unchanged onto Bus 1. Bridge2 ignores it but Bridge3 converts it into a Type 0 Configuration command and sends it out on Bus 3 where Device 1 responds to it.

It is up to each individual operating system to allocate bus numbers during PCI configuration but whatever the numbering scheme used the following statement must be true for all of the PCI-PCI bridges in the system:

``All PCI buses located behind a PCI-PCI bridge must reside between the seondary bus number and the subordinate bus number (inclusive).''

If this rule is broken then the PCI-PCI Bridges will not pass and translate Type 1 PCI configuration cycles correctly and the system will fail to find and initialise the PCI devices in the system. To achieve this numbering scheme, Linux configures these special devices in a particular order. Section  on page  describes Linux's PCI bridge and bus numbering scheme in detail together with a worked example.

Linux PCI Initialization

The PCI initialisation code in Linux is broken into three logical parts:

PCI Device Driver
This pseudo-device driver searches the PCI system starting at Bus 0 and locates all PCI devices and bridges in the system. It builds a linked list of data structures describing the topology of the system. Additionally, it numbers all of the bridges that it finds.

PCI BIOS
This software layer provides the services described in bib-pci-bios-specification. Even though Alpha AXP does not have BIOS services, there is equivalent code in the Linux kernel providing the same functions,

PCI Fixup
System specific fixup code tidies up the system specific loose ends of PCI initialization.

The Linux Kernel PCI Data Structures


Figure 6.5: Linux Kernel PCI Data Structures

As the Linux kernel initialises the PCI system it builds data structures mirroring the real PCI topology of the system. Figure  shows the relationships of the data structures that it would build for the example PCI system in Figure  on page .

Each PCI device (including the PCI-PCI Bridges) is described by a pci_dev data structure. Each PCI bus is described by a pci_bus data structure. The result is a tree structure of PCI buses each of which has a number of child PCI devices attached to it. As a PCI bus can only be reached using a PCI-PCI Bridge (except the primary PCI bus, bus 0), each pci_bus contains a pointer to the PCI device (the PCI-PCI Bridge) that it is accessed through. That PCI device is a child of the the PCI Bus's parent PCI bus.

Not shown in the Figure  is a pointer to all of the PCI devices in the system, pci_devices. All of the PCI devices in the system have their pci_dev data structures queued onto this queue.. This queue is used by the Linux kernel to quickly find all of the PCI devices in the system.

The PCI Device Driver

The PCI device driver is not really a device driver at all but a function of the operating system called at system initialisation time. The PCI initialisation code must scan all of the PCI buses in the system looking for all PCI devices in the system (including PCI-PCI bridge devices).

It uses the PCI BIOS code to find out if every possible slot in the current PCI bus that it is scanning is occupied. If the PCI slot is occupied, it builds a pci_dev data structure describing the device and links into the list of known PCI devices (pointed at by pci_devices).

The PCI initialisation code starts by scanning PCI Bus 0. It tries to read the Vendor Identification and Device Identification fields for every possible PCI device in every possible PCI slot. When it finds an occupied slot it builds a pci_dev data structure describing the device. All of the pci_dev data structures built by the PCI initialisation code (including all of the PCI-PCI Bridges) are linked into a singly linked list; pci_devices.

If the PCI device that was found was a PCI-PCI bridge then a pci_bus data structure is built and linked into the tree of pci_bus and pci_dev data structures pointed at by pci_root. The PCI initialisation code can tell if the PCI device is a PCI-PCI Bridge because it has a class code of 0x060400. The Linux kernel then configures the PCI bus on the other (downstream) side of the PCI-PCI Bridge that it has just found. If more PCI-PCI Bridges are found then these are also configured. This process is known as a depthwise algorithm; the system's PCI topology is fully mapped depthwise before searching breadthwise. Looking at Figure  on page , Linux would configure PCI Bus 1 with its Ethernet and SCSI device before it configured the video device on PCI Bus 0.

As Linux searches for downstream PCI buses it must also configure the intervening PCI-PCI bridges' secondary and subordinate bus numbers. This is described in detail in Section  below.

Configuring PCI-PCI Bridges - Assigning PCI Bus Numbers


Figure 6.6: Configuring a PCI System: Part 1

For PCI-PCI bridges to pass PCI I/O, PCI Memory or PCI Configuration address space reads and writes across them, they need to know the following:

Primary Bus Number
The bus number immediately upstream of the PCI-PCI Bridge,
Secondary Bus Number
The bus number immediately downstream of the PCI-PCI Bridge,
Subordinate Bus Number
The highest bus number of all of the buses that can be reached downstream of the bridge.
PCI I/O and PCI Memory Windows
The window base and size for PCI I/O address space and PCI Memory address space for all addresses downstream of the PCI-PCI Bridge.

The problem is that at the time when you wish to configure any given PCI-PCI bridge you do not know the subordinate bus number for that bridge. You do not know if there are further PCI-PCI bridges downstream and if you did, you do not know what numbers will be assigned to them. The answer is to use a depthwise recursive algorithm and scan each bus for any PCI-PCI bridges assigning them numbers as they are found. As each PCI-PCI bridge is found and its secondary bus numbered, assign it a temporary subordinate number of 0xFF and scan and assign numbers to all PCI-PCI bridges downstream of it. This all seems complicated but the worked example below makes this process clearer.

PCI-PCI Bridge Numbering: Step 1
Taking the topology in Figure , the first bridge the scan would find is Bridge1. The PCI bus downstream of Bridge1 would be numbered as 1 and Bridge1 assigned a secondary bus number of 1 and a temporary subordinate bus number of 0xFF. This means that all Type 1 PCI Configuration addresses specifying a PCI bus number of 1 or higher would be passed across Bridge1 and onto PCI Bus 1. They would be translated into Type 0 Configuration cycles if they have a bus number of 1 but left untranslated for all other bus numbers. This is exactly what the Linux PCI initialisation code needs to do in order to go and scan PCI Bus 1.


Figure 6.7: Configuring a PCI System: Part 2

PCI-PCI Bridge Numbering: Step 2
Linux uses a depthwise algorithm and so the initialisation code goes on to scan PCI Bus 1. Here it finds PCI-PCI Bridge2. There are no further PCI-PCI bridges beyond PCI-PCI Bridge2, so it is assigned a subordinate bus number of 2 which matches the number assigned to its secondary interface. Figure  shows how the buses and PCI-PCI bridges are numbered at this point.


Figure 6.8: Configuring a PCI System: Part 3

PCI-PCI Bridge Numbering: Step 3
The PCI initialisation code returns to scanning PCI Bus 1 and finds another PCI-PCI bridge, Bridge3. It is assigned 1 as its primary bus interface number, 3 as its secondary bus interface number and 0xFF as its subordinate bus number. Figure  on page  shows how the system is configured now. Type 1 PCI configuration cycles with a bus number of 1, 2 or 3 wil be correctly delivered to the appropriate PCI buses.


Figure 6.9: Configuring a PCI System: Part 4

PCI-PCI Bridge Numbering: Step 4
Linux starts scanning PCI Bus 3, downstream of PCI-PCI Bridge3. PCI Bus 3 has another PCI-PCI bridge (Bridge4) on it, it is assigned 3 as its primary bus number and 4 as its secondary bus number. It is the last bridge on this branch and so it is assigned a subordinate bus interface number of 4. The initialisation code returns to PCI-PCI Bridge3 and assigns it a subordinate bus number of 4. Finally, the PCI initialisation code can assign 4 as the subordinate bus number for PCI-PCI Bridge1. Figure  on page  shows the final bus numbers.
这里可以看到
bridge1包含从secondary号开始到subordinate号结束的1-4共4个bridge桥
bridge2包含从2-2一共就它哥一个的bridge桥
bridge3包含从3-4一共2个bridge桥
bridge4包含从4-4一共就它哥一个的bridge桥[luther.gliethttp]

PCI BIOS Functions

The PCI BIOS functions are a series of standard routines which are common across all platforms. For example, they are the same for both Intel and Alpha AXP based systems. They allow the CPU controlled access to all of the PCI address spaces.

Only Linux kernel code and device drivers may use them.

PCI Fixup

The PCI fixup code for Alpha AXP does rather more than that for Intel (which basically does nothing).

For Intel based systems the system BIOS, which ran at boot time, has already fully configured the PCI system. This leaves Linux with little to do other than map that configuration. For non-Intel based systems further configuration needs to happen to:

  • Allocate PCI I/O and PCI Memory space to each device,
  • Configure the PCI I/O and PCI Memory address windows for each PCI-PCI bridge in the system,
  • Generate Interrupt Line values for the devices; these control interrupt handling for the device.

The next subsections describe how that code works.

Finding Out How Much PCI I/O and PCI Memory Space a Device Needs

Each PCI device found is queried to find out how much PCI I/O and PCI Memory address space it requires. To do this, each Base Address Register has all 1's written to it and then read. The device will return 0's in the don't-care address bits, effectively specifying the address space required.


Figure 6.10: PCI Configuration Header: Base Address Registers

There are two basic types of Base Address Register, the first indicates within which address space the devices registers must reside; either PCI I/O or PCI Memory space. This is indicated by Bit 0 of the register. Figure  shows the two forms of the Base Address Register for PCI Memory and for PCI I/O.

To find out just how much of each address space a given Base Address Register is requesting, you write all 1s (向该寄存器写全1到,如果是32位系统就是0xffffffff) into the register and then read it back. The device will specify zeros in the don't care address bits, effectively specifying the address space required. This design implies that all address spaces used are a power of two and are naturally aligned.[地址值为2^的幂,同时地址都已经按2^的幂实现对齐.luther.gliethttp]如下一篇文章包含了对地址使用上的简短叙述包含一些细致的PCI配置加载流程--PCI卡的WDM驱动开发笔记

For example when you initialize the DECChip 21142 PCI Fast Ethernet device, it tells you that it needs 0x100 bytes of space of either PCI I/O or PCI Memory. The initialization code allocates it space. The moment that it allocates space, the 21142's control and status registers can be seen at those addresses.

Allocating PCI I/O and PCI Memory to PCI-PCI Bridges and Devices

Like all memory the PCI I/O and PCI memory spaces are finite, and to some extent scarce. The PCI Fixup code for non-Intel systems (and the BIOS code for Intel systems) has to allocate each device the amount of memory that it is requesting in an efficient manner. Both PCI I/O and PCI Memory must be allocated to a device in a naturally aligned way. For example, if a device asks for 0xB0 of PCI I/O space then it must be aligned on an address that is a multiple of 0xB0. In addition to this, the PCI I/O and PCI Memory bases for any given bridge must be aligned on 4K and on 1Mbyte boundaries respectively. Given that the address spaces for downstream devices must lie within all of the upstream PCI-PCI Bridge's memory ranges for any given device, it is a somewhat difficult problem to allocate space efficiently.

The algorithm that Linux uses relies on each device described by the bus/device tree built by the PCI Device Driver being allocated address space in ascending PCI I/O memory order. Again a recursive algorithm is used to walk the pci_bus and pci_dev data structures built by the PCI initialisation code. Starting at the root PCI bus (pointed at by pci_root) the BIOS fixup code:

  • Aligns the current global PCI I/O and Memory bases on 4K and 1 Mbyte boundaries respectively,

  • For every device on the current bus (in ascending PCI I/O memory needs),
    • allocates it space in PCI I/O and/or PCI Memory,

    • moves on the global PCI I/O and Memory bases by the appropriate amounts,

    • enables the device's use of PCI I/O and PCI Memory,

  • Allocates space recursively to all of the buses downstream of the current bus. Note that this will change the global PCI I/O and Memory bases,

  • Aligns the current global PCI I/O and Memory bases on 4K and 1 Mbyte boundaries respectively and in doing so figure out the size and base of PCI I/O and PCI Memory windows required by the current PCI-PCI bridge,

  • Programs the PCI-PCI bridge that links to this bus with its PCI I/O and PCI Memory bases and limits,

  • Turns on bridging of PCI I/O and PCI Memory accesses in the PCI-PCI Bridge. This means that if any PCI I/O or PCI Memory addresses seen on the Bridge's primary PCI bus that are within its PCI I/O and PCI Memory address windows will be bridged onto its secondary PCI bus.

Taking the PCI system in Figure  on page  as our example the PCI Fixup code would set up the system in the following way:

Align the PCI bases
PCI I/O is 0x4000 and PCI Memory is 0x100000. This allows the PCI-ISA bridges to translate all addresses below these into ISA address cycles,
The Video Device
This is asking for 0x200000 of PCI Memory and so we allocate it that amount starting at the current PCI Memory base of 0x200000 as it has to be naturally aligned to the size requested. The PCI Memory base is moved to 0x400000 and the PCI I/O base remains at 0x4000.
The PCI-PCI Bridge
We now cross the PCI-PCI Bridge and allocate PCI memory there, note that we do not need to align the bases as they are already correctly aligned:
The Ethernet Device
This is asking for 0xB0 bytes of both PCI I/O and PCI Memory space. It gets allocated PCI I/O at 0x4000 and PCI Memory at 0x400000. The PCI Memory base is moved to 0x4000B0 and the PCI I/O base to 0x40B0.
The SCSI Device
This is asking for 0x1000 PCI Memory and so it is allocated it at 0x401000 after it has been naturally aligned. The PCI I/O base is still 0x40B0 and the PCI Memory base has been moved to 0x402000.
The PCI-PCI Bridge's PCI I/O and Memory Windows
We now return to the bridge and set its PCI I/O window at between 0x4000 and 0x40B0 and it's PCI Memory window at between 0x400000 and 0x402000. This means that the PCI-PCI Bridge will ignore the PCI Memory accesses for the video device and pass them on if they are for the ethernet or SCSI devices.


Footnotes:

For example?


File translated from TEX by , version 1.0.
, , ,
© 1996-1999 David A Rusling

, ,

中文翻译:

第六章 PCI


外围设备互连(PCI)是一种将系统中外部设备以结构化与可控制方式连接到起来的总线标准,包括系统部件连接的电气特性及行为。本章将详细讨论Linux核心对系统中的PCI总线与设备的初始化过程。


图6.1 一个基于PCI的系统示意图

图6.1是一个基于PCI的系统示意图。PCI总线和PCI-PCI桥接器在连接系统中设备到上起关键作用,在这个系统中CPU和视频设备 被连到PCI bus 0上,它是系统中的主干PCI总线。而PCI-PCI桥接器这个特殊PCI设备将主干总线PCI bus 0与下级总线PCI bus 1连接到一起。PCI标准术语中,PCI bus 1是PCI-PCI桥接器的downstream而PCI bus 0是此桥接器的up-stream。SCSI和以太网设备通过二级PCI总线连接到这个系统中。而在物理实现上,桥接器和二级PCI总线被集成到一块 PCI卡上。而PCI-ISA桥接器用来支持古老的ISA设备,图中有一个高级I/O控制芯片来控制键盘、鼠标及软盘设备。

PCI地址空间

CPU和PCI设备需要存取在它们之间共享的内存空间。这块内存区域被设备驱动用来控制PCI设备并在CPU与PCI设备之间传递信息。最典型的共享内存包括设备的控制与状态寄存器。这些寄存器用来控制设备并读取其 信息。例如PCI SCSI设备驱动可以通过读取其状态寄存器,找出已准备好将一块数据写入SCSI磁盘的SCSI设备。同时还可以在设备加电后,通过对控制寄存器写入信息来启动设备。

CPU的系统内存可以被用作这种共享内存,但是如果采用这种方式,则每次PCI设备访问此内存块时,CPU将被迫停止工作以等待PCI设备完成此操作。这 种方式将共享内存限制成每次只允许一个系统设备访问。该策略会大大降低系统性能。但如果允许系统外设不受限制地访问主存也不是好办法。它的危险之处在于一 个有恶意行为的设备将使整个系统置于不稳定状态。

外设有其自身的内存空间。CPU可以自由存取此空间,但设备对系统主存的访问将处于DMA(直接内存访问)通道的严格控制下。ISA设备需要存取两个地址空间:ISA I/O(输入输出)和ISA内存。而PCI设备需要访问三种地址空间:PCI I/O、PCI内存和PCI配置空间。CPU则可以访问所有这些地址空间。PCI I/O和 PCI内存由设备驱动程序使用而PCI配置空间被Linux 核心中的PCI初始化代码使用。

Alpha AXP处理器并不能象访问系统地址空间那样随意访问这些地址空间,它只能通过辅助芯片组来存取这些 地址空间,如PCI配置空间。Alpha AXP处理器使用稀疏地址映射策略来从系统巨大的虚拟内存中"窃取"一部分并将其映射到PCI地址空间。

PCI 配置头


图6.2 PCI配置头

系统中每个PCI设备,包括PCI-PCI桥接器在内,都有一个配置数据结构,它通常位于PCI配置地址空间中。PCI配置头允许系统来标 识与控制设备。配置头在PCI配置空间的位置取决于系统中PCI设备的拓扑结构。例如将一个PCI视频卡插入不同的PCI槽,其配置头位置会变化。但对系 统没什么影响,系统将找到每个PCI设备与桥接器并使用它们配置头中的信息来配置其寄存器。

典型的办法是用PCI槽相对主板的位置来决定其PCI配置头在配置空间中的偏移。比如主板中的第一个PCI槽的PCI配置头位于配置空间偏移0处,而第二 个则位于偏移256处(所有PCI配置头长度都相等,为256字节),其它槽可以由此类推。系统还将提供一种硬件相关机制以便PCI设置代码能正确的辨认 出对应PCI总线上所有存在的设备的PCI配置头。通过PCI配置头中的某些域来判断哪些设备存在及哪些设备不存在(这个域叫厂商标志域: Vendor Identification field)。对空PCI槽中这个域的读操作将得到一个值为0xFFFFFFFF的错误信息。

图6.2给出了256字节PCI配置头的结构,它包含以下域:

厂商标识(Vendor Identification)
用来唯一标识PCI设备生产厂家的数值。Digital的PCI厂商标识为0x1011而Intel的为0x8086。
设备标识(Device Identification)
用来唯一标识设备的数值。Digital 21141快速以太设备的设备标识为0x0009。
状态(Status)
此域提供PCI标准定义中此设备的状态信息。
命令(Command)
通过对此域的写可以控制此设备,如允许设备访问PCI I/O内存。
分类代码(Class Code)
此域标识本设备的类型。对于每种类型的视频,SCSI等设备都有标准的分类代码。如SCSI设备分类代码为0x0100。
基地址寄存器(Base Address Registers)
这些寄存器用来决定和分配此设备可以使用的PCI I/O与PCI内存空间的类型,数量及位置。
中断引脚(Interrupt Pin)
PCI卡上的四个物理引脚可以将中断信号从插卡上带到PCI总线上。这四个引脚标准的标记分别为A、B、C及D。中断引脚域描叙此PCI设备使用的引脚 号。通常特定设备都是采用硬连接方式。这也是系统启动时,设备总使用相同中断引脚的原因。中断处理子系统用它来管理来自该设备的中断。
中断连线(Interrupt Line)
本设备配置头中的中断连线域用来在PCI初始化代码、设备驱动以及Linux中断处理子系统间传递中断处理过程。虽然本域中记录的这个数值对于设备驱动毫无意义。但是它可以将中断处理过程从PCI卡上正确路由到Linux操作系统中相应的设备驱动中断处理代码中。在一章中将详细描叙Linux中断处理过程。

PCI I/O和PCI内存地址

这两个地址空间用来实现PCI设备和Linux核心中设备驱动程序之间的通讯。例如DEC21141快速以太网设备的内部寄存器被映射到PIC I/O空间上时,其对应的Linux设备驱动可以通过对这些寄存器的读写来控制此设备。PCI视频卡通常使用大量的PCI内存空间来存储视频信息。

在PCI系统建立并通过用PCI配置头中的命令域来打开这些地址空间前,系统决不允许对它们进行存取。值得注意的是只有PCI配置代码读取和写入PCI配置空间,Linux设备驱动只读写PCI I/O和PCI内存地址。

PCI-ISA 桥接器

这种桥接器通过将PCI I/O和PCI内存空间的存取转换成对ISA I/O和ISA内存的存取来支持古老的ISA设备。市场上许多主板中同时包含几个ISA总线槽和PCI槽。但今后对ISA设备的向后兼容支持将逐渐减弱,最终主板上只会有PCI槽。早期的Intel 8080 PC就将ISA设备的ISA地址空间固定了下来。即使在价值5000美圆的Alpha AXP 系统中其ISA软盘控制器地址也和最早IBM PC上的相同。PCI标准将PCI I/O和PCI内存的低端部分保留给系统中的ISA外设,另外还使用PCI-ISA桥接器实现从PCI内存访问到ISA内存访问的转换。

PCI-PCI 桥接器

PCI-PCI桥接器是一种将系统中所有PCI总线连接起来的特殊PCI设备。在简单系统中只存在一条PCI总线,由于受电气特性的限制,它所连接的 PCI设备个数有限。引入PCI-PCI桥接器后系统可以使用更多的PCI设备。对于高性能服务器这是非常重要的。Linux提供了对PCI-PCI桥接 器的全面支持。

PCI-PCI桥接器:PCI I/O和PCI 内存窗口

PCI-PCI桥接器将PCI I/O和PCI内存读写请求中的一个子集向下传送。例如在图6.1中,如果来自PCI 总线0请求是对SCSI或以太设备所拥有的PCI I/O或PCI内存的读写,则此PCI-PCI桥接器将只需把请求从总线0传递到PCI总线1上;所有其它PCI I/O和内存地址都将被它忽略。这个过滤使得这些地址信息不会在整个系统中扩散。为了实现这点,PCI-PCI桥接器必须编程为有某个PCI I/O及PCI内存基址和上限,只有在这个地址范围内的PCI地址访问才能从主干总线传递到二级总线。一旦系统中的PCI-PCI桥接器被设置成这样,则只要当Linux设备驱动程序通过这个窗口访问PCI I/O和PCI内存空间时,此PCI-PCI桥接器就将变得透明。这样也给Linux PCI设备驱动编写者提供了方便。我们在稍后的讨论中将看到Linux对PCI-PCI桥接器非常巧妙的配置。

PCI-PCI桥接器:PCI配置循环及PCI总线编号方式


图6.3 0类型PCI配置循环


图6.4 1类型PCI配置循环

为了让CPU上运行的PCI初始化代码能访问位于分支PCI总线上的设备,必须为桥接器提供某种机制以便它可以决定是否将配置循环从主干接 口传递到其二级接口。循环是出现在PCI总线上的一个地址。PCI 标准定义了两种PCI配置寻址格式;类型0和类型1;它们分别如图6.3及6.4所示。类型0 PCI配置循环不包含总线序号,同时在此PCI总线上对应于这个PCI配置地址的所有PCI设备都会来对它们进行解释。类型0 配置循环的11 位到31位用来进行PCI设备选择。有种设计方式是让每位代表系统中一个不同的设备。这时11位对应PCI槽0中的PCI设备而12位标识槽1中的设备等 等,如此类推。另外一种方式是直接将设备的槽号写入到位31到11中。系统使用哪种机制依赖于系统PCI内存控制器。

类型1 PCI配置循环包含一个PCI总线序号,同时这种配置循环将被除桥接器外的所有PCI设备所忽略。所有发现类型1 配置循环的PCI-PCI桥接器把它们看到的地址传递到各自的下级PCI总线。至于PCI-PCI桥接器是否忽略类型1 配置循环或将其传递到PCI总线则依赖于PCI-PCI桥接器的配置方式。每个PCI-PCI桥接器都拥有一个主干总线接口序号以及一个二级总线接口序 号。主干总线是那个离CPU最近的PCI总线而二级总线是离它稍远的PCI总线。任何PCI-PCI桥接器还包含一个从属总线序号,这是所有二级总线接口 所桥接的PCI总线中序号最大的那个。或者说这个从属总线序号是PCI-PCI桥接器向下连接中PCI总线的最大序号。当PCI-PCI桥接器看到类型1 PCI配置循环时它将进行如下操作:

  • 如果此总线序号不在桥接器的二级总线序号和从属总线序号之间则忽略掉它。

  • 如果此总线序号与桥接器的二级总线序号相同则将其转换成类型0 配置命令。

  • 如果此总线序号位于桥接器的二级总线序号与从属总线序号之间则将它不作改变的传递到二级总线接口中。

所以如果想寻址PCI-PCI配置例4中总线3上的设备1,我们继续从CPU中产生一个类型1 配置命令。桥接器1将其传递给总线1。桥接器2虽然忽略它但会将其转换成一个类型0 配置命令并送到总线3上,在那里设备1将作出相应反应。

PCI配置中总线序号由操作系统来分配。但是序号分配策略必须遵循对系统中所有PCI-PCI桥接器都正确的描叙:

“位于PCI-PCI桥接器后所有的PCI总线必须位于二级总线序号和从属总线序号之间”。

如果这个规则被打破,则PCI-PCI桥接器将不能正确的传递与转换类型1 PCI配置循环,同时系统将找不到或者不能正确地初始化系统中的PCI设备。为了满足这个序号分配策略,Linux以特殊的顺序配置这些特殊的设备。一节详细描叙了Linux的PCI桥接器与总线序号分配策略。

Linux PCI 初始化过程

Linux中的PCI初始化代码逻辑上可分成三个部分:

PCI 设备驱动
这个伪设备驱动程序将从总线0开始搜索PCI系统并定位系统中所有的PCI设备与桥接器。它将建立起一个描叙系统拓扑结构的数据结构链表。另外它还为所有的桥接器进行编号。
 
PCI BIOS


这个软件层提供了在bib-pci-bios定义中描叙的服务。即使Alpha AXP没有BIOS服务,Linux核心也将为它提供具有相同功能的代码。
 
PCI Fixup
系统相关补丁代码将整理PCI初始化最后阶段的一些系统相关事物。

Linux 核心PCI数据结构


图6.5 Linux核心PCI数据结构

Linux核心初始化PCI系统时同时也建立了反应系统中真实PCI拓扑的数据结构。 图6.5显示了图6.1所标识的PCI示例系统中数据结构间关系。每个PCI设备(包括PCI-PCI桥接器)用一个pci_dev数据结构来描叙。每个 PCI总线用一个pci_bus数据结构来描叙。这样系统中形成了一个PCI总线树,每棵树上由一些子PCI设备组成。由于PCI总线仅能通过PCI- PCI桥接器(除了主干PCI总线0)存取,所以pci_bus结构中包含一个指向PCI-PCI桥接器的指针。这个PCI设备是PCI总线的父PCI总 线的子设备。

在图6.5中没有显示出来的是一个指向系统中所有PCI设备的指针,pci_devices。系统中所有的PCI设备将其各自的pci_dev数据结构加入此队列中。这个队列被Linux核心用来迅速查找系统中所有的PCI设备。

PCI设备驱动

PCI设备驱动根本不是真正的设备驱动,它仅是在系统初始化时由操作系统调用的一些函数。PCI初始化代码将扫描系统中所有的PCI总线以找到系统中所有的PCI设备(包括PCI-PCI桥接器)。

它通过PCI BIOS代码来检查当前PCI总线的每个插槽是否已被占用。如果被占用则它建立一个pci_dev数据结构来描叙此设备并将其连接到已知PCI设备链表中(由pci_devices指向)。

首先PCI初始化代码扫描PCI总线0。它将试图读取对每个PCI槽中可能的PCI设备厂商标志与设备标志域。当发现槽被占用后将建立一个pci_dev 结构来描叙此设备。所有这些PCI初始化代码建立的pci_dev结构(包括PCI-PCI桥接器)将被连接到一个单向链表pci_devices中。

如果这个PCI设备是一个PCI-PCI桥接器则建立一个pci_bus结构并将其连接到由pci_root指向的pci_dev结构和pci_bus树 中。PCI初始化代码通过类别代码0x060400来判断此PCI设备是否是一个PCI-PCI桥接器。然后Linux 核心代码将配置此PCI-PCI桥接器下方的PCI设备。如果有更多的桥接器被找到则进行同样的配置。显然这个过程使用了深度优先搜索算法;系统中PCI 拓扑将在进行广度映射前先进行深度优先映射。图6.1中Linux将在配置PCI总线0上的视频设备前先配置PCI设备1上的以太与SCSI设备。

由于Linux优先搜索从属的PCI总线,它必须处理PCI-PCI桥接器二级总线与从属总线序号。在下面的pci-pci总线序号分配中将进行详细讨论。

配置PCI-PCI桥接器 - 指定PCI总线序号


图6.6 配置PCI系统:第一部分

为了让PCI-PCI桥接器可以传递PCI I/O、PCI内存或PCI配置地址空间,它们需要如下内容:

Primary Bus Number:主干总线序号
位于PCI-PCI桥接器上方的总线序号
Secondary Bus Number:二级总线序号
位于PCI-PCI桥接器下方的总线序号
Subordinate Bus Number:从属总线序号
在桥接器下方可达的最大总线序号
PCI I/O and PCI Memory Windows:PCI I/O与PCI内存窗口
对于PCI-PCI桥接器下方所有PCI I/O地址空间与PCI内存地址空间的窗口基址和大小。

配置任一PCI-PCI桥接器时我们对此桥接器的从属总线序号一无所知。不知道是否还有下一级桥接器存在,同时也不知道指派给它们的序号是什么。但可以使 用深度优先遍历算法来对扫描出指定PCI-PCI桥接器连接的每条总线,同时将它们编号。当找到一个PCI-PCI桥接器时,其二级总线被编号并且将临时 从属序号0xff指派给它以便对其所有下属PCI-PCI桥接器进行扫描与指定序号。以上过程看起来十分复杂,下面将提供一个实例以帮助理解。

PCI-PCI 桥接器序号分配:步骤1
考虑图6.6所显示的拓扑结构,第一个被扫描到的桥接器将是桥1。所以桥1下方的总线将被编号成总线1,同时桥1被设置为二级总线1且拥有临时总线序号0xff。这意味着所有PCI总线序号为1或以上的类型1 PCI配置地址将被通过桥1传递到PCI总线1上。如果其总线序号为1则此配置循环将被转换成类型0 配置循环,对于其它序号不作转换。这正是Linux PCI初始化代码所需要的按序访问及扫描 PCI总线1。


图6.7 配置PCI系统:第二部分

PCI-PCI 桥接器序号分配:第二步
由于Linux使用深度优先算法,初始化代码将继续扫描PCI总线1。在此处它将发现一个PCI-PCI桥接器2。除此桥接器2外再没有其它桥接器存在, 因此它被分配给从属总线序号2,这正好和其二级接口序号相同。图6.7画出了此处的PCI-PCI桥接器与总线的编号情况。


图6.8 配置PCI系统:第三部分

PCI-PCI 桥接器序号分配:步骤三
PCI初始化代码将继续扫描总线1并发现另外一个PCI-PCI桥接器,桥3。桥3的主干总线接口序号被设置成1,二级总线接口序号为3,同时从属总线序号为0xff。图6.8给出了系统现在的配置情况。 带总线序号1、2或者3的类型1 PCI配置循环将被发送到正确的PCI总线。


图6.9 配置PCI系统:第四部分

PCI-PCI 桥接器序号分配:步骤四
Linux开始沿PCI总线3向下扫描PCI-PCI桥接器。PCI总线3上有另外一个PCI-PCI桥接器(桥4), 桥4的主干总线序号被设置成3,二级总线序号为4。由于它是此分支上最后一个桥接器所以它的从属总线接口序号为4。初始化代码将重新从PCI-PCI桥接 器3开始并将其从属总线序号设为4。 最后PCI初始化代码将PCI-PCI桥接器1的从属总线序号设置为4。图6.9给出了最后的总线序号分配情况。

PCI BIOS 函数

PCI BIOS函数是一组适用于所有平台的标准过程。在Intel和Alpha AXP系统上没有区别。虽然在CPU控制下可以用它们对所有PCI地址空间进行访问。但只有Linux核心代码和设备驱动才能使用它们。

 

PCI 补丁代码

在Alpha AXP平台上的PCI补丁代码所作工作量要大于Intel平台。

基于Intel的系统在系统启动时就已经由系统BIOS完成了PCI系统的配置。Linux只需要完成简单的映射配置. 非Intel系统将需要更多的配置:

  • 为每个设备分配PCI I/O及PCI内存空间。
  • 为系统中每个PCI-PCI桥接器配置PCI I/O和PCI内存地址窗口。
  • 为这些设备产生中断连线值;用来控制设备的中断处理。

下一节将描叙这些代码的工作过程。

确定设备所需PCI I/O和PCI内存空间的大小

系统要查询每个PCI设备需要多少PCI I/O于PCI内存地址空间。为了完成这项工作,每个基地址寄存器将被写上全1并读取出来。设备将把不必要的地址位设为0从而有效的定义所需地址空间。


图6.10 PCI配置头:基地址寄存器

有两类基本的基地址寄存器,一类标识设备寄存器必须驻留的地址空间;另一类是PCI I/O或PCI内存空间。此寄存器的0位来进行类型的区分。图6.10给出了对应于PCI内存和PCI I/O两种不同类型的基地址寄存器。

确定某个基地址寄存器所需地址空间大小时,先向此寄存器写入全1再读取此寄存器,设备将在某些位填上0来形成一个二进制数表示所需有效地址空间。

以初始化DEC 21142 PCI快速以太设备为例,它将告诉系统需要0x100字节的PCI I/O空间或者PCI内存空间。于是初始化代码为其分配空间。空间分配完毕后,就可以在那些地址上看到21142的控制与状态寄存器。

为PCI-PCI桥接器与设备分配PCI I/O与PCI内存

象所有内存一样,PCI I/O和PCI内存空间是非常有限甚至匮乏。非Intel系统的PCI补丁代码(或者Intel 系统的BIOS代码)必须为每个设备分配其所要求的内存。PCI I/O和PCI内存必须以自然对齐方式分配给每个设备。比如如果一个设备要求0xB0大小的PCI I/O空间则它必须和一个0xB0倍数的地址对齐。除此以外,对于任何指定桥接器,其PCI I/O和PCI内存基址必须以在1M字节边界上以4K字节方式对齐。所以在桥接器下方的设备的地址空间必须位于任意指定设备上方的PCI-PCI桥接器的内存范围内。进行有效的空间分配是一件比较困难的工作。

Linux使用的算法依赖于由PCI设备驱动程序建立的描叙PCI设备的总线/设备树,每个设备的地址空间按照PCI I/O内存顺序的升序来分配。同时再次使用遍历算法来遍历由PCI初始化代码建立的pci_bus和 pci_dev结构。从根PCI总线开始(由pci_boot指向)PCI补丁代码将完成下列工作:

  • 使当前全局PCI I/O和内存的基址在4K,边界在1M上对齐。

  • 对于当前总线上的每个设备(按照PCI I/O内存需要的升序排列)
    • 在PCI I/O和PCI内存中为其分配空间

    • 为全局PCI I/O和内存基址同时加上一个适当值

    • 授予设备对PCI I/O和PCI内存的使用权

     

  • 为对于当前总线下方的所有总线循环分配空间。注意这将改变全局PCI I/O和内存基址。

  • 使当前全局PCI I/O和内存的基址和边界分别在4K和1M对齐,以便确定当前PCI-PCI桥接器所需的PCI I/O和PCI内存基址及大小。

  • 对此PCI-PCI桥接器编程,将其PCI I/O和PCI内存基址及界限连接到总线上。

  • 打开PCI-PCI桥接器上的PCI I/O和PCI内存访问桥接功能。这时在此桥接器主干PCI总线上位于此桥接器PCI I/O和PCI内存地址窗口中的任何PCI I/O或者PCI内存地址将被桥接到二级PCI总线上。

以图6.1中的PCI系统为例,PCI补丁代码将以如下方式设置系统:

对齐PCI基址
PCI I/O基址为0x4000而PCI内存基址为0x100000。这样允许PCI-ISA桥接器将此地址以下的地址转换成ISA地址循环。
视频设备
我们按照它的请求从当前PCI内存基址开始分配0x200000字节给它,这样可以在边界上对齐。PCI内存基址被移到0x400000同时PCI I/O基址保持在0x4000。
PCI-PCI 桥接器
现在我们将穿过PCI-PCI桥接器来分配PCI内存,注意此时我们无需对齐这些基址,因为它们已经自然对齐。
以太网设备
它需要0xB0字节的PCI I/O和PCI内存空间。这些空间从PCI I/O地址0x4000和PCI内存地址 0x400000处开始。PCI内存基址被移动到0x4000B0同时PCI I/O基址移动到0x40B0。
SCSI 设备
它需要0x1000字节PCI内存,所以它将在自然对齐后从从0x401000处开始分配空间。PCI I/O基址仍然在0x40B0而PCI内存基址被移动到0x402000。
PCI-PCI 桥接器的PCI I/O和内存窗口
现在我们重新回到桥接器并将其PCI I/O窗口设置成0x4000和0x40B0之间, 同时其PCI内存窗口被设置到0x400000和0x402000之间。这样此PCI-PCI桥接器将忽略对视频设备的PCI内存访问但传递对以太网设备 或者SCSI设备的访问。

 


File translated from TEX by , version 1.0.
, , ,
阅读(1429) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~