1 / 20

The Linux PCI Interface

The Linux PCI Interface. An introduction to the PCI configuration space registers. Some background on PCI. ISA: Industry Standard Architecture (1981) PCI: Peripheral Component Interconnect An Intel-backed industry initiative (1992-9) Main goals: Improve data-xfers to/from peripheral devices

jenaya
Download Presentation

The Linux PCI Interface

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. The Linux PCI Interface An introduction to the PCI configuration space registers

  2. Some background on PCI • ISA: Industry Standard Architecture (1981) • PCI: Peripheral Component Interconnect • An Intel-backed industry initiative (1992-9) • Main goals: • Improve data-xfers to/from peripheral devices • Eliminate (or reduce) platform dependencies • Simplify adding/removing peripheral devices • Lower total consumption of electrical power

  3. Features for driver-writers • Support for “auto-detection” of devices • Device configuration is “programmable” • Introduces “PCI Configuration Space” • A nonvolatile data-structure of device info • A standard “header” layout: 64 longwords • Linux provides some interface functions: #include <linux/pci.h>

  4. pci_dev_struct • Linux extracts info from PCI Config. Space • Stores the info in linked-lists of structures • Examples: • Name of the device’s manufacturer • Name and release version of the product • Hardware resources provided by the product • System resources allocated to the product (Linux provides “search-and-extract” routines)

  5. The ‘lspci’ command • Linux scans PCI Configuration Space • It builds a list of ‘pci_dev_struct’ objects • It exports partial info using a ‘/proc’ file • You can view this info using a command: $ /sbin/lspci • Or you can directly view the /proc/pci file: $ cat /proc/pci

  6. An illustrative example: vram.c • Let’s write another character device-driver • It will allow read/write access to video ram • Very analogous to our prior ‘ram.c’ driver • Some differences: • Device’s memory resides on PCI the bus • Can safely allow writing as well as reading • Hardware uses memory in nonstandard ways • We really need vendor’s programmer manual

  7. init_module() • Driver’s first job is ‘device detection’ • PCI devices are identified by numbers • Device classes also have ID-numbers • VGA device-class: 0x030000 • ’03’ means a ‘display device’ • ’00’ means ‘VGA compatible’ • ’00’ means ‘revision-number’

  8. pci_find_class(); • Define the manifest constant: #define VGA_CLASS 0x030000 • Declare a null-pointer: struct pci_dev_struct *devp = NULL; • Call ‘pci_find_class()’ function: devp = pci_find_class( VGA_CLASS, devp ); • Check for ‘device-not-found’: if ( devp == NULL ) return –ENODEV;

  9. Locate the VGA ‘frame buffer’ • In PCI Configuration Space: • offset 0x10: base_address0 • offset 0x14: base_address1 • offset 0x18: base_address2 • . . . etc. . . . (complete layout on page 475 in textbook) A convenient Linux extraction-function: fb_base = pci_resource_start( devp, 0 );

  10. How big is the frame buffer? • Size of video memory varies with product • Driver needs to determine memory-size • PCI: a standard way to determine size • (But product might provide support for larger vram than is currently installed) • Two-step size-detection method: • First determine maximum supported size • Then check for ‘redundant’ addressing

  11. Maximum memory-size • Some bits in ‘base_address0’ are ‘wired’ • But other bit-values are ‘programmable’ • Bits 0..3 have some special meanings • So we will need to examing bits 4..31 • Find least significant ‘programmable’ bit • It tells the ‘maximum’ supported memory

  12. Programming algorithm • Get configuration longword at offset 0x10 • Save it (so that we can restore it later) • Write a new value: all bits set to 1’s • Read back the longword just written • The ‘hard-wired’ bits will still be 0’s • We will scan for first bit that’s ‘1’ • Be sure to restore the original longword

  13. Loop to find the ‘lowest 1’ • Implementing the PCI size-test: • pci_write_config_dword( devp, 0x10, ~0 ); • pci_read_config_dword( devp, 0x10, &val); • int i; • for (i = 4; i < 32; i++) if ( val & ( 1 << i ) ) break; • fb_maxsize = ( 1 << i );

  14. Checking for memory ‘wrap’ • Do vram bytes have multiple addresses? • We use a ‘quick-and-dirty’ check • write to one address, read from another • If what we read didn’t change: no ‘wrap’! • Some assumptions we make: • Memory-size will be a power of 2 • If two bytes differ, all between them do, too • (Should we question these assumptions?)

  15. Device-memory: read and write • The CPU understands ‘virtual’ addresses • They must be ‘mapped’ to bus addresses • The kernel must setup page-table entries • Linux kernel provides functions: vaddr = ioremap( physaddr, memsize ); iounmap( vaddr ); Alternative: can use ‘ioremap_nocache()’

  16. For copying: ram to/from vram • Linux provides special ‘memcpy’ functions: • memcpy_fromio( ram, vram, nbytes ); • memcpy_toio( vram, ram, nbytes );

  17. Our ‘vram.c’ driver • We imitate the code in our ‘ram.c’ driver • We use ‘temporary’ mappings (one page) • Our ‘read()’ and ‘write()’ are very similar • One notable difference: ‘read()’ is supposed to return 0 in case the file’s pointer is at the ‘end-of-file’ • (This defect should be corrected in ‘ram.c’)

  18. Warning about Red Hat 9.0 • Red Hat 9.0 is now available in stores • It advertises kernel version 2.4.20 • But it’s not identical to 2.4.20 in our class • Our demo modules do not always work • Changes were made to kernel structures (e.g., task_struct) • Changes were made to exported symbols (e.g., sys_call_table)

  19. Need a ‘work-around’ • Our ‘vram.c’ doesn’t create its device-node • Requires users to create a node manually • We ‘hard-coded’ the device major number • So decisions differ from our ‘past practice’

  20. Exercises • Get ‘vram.c’ from our class website • Compile and install the ‘vram.c’ driver • Create the device special file: ‘/dev/vram’ • Change file-attributes (to allow writing) • Try copying video frame-buffer to a file • Use ‘dump.cpp’ to view that binary file • Try using ‘fileview.cpp’ to view video ram

More Related