- Brief introduction
- This chapter gives a summary of a high-level bus architecture
- Discussion focuses on kernel functions for accessing peripheral Component interconnect (PCI, peripheral interconnect) Peripherals
- PCI bus is the best supported bus in the kernel
- This chapter mainly introduces the PCI driver if it looks for its hardware and gets access to it
- This chapter also describes the ISA bus
- PCI interface
- PCI is a complete set of specifications that defines how different parts of a computer should interact with each other
- The PCI specification covers most issues related to computer interfaces
- The PCI architecture is designed as a replacement for the ISA standard with three main goals
- Gain better performance when transferring data between a computer and a peripheral
- By using a higher clock frequency than Isa, the PCI bus achieves better performance, its clock frequency is typically 25 or 33MHz (the actual frequency is the coefficient of the system clock), the latest implementation reached 66MHz or even 133MHz
- Equipped with a 32-bit data bus, and the specification already includes 64-bit extensions
- Platform independence as much as possible
- simplifies the task of adding and removing peripherals to the system
- PCI device is a jumper-free device that can be configured automatically during the boot phase
-
- PCI Addressing
- each PCI peripheral is identified by a bus number, a device number, and a feature number
- The PCI specification allows a single system to have up to 256 buses, but 256 buses are not enough for many large systems, so Linux currently supports PCI domain
- each PCI domain can have up to 256 buses
- can support 32 devices per bus, and each device can be a multifunction board with up to eight functions
- Each feature can be identified at the hardware level by a 16-bit address to identify
- device drivers written for Linux can use a special data structure (PCI_DEV) to access the device
- The current workstation is typically configured with at least two PCI buses. Multiple buses are inserted into a single system, which can be done via bridge, which is a special PCI peripheral for connecting two buses
- the overall layout of the PCI system is tree-shaped, where each bus connects to the upper line bus until the root of bus number No. 0
- Lspci
- proc/pci
- /proc/bus/pci/
- View PCI device inventory and device configuration register
- /sys/bus/pci/de Vices
- The hardware circuitry for each peripheral board answers queries for the following three address spaces
- memory location
- I/O port
- configuration register
- the first two address spaces are shared by all devices on the same PCI bus
- configuration space takes advantage of geographic addressing
- the configuration query addresses only one slot at a time
- each PCI slot has four interrupt pins, one of which can be used for each device feature
- I/O space in the PCI bus uses a 32-bit address bus, and the memory space can be accessed through 32-bit or 64-bit addresses
- Boot stage
- The hardware remains inactive when the PCI device is power-up
- There will be no memory and I/O ports mapped to the computer's address space
- Prohibit interrupt reporting
- Each PCI motherboard is equipped with firmware capable of handling PCI, called BIOS, nvram or prom, and the firmware provides access to the device configuration address space by reading and writing registers in the PCI controller
- When the system boots, the firmware performs a configuration transaction on each PCI peripheral to allocate a secure location for each address area it provides
- Configuration registers and initialization
- All PCI devices have at least 256 bytes of address space
- The first 64 bytes are standardized, while the rest are device-related
- PCI registers are always small-ended
- Driver writers pay great attention to the byte order when accessing multibyte configuration registers, as they may not work on the PC on the team's code to other platforms
- VendorID, DeviceID, and class are common three registers
- VendorID
- 16-bit registers that identify hardware manufacturers
- PCI Special Intere St Group maintains a global vendor number registry, and the manufacturer must request a register that is unique numbered and assigned to them
- DeviceID
- 16-bit registers, which are selected by the manufacturer, usually with the vendor ID Generates a unique 32-bit hardware device identifier for the build
- class
- each external device belongs to a class
- 16-bit register, high 8 bits identify "base class" or group
- subsystem VendorID, subsystem DeviceID
- These two fields can be used to further identify the device
- struct pci_device_id is used to define the different types of PCI device lists supported by the driver
- __U32 vendor;
- __U32 device;
- The above two fields specify the PCI vendor and device ID of the device, and if the driver can process any vendor or device ID, these fields should use the value pci_any_id
- __u32 Subvendor;
- __u32 Subdevice;
- The above two fields specify the device's PCI subsystem vendor and subsystem device ID, and if the driver can handle any type of subsystem ID, these fields should use the value pci_any_id
- __u32 class;
- __u32 Class_mask;
- These two values enable the driver to specify that it supports a PCI class device, and that if the driver can handle any type of subsystem ID, these fields should use the value pci_any_id
- kernel_ulong_t Driver_data
- Used to save the information that the PCI driver uses to differentiate between different devices
- Initialization
- Pci_device (Vendor, DEVICE)
- Pci_device_class (Device_class, Device_class_mask)
- Module_device_table
- Module_device_table (PCI, i810_ids);
- Create a local variable named __mod_pci_device_table, pointing to the struct pci_device_id array
- During the kernel build process, the DEPMOD program searches for symbols in all modules __mod_pci_device_table
- If the symbol is found, it extracts the data from the module and adds it to the file/lib/modules/kernel_version/modules.pcimap.
- When the kernel informs the hot-swappable system that a new PCI device has been discovered, the hot-swap system uses the Modules.pcimap file to find the appropriate driver to load
- Registering the PCI driver
- The main structure that the PCI driver must create is the struct pci_driver
- const char *name;
- driver name
- when the driver is running in the kernel, it appears under Sysfs/sys/bus/pci/drivers/
- const struct PCI_DEVICE_ID *id_table
- Int (*probe) (struct Pci_dev *dev, const struct pci_device_id *id); The
- pointer to the probe function in the PCI driver is called when the PCI core has a struct pci_dev that it thinks the driver needs to control
- void (*remove) (struct Pci_dev *dev);
- points to a pointer to a remove function that is called by the PCI core when the struct Pci_dev is removed from the system, or if the PCI driver is being unloaded from the kernel
- void (*suspend) (struct Pci_dev *dev, u32 State);
- Pointer to a recovery function called by the PCI core when the struct Pci_dev is restored
- int pci_register_driver (struct pci_driver *drv);
- Registration successfully returns 0, otherwise a negative error number is returned
- void Pci_unregister_driver (struct pci_driver *drv);
- PCI devices can appear or disappear at any time on a system or CardBus system that supports PCI hot-swapping
The
- 2.6 kernel allows you to dynamically assign a new PCI ID to a driver after it is loaded
- Old-Fashioned PCI detection
- struct Pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
- struct Pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, s Truct Pci_dev *from);
- struct Pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
- Activating a PCI device
- int Pci_enable_device (struct pci_dev *dev);
- Accessing the configuration Space
- After the driver detects a device, it is usually necessary to read or write three address spaces
- Memory
- Port
- Configuration
- <linux/pci.h>
- int pci_read_config_byte (struct pci_dev *dev, int where, U8 *val);
- int Pci_read_config_word (struct pci_dev *dev, int where, U16 *val);
- int Pci_read_config_dword (struct pci_dev *dev, int where, u32 *val);
- int pci_write_config_byte (struct pci_dev *dev, int where, U8 *val);
- int Pci_write_config_word (struct pci_dev *dev, int where, U16 *val);
- int Pci_write_config_dword (struct pci_dev *dev, int where, u32 *val);
- int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, U8 *val);
- int Pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, U16 *val);
- int Pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
- int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, U8 *val);
- int Pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, U16 *val);
- int Pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
- access I/O and memory space
- One PCI device can implement up to 6 I/O address areas
- An interface board reports the size and current position of its region through the configuration register, with their symbolic names pci_base_address_0 through Pci_ Base_address_5
- in the kernel, the I/O area of a PCI device has been integrated into common resource management, and we do not need to access configuration variables to see where the device is mapped to memory or I/O space
- unsigned long pci_ Resource_start (struct pci_dev *dev, int bar);
- unsigned long pci_resource_end (struct pci_dev *dev, int bar);
- unsinged long pci_resource_flags (struct pci_dev *dev, int bar);
- <linux/ioport.h>
- ioresource_io
- ioresource_mem
- ioresource_prefetch
- ioresource_readonly
The
- interrupt number is saved in the configuration register (pci_interrupt_line), which is one byte wide
- If the device does not support interrupts, register Pci_interrupt_pin is 0
- Hardware abstraction
- In PCI management, the only hardware-dependent operation is to read and write the configuration register
- The relevant structure for configuring register access contains only 2 fields
- struct PCI_OPS
- Int (*read) (struct Pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
- Int (*write) (struct Pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
- The structure is defined in <linux/pci.h> and used by DRIVERS/PCI/PCI.C, which defines the actual public function
- ISA review
- The ISA bus is quite outdated in design and its poor performance is notorious
- ISA has some advantages over PCI when it is not very important to support older motherboards
- If you are an electronics enthusiast, you can easily design and develop your own ISA device
- The biggest disadvantage of ISA is that it is tightly bound to the PC architecture
- Another big problem with ISA design is the lack of geographic addressing
- Hardware Resources
- An ISA device can be equipped with an I/O port, memory area, and medium disconnection
- Plug and Play specifications
- Some new Isa device boards follow special design principles and require a special initialization sequence to simplify the installation and configuration of additional interface boards, which are known as PNP (Plug and play, Plug and play).
- The goal of PNP is to obtain the same flexibility as a PCI device without having to modify the underlying electrical interface (that is, ISA bus). To do this, the specification defines a set of device-independent configuration registers, as well as methods for addressing interface boards.
- pc/104 and pc/104+
- These two standards specify the form factor of the printed circuit board and the electrical/mechanical specifications for inter-board interconnection, the real benefit of which is that they can be stacked vertically using a plug-receptacle type connector on one side of the device
- The two buses have the same electronic and logical layout as ISA (pc/104) and PCI (pc/104+)
- Other PC-Bus
- Mca
- MCA (Micro Channel Architecture, microchannel structure) is the IBM standard used in PS/2 computers and some laptops
- Supports multi-master DMA, 32-bit address and data lines, shared interrupts, and geo-addressing to access the onboard configuration register
- EISA
- The extended ISA (EISA) bus is a 32 extension to the ISA bus with a compatible interface connector
- Designed for jumper-free devices
- 32-bit address and data cable, multi-master DMA, and shared disconnection
- VLB
- VLB (VESA local BUS,VESA partial bus) interface bus, which extends the ISA connector by adding a third vertical slot
- SBus
- has been around for a long time, with quite a high level of design
- Although only SPARC computers use the bus, it is intended to be processor-independent and optimized for I/O peripheral boards
- NuBus
- It can be found on older Mac computers (using the m68k series CPU)
- All the buses are memory-mapped and the devices can only be geographically addressed
- External bus
- External buses include: USB, FireWire, and IEEE1284
- These buses are neither full-featured interface buses (such as PCI), but also dumb communication channels (such as serial ports)
- Can usually be divided into two levels
- Drivers for hardware controllers
- Drivers for a specific "customer" device
"Linux Device Drivers" The 12th Chapter PCI driver--note