Device drivers use ddi_regs_map_setup(9F) to establish mappings between kernel virtual address (kvaddr) and device address space for PIO. A device address space may consist of multiple addressable memory regions. Each region is assigned a register set number, rnumber. ddi_dev_nregs(9F) gives the total number of register sets that a device has.
The "reg" property shows the number of addressable regions exported by the device to the system. ddi_regs_map_setup(9F) uses rnumber to index into the array of registers in the "reg" property and returns a kvaddr mapped to the region corresponding to rnumber.
As mentioned in "IEEE 1275 PCI Binding," IEEE 1275 PCI binding makes no specific connection between the entries in the "reg" property and the configuration registers in PCI configuration space. Driver developers should check the "reg" property to ensure that the correct rnumber is used in ddi_regs_map_setup(9F).
For example, the "reg" property of /pci@1f,4000/scsi@3 shown in the example of the PCI SCSI device node properties contains four register sets: one for configuration space, one for I/O space, and two for memory space.
The "assigned-addresses" property has three register sets: one for I/O space, and two for memory space, as shown below.
If you type show-pci-config at the ok prompt of OpenBoot, you get the values of the device's configuration registers, as shown in this example of the configuration register values for an on-board SCSI device. As shown below, base address 0 is for I/O space and base address 1 and 2 are for memory space.
If you write a routine to map into register set 0, as shown below, you should be able to read the device's configuration space and get the same value of device ID, vendor ID, and Class Code as shown in the example of on-board SCSI configuration register values.
In the example above, mem_reg1 and base_addr2 are referring to the same memory object on the device. mem_reg1 is the kvaddr mapped to the memory object and can be used by the driver to access that memory object.
mem_reg1 is allocated from the kernel resources map (kernelmap) and has the value between SYSBASE and SYSEND, as shown in the kernel address map below.
base_addr2 contains the value of the base address register for memory space 1. In this example, the value of base_addr2 is 18000. base_addr2 is the physical address of the memory object in the PCI bus address domain. The system uses base_addr2 in ddi_regs_map_setup(9F) to establish mapping between mem_reg1 and rnumber.
In the ddi_regs_map_setup(9F) call, the system traverses the device tree all the way up to the root nexus driver to establish mapping between kernel virtual address (for example, mem_reg1) and the device register address space denoted by rnumber. On the way to the root nexus driver, the system calls the PCI nexus driver, the device's parent node, to convert rnumber to a generic register structure that can be used by the root nexus driver. The PCI nexus driver reads the values of the "reg" property of the device (if the address in the "reg" property is relocatable, the PCI nexus driver gets the values from the "assigned-addresses" property) and uses rnumber to index into the array to construct the register structure. Inside the register structure is a field that contains the physical address of the device register in the PCI bus address domain (for example, the value of base_addr2).
The system passes the register structure to the root nexus driver. The root nexus driver does three things:
- Converts the address in the register structure into a physical address (
paddr) in the system bus domain - Allocates a
kvaddrfromkernelmap - Establishes a mapping between
kvaddrandpaddr
The root nexus driver then returns the kvaddr to the device driver. When the kvaddr is accessed, the system generates a memory fault to load the system MMU with the kvaddr->paddr translations. It should be noted that the IOMMU of the HPB is not involved in the translations.
本文详细介绍了设备驱动中使用ddi_regs_map_setup建立内核虚拟地址与设备地址空间之间的映射过程,包括如何通过rnumber索引到reg属性中的不同内存区域,并通过实例展示了配置寄存器值的读取方法。
1497

被折叠的 条评论
为什么被折叠?



