Hands-on Projects for the Linux Graphics Subsystem
|
X Server collects information about the PCI in two stages:
First by pasing the xorg.conf, the configuration file for the X Server. This file is in some cases generated automatically (like in Ubuntu Linux) and in some cases is filled by the administrator. In the latter case, PCI programs like the lspci or the -scanpci command line option of the Xorg server are used to gather information about the PCI bus of the system.
The second source of information is by making a General PCI probe to discover the whole picture of the PCI bus of the current system.
At section 3.2.2.1 and section 3.2.2.2 we followed the xorg.conf parsing from the X server. In those sections an example of parsing a specific section of xorg.conf was illustrated, however since this example was not about the "Device" section that is of interest, regarding PCI, we will shortly illustrate the data structures involved to parsing the "Device" section. The xorg.conf manual page might be usefull in describing the xorg.conf sections.
As noted in these sections the aim of parsing xorg.conf is filling struct XF86ConfigRec, which is defined in xf86Parser.h as:
typedef struct { XF86ConfFilesPtr conf_files; XF86ConfModulePtr conf_modules; XF86ConfFlagsPtr conf_flags; XF86ConfVideoAdaptorPtr conf_videoadaptor_lst; XF86ConfModesPtr conf_modes_lst; XF86ConfMonitorPtr conf_monitor_lst; XF86ConfDevicePtr conf_device_lst; XF86ConfScreenPtr conf_screen_lst; XF86ConfInputPtr conf_input_lst; XF86ConfLayoutPtr conf_layout_lst; XF86ConfVendorPtr conf_vendor_lst; XF86ConfDRIPtr conf_dri; XF86ConfExtensionsPtr conf_extensions; char *conf_comment; } XF86ConfigRec, *XF86ConfigPtr; |
For the "Device" section we focus in conf_device_lst field, which is highlighted in the previous box. This is of type XF86ConfDevicePtr, which is defined in the same file as:
typedef struct { GenericListRec list; char *dev_identifier; char *dev_vendor; char *dev_board; char *dev_chipset; char *dev_busid; char *dev_card; char *dev_driver; char *dev_ramdac; int dev_dacSpeeds[CONF_MAXDACSPEEDS]; int dev_videoram; int dev_textclockfreq; unsigned long dev_bios_base; unsigned long dev_mem_base; unsigned long dev_io_base; char *dev_clockchip; int dev_clocks; int dev_clock[CONF_MAXCLOCKS]; int dev_chipid; int dev_chiprev; int dev_irq; int dev_screen; XF86OptionPtr dev_option_lst; char *dev_comment; } XF86ConfDeviceRec, *XF86ConfDevicePtr; |
The xorg.conf man page explains most of the XF86ConfDeviceRec fields:
BusID "bus-id"
Screen number
Chipset "chipset"
Ramdac "ramdac-type"
DacSpeed speed
Clocks clock ...
ClockChip "clockchip-type"
VideoRam mem
BiosBase baseaddress
MemBase baseaddress
IOBase baseaddress
ChipID id
ChipRev rev
TextClockFreq freq
Options
|
As we see in section 3.2.2.1 xf86readConfigFile() uses the following part of code to parse the "Device" section:
else if (xf86nameCompare (val.str, "device") == 0) { xf86conffree(val.str); val.str = NULL; HANDLE_LIST (conf_device_lst, xf86parseDeviceSection, XF86ConfDevicePtr); } |
This calls xf86parseDeviceSection(), to fill XF86ConfDeviceRec. For instance the BusID option of the Device section of the xorg.conf is placed in the dev_busid field of XF86ConfDeviceRec with the following code snippet:
case BUSID: if (xf86getSubToken (&(ptr->dev_comment)) != STRING) Error (QUOTE_MSG, "BusID"); ptr->dev_busid = val.str; break;As an example of BusID, consider for instance the following BusID values, as part of the xorg.conf found in 3 monitors, 2 graphics cards, 1 X:
Section "Device" Identifier "G450" Driver "mga" BusID "PCI:1:0:0" Screen 0 EndSection Section "Device" Identifier "G450-1" Driver "mga" BusID "PCI:1:0:0" Screen 1 EndSection Section "Device" Identifier "9200SE" Driver "radeon" BusID "PCI:0:10:0" EndSection |
From the same page we see the lspci output:
00:0a.0 VGA compatible controller: ATI Technologies Inc RV280 [Radeon 9200 SE] (rev 01) 01:00.0 VGA compatible controller: Matrox Graphics, Inc. MGA G400 AGP (rev 82) X wants these values in decimal, therefore 00:0a:0 will be entered as 0:10:0. |
Also from RadeonDriver we read: "BusID gives the hardware address of the graphics card (...) The BusID can be found using the command lspci. A BusID given in lspci as 01:00.0 will become "PCI:1:0:0" in xorg.conf".
It might be also helpfull to remind what BusID represents. From the xorg.conf man page we read:
BusID bus-id This specifies the bus location of the graphics card. For PCI/AGP cards, the bus-id string has the form PCI:bus:device:function (e.g., lqPCI:1:0:0rq might be appropriate for an AGP card). This field is usually optional in single-head configurations when using the primary graphics card. In multi-head configurations, or when using a secondary graphics card in a single-head configuration, this entry is mandatory. Its main purpose is to make an unambiguous connection between the device section and the hardware it is representing. This information can usually be found by running the pciaccess tool scanpci. |
To summarise: the lspci (or a similar unix command) is used to find the BusID, which is used to fill the BusID field of xorg.conf, the value of which becomes then the dev_busid field of the XF86ConfDeviceRec struct in the source code of X Server. This struct is pointed by one of the fields of the main configuration struct for X, which is XF86ConfigRec.
The general PCI probe was covered in section 3.2.2.3. The aim here is to fill xf86PciVideoInfo[], whose element type is a pointer to the following struct:
typedef struct { int vendor; int chipType; int chipRev; int subsysVendor; int subsysCard; int bus; int device; int func; int class; int subclass; int interface; memType memBase[6]; memType ioBase[6]; int size[6]; unsigned char type[6]; memType biosBase; int biosSize; pointer thisCard; Bool validSize; Bool validate; CARD32 listed_class; } pciVideoRec, *pciVideoPtr; |
Certainly some of the fields of pciVideoRec are identical with the ones of XF86ConfDeviceRec, we met at stage 1 previously.
typedef struct { char * identifier; char * vendor; char * board; char * chipset; char * ramdac; char * driver; struct _confscreenrec * myScreenSection; Bool claimed; int dacSpeeds[MAXDACSPEEDS]; int numclocks; int clock[MAXCLOCKS]; char * clockchip; char * busID; Bool active; Bool inUse; int videoRam; int textClockFreq; unsigned long BiosBase; /* Base address of video BIOS */ unsigned long MemBase; /* Frame buffer base address */ unsigned long IOBase; int chipID; int chipRev; pointer options; int irq; int screen; /* For multi-CRTC cards */ } GDevRec, *GDevPtr; |