1. Basice definations
=====================
"struct pci_access", the structure used to communicate with lipci
lib/pci.h:
43 struct pci_access {
44 /* Options you can change: */
45 unsigned int method; /* Access method */
46 int writeable; /* Open in read/write mode */
47 int buscentric; /* Bus-centric view of the world */
48
49 char *id_file_name; /* Name of ID list file (use pci_set_name_list_path()) */
50 int free_id_name; /* Set if id_file_name is malloced */
51 int numeric_ids; /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */
52
53 unsigned int id_lookup_mode; /* pci_lookup_mode flags which are set automatically */
54 /* Default: PCI_LOOKUP_CACHE */
55
56 int debugging; /* Turn on debugging messages */
57
58 /* Functions you can override: */
59 void (*error)(char *msg, ...) PCI_PRINTF(1,2); /* Write error message and quit */
60 void (*warning)(char *msg, ...) PCI_PRINTF(1,2); /* Write a warning message */
61 void (*debug)(char *msg, ...) PCI_PRINTF(1,2); /* Write a debugging message */
62
63 struct pci_dev *devices; /* Devices found on this bus */
64
65 /* Fields used internally: */
66 struct pci_methods *methods;
67 struct pci_param *params;
68 struct id_entry **id_hash; /* names.c */
69 struct id_bucket *current_id_bucket;
70 int id_load_failed;
71 int id_cache_status; /* 0=not read, 1=read, 2=dirty */
72 int fd; /* proc: fd */
73 int fd_rw; /* proc: fd opened read-write */
74 struct pci_dev *cached_dev; /* proc: device the fd is for */
75 int fd_pos; /* proc: current position */
76 };
struct pci_methods: the methods to access pci configure space
lib/internal.h:
16 struct pci_methods {
17 char *name;
18 char *help;
19 void (*config)(struct pci_access *);
20 int (*detect)(struct pci_access *);
21 void (*init)(struct pci_access *);
22 void (*cleanup)(struct pci_access *);
23 void (*scan)(struct pci_access *);
24 int (*fill_info)(struct pci_dev *, int flags);
25 int (*read)(struct pci_dev *, int pos, byte *buf, int len);
26 int (*write)(struct pci_dev *, int pos, byte *buf, int len);
27 void (*init_dev)(struct pci_dev *);
28 void (*cleanup_dev)(struct pci_dev *);
29 };
The methods are OS depended:
lib/init.c:
16 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
17 NULL,
18 #ifdef PCI_HAVE_PM_LINUX_SYSFS
19 &pm_linux_sysfs,
20 #else
21 NULL,
22 #endif
23 #ifdef PCI_HAVE_PM_LINUX_PROC
24 &pm_linux_proc,
25 #else
26 NULL,
27 #endif
28 #ifdef PCI_HAVE_PM_INTEL_CONF
29 &pm_intel_conf1,
30 &pm_intel_conf2,
31 #else
32 NULL,
33 NULL,
34 #endif
35 #ifdef PCI_HAVE_PM_FBSD_DEVICE
36 &pm_fbsd_device,
37 #else
38 NULL,
39 #endif
40 #ifdef PCI_HAVE_PM_AIX_DEVICE
41 &pm_aix_device,
42 #else
43 NULL,
44 #endif
45 #ifdef PCI_HAVE_PM_NBSD_LIBPCI
46 &pm_nbsd_libpci,
47 #else
48 NULL,
49 #endif
50 #ifdef PCI_HAVE_PM_OBSD_DEVICE
51 &pm_obsd_device,
52 #else
53 NULL,
54 #endif
55 #ifdef PCI_HAVE_PM_DUMP
56 &pm_dump,
57 #else
58 NULL,
59 #endif
60 };
lib/pci.h:
28 enum pci_access_type {
29 /* Known access methods, remember to update access.c as well */
30 PCI_ACCESS_AUTO, /* Autodetection */
31 PCI_ACCESS_SYS_BUS_PCI, /* Linux /sys/bus/pci */
32 PCI_ACCESS_PROC_BUS_PCI, /* Linux /proc/bus/pci */
33 PCI_ACCESS_I386_TYPE1, /* i386 ports, type 1 */
34 PCI_ACCESS_I386_TYPE2, /* i386 ports, type 2 */
35 PCI_ACCESS_FBSD_DEVICE, /* FreeBSD /dev/pci */
36 PCI_ACCESS_AIX_DEVICE, /* /dev/pci0, /dev/bus0, etc. */
37 PCI_ACCESS_NBSD_LIBPCI, /* NetBSD libpci */
38 PCI_ACCESS_OBSD_DEVICE, /* OpenBSD /dev/pci */
39 PCI_ACCESS_DUMP, /* Dump file */
40 PCI_ACCESS_MAX
41 };
For SUNOS, we always get the following method:
255 struct pci_methods pm_intel_conf1 = {
256 "intel-conf1",
257 "Raw I/O port access using Intel conf1 interface",
258 NULL, /* config */
259 conf1_detect,
260 conf12_init,
261 conf12_cleanup,
262 pci_generic_scan,
263 pci_generic_fill_info,
264 conf1_read,
265 conf1_write,
266 NULL, /* init_dev */
267 NULL /* cleanup_dev */
268 };
Other methods should be all NULL's.
2. libpci interface
===================
pci_alloc()
alloc a pci_access structure
pci_init()
specify the debugging method and pci access methods
Since pci access methods are OS depended, it's a neccesarity to choose the method dynamically. In pci_alloc(), each config() function of each member in pci_methods[] is invoked to let the methods declaim themselves. If this failed, libpci has to specify a suitable method, otherwise it should be result in error. In pci_init(), if no method is claimed for pci access, the detect() of pci_methods are invoked in turn, once a success return, the mothod for pci access is specified with it.
So in the real case, the io port access is always support. So if there is no advandced method is chosed on an OS. The io port access the last choose.
3. rough architecture of pciutils
pci utilities: lspci, setpci ...
************************************************
libpci interfaces(pci_alloc, pci_init, bus_scan)
OS dependent pci access method( ... )
************************************************
pci device configure space
=====================
"struct pci_access", the structure used to communicate with lipci
lib/pci.h:
43 struct pci_access {
44 /* Options you can change: */
45 unsigned int method; /* Access method */
46 int writeable; /* Open in read/write mode */
47 int buscentric; /* Bus-centric view of the world */
48
49 char *id_file_name; /* Name of ID list file (use pci_set_name_list_path()) */
50 int free_id_name; /* Set if id_file_name is malloced */
51 int numeric_ids; /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */
52
53 unsigned int id_lookup_mode; /* pci_lookup_mode flags which are set automatically */
54 /* Default: PCI_LOOKUP_CACHE */
55
56 int debugging; /* Turn on debugging messages */
57
58 /* Functions you can override: */
59 void (*error)(char *msg, ...) PCI_PRINTF(1,2); /* Write error message and quit */
60 void (*warning)(char *msg, ...) PCI_PRINTF(1,2); /* Write a warning message */
61 void (*debug)(char *msg, ...) PCI_PRINTF(1,2); /* Write a debugging message */
62
63 struct pci_dev *devices; /* Devices found on this bus */
64
65 /* Fields used internally: */
66 struct pci_methods *methods;
67 struct pci_param *params;
68 struct id_entry **id_hash; /* names.c */
69 struct id_bucket *current_id_bucket;
70 int id_load_failed;
71 int id_cache_status; /* 0=not read, 1=read, 2=dirty */
72 int fd; /* proc: fd */
73 int fd_rw; /* proc: fd opened read-write */
74 struct pci_dev *cached_dev; /* proc: device the fd is for */
75 int fd_pos; /* proc: current position */
76 };
struct pci_methods: the methods to access pci configure space
lib/internal.h:
16 struct pci_methods {
17 char *name;
18 char *help;
19 void (*config)(struct pci_access *);
20 int (*detect)(struct pci_access *);
21 void (*init)(struct pci_access *);
22 void (*cleanup)(struct pci_access *);
23 void (*scan)(struct pci_access *);
24 int (*fill_info)(struct pci_dev *, int flags);
25 int (*read)(struct pci_dev *, int pos, byte *buf, int len);
26 int (*write)(struct pci_dev *, int pos, byte *buf, int len);
27 void (*init_dev)(struct pci_dev *);
28 void (*cleanup_dev)(struct pci_dev *);
29 };
The methods are OS depended:
lib/init.c:
16 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
17 NULL,
18 #ifdef PCI_HAVE_PM_LINUX_SYSFS
19 &pm_linux_sysfs,
20 #else
21 NULL,
22 #endif
23 #ifdef PCI_HAVE_PM_LINUX_PROC
24 &pm_linux_proc,
25 #else
26 NULL,
27 #endif
28 #ifdef PCI_HAVE_PM_INTEL_CONF
29 &pm_intel_conf1,
30 &pm_intel_conf2,
31 #else
32 NULL,
33 NULL,
34 #endif
35 #ifdef PCI_HAVE_PM_FBSD_DEVICE
36 &pm_fbsd_device,
37 #else
38 NULL,
39 #endif
40 #ifdef PCI_HAVE_PM_AIX_DEVICE
41 &pm_aix_device,
42 #else
43 NULL,
44 #endif
45 #ifdef PCI_HAVE_PM_NBSD_LIBPCI
46 &pm_nbsd_libpci,
47 #else
48 NULL,
49 #endif
50 #ifdef PCI_HAVE_PM_OBSD_DEVICE
51 &pm_obsd_device,
52 #else
53 NULL,
54 #endif
55 #ifdef PCI_HAVE_PM_DUMP
56 &pm_dump,
57 #else
58 NULL,
59 #endif
60 };
lib/pci.h:
28 enum pci_access_type {
29 /* Known access methods, remember to update access.c as well */
30 PCI_ACCESS_AUTO, /* Autodetection */
31 PCI_ACCESS_SYS_BUS_PCI, /* Linux /sys/bus/pci */
32 PCI_ACCESS_PROC_BUS_PCI, /* Linux /proc/bus/pci */
33 PCI_ACCESS_I386_TYPE1, /* i386 ports, type 1 */
34 PCI_ACCESS_I386_TYPE2, /* i386 ports, type 2 */
35 PCI_ACCESS_FBSD_DEVICE, /* FreeBSD /dev/pci */
36 PCI_ACCESS_AIX_DEVICE, /* /dev/pci0, /dev/bus0, etc. */
37 PCI_ACCESS_NBSD_LIBPCI, /* NetBSD libpci */
38 PCI_ACCESS_OBSD_DEVICE, /* OpenBSD /dev/pci */
39 PCI_ACCESS_DUMP, /* Dump file */
40 PCI_ACCESS_MAX
41 };
For SUNOS, we always get the following method:
255 struct pci_methods pm_intel_conf1 = {
256 "intel-conf1",
257 "Raw I/O port access using Intel conf1 interface",
258 NULL, /* config */
259 conf1_detect,
260 conf12_init,
261 conf12_cleanup,
262 pci_generic_scan,
263 pci_generic_fill_info,
264 conf1_read,
265 conf1_write,
266 NULL, /* init_dev */
267 NULL /* cleanup_dev */
268 };
Other methods should be all NULL's.
2. libpci interface
===================
pci_alloc()
alloc a pci_access structure
pci_init()
specify the debugging method and pci access methods
Since pci access methods are OS depended, it's a neccesarity to choose the method dynamically. In pci_alloc(), each config() function of each member in pci_methods[] is invoked to let the methods declaim themselves. If this failed, libpci has to specify a suitable method, otherwise it should be result in error. In pci_init(), if no method is claimed for pci access, the detect() of pci_methods are invoked in turn, once a success return, the mothod for pci access is specified with it.
So in the real case, the io port access is always support. So if there is no advandced method is chosed on an OS. The io port access the last choose.
3. rough architecture of pciutils
pci utilities: lspci, setpci ...
************************************************
libpci interfaces(pci_alloc, pci_init, bus_scan)
OS dependent pci access method( ... )
************************************************
pci device configure space