/[soft]/ldetect/trunk/pci.c
ViewVC logotype

Contents of /ldetect/trunk/pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7781 - (show annotations) (download)
Fri Apr 5 10:36:53 2013 UTC (11 years ago) by tv
File MIME type: text/plain
File size: 5447 byte(s)
do not fake Xen blk & net controllers on dom0 (mga#9546)
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <pci/pci.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <dirent.h>
12 #include <pci/header.h>
13 #include "common.h"
14
15 /* /proc files're 256 bytes but we only need first 64 bytes*/
16 #define CONFIG_SPACE_SIZE 64
17
18 static char *proc_pci_path_default = "/proc/bus/pci/devices";
19 char* proc_pci_path = NULL;
20
21 static void __attribute__((noreturn)) error_and_die(char *msg, ...)
22 {
23 va_list args;
24
25 va_start(args, msg);
26 fprintf(stderr, "%s: ", "lspcidrake");
27 vfprintf(stderr, msg, args);
28 fputc('\n', stderr);
29 exit(1);
30 }
31
32 static struct pci_access *pacc;
33 char* get_pci_description(int vendor_id, int device_id) {
34 char vendorbuf[128], devbuf[128];
35 char *buf = malloc(256);
36
37 if (!pacc) {
38 pacc = pci_alloc();
39 pci_init(pacc); /* Initialize the PCI library */
40 pacc->numeric_ids = 0;
41 pci_init(pacc);
42 }
43
44 asprintf(&buf, "%s|%s",
45 pci_lookup_name(pacc, vendorbuf, sizeof(vendorbuf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_NO_NUMBERS, vendor_id, device_id),
46 pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, vendor_id, device_id)
47 );
48 //pci_cleanup(pacc); // only used by stage1's merge-pcitable.pl that doesn't care about leaking _one_ struct
49 return buf;
50 }
51
52 // fake two PCI controllers for xen
53 static void detect_xen(struct pciusb_entries *r) {
54 struct stat sb;
55 if (stat("/sys/bus/xen", &sb) != 0)
56 return;
57 FILE *f;
58 if (!(f = fopen("/sys/hypervisor/uuid", "r")))
59 return;
60 char buf[38];
61 fgets(buf, sizeof(buf) - 1, f);
62 fclose(f);
63 if (!strncmp(buf, "00000000-0000-0000-0000-000000000000", sizeof(buf)))
64 return;
65
66 // We're now sure to be in a Xen guest:
67
68 struct pciusb_entry *e = &r->entries[r->nb++];
69 pciusb_initialize(e);
70 asprintf(&e->text, "%s|%s", "XenSource, Inc.", "Block Frontend");
71 e->class_id = 0x0106; // STORAGE_SATA
72
73 e->vendor = 0x1a71; // XenSource
74 e->device = 0xfffa; // fake
75 e->subvendor = 0;
76 e->subdevice = 0;
77 e->class_id = 0x0106;
78 e->module = strdup("xen_blkfront");
79
80 e = &r->entries[r->nb++];
81 pciusb_initialize(e);
82 asprintf(&e->text, "%s|%s", "XenSource, Inc.", "Network Frontend");
83 e->class_id = 0x0200; // NETWORK_ETHERNET
84
85 e->vendor = 0x1a71; // XenSource
86 e->device = 0xfffb; // fake
87 e->subvendor = 0;
88 e->subdevice = 0;
89 e->class_id = 0x0200;
90 e->module = strdup("xen_netfront");
91 }
92
93 extern struct pciusb_entries pci_probe(void) {
94 u8 buf[CONFIG_SPACE_SIZE];
95 struct pciusb_entries r;
96
97 static struct pci_access *pacc;
98 struct pci_dev *dev;
99 char classbuf[128], vendorbuf[128], devbuf[128];
100 size_t allocated = MAX_DEVICES;
101
102 r.nb = 0;
103 if ((access(proc_pci_path_default, R_OK) != 0)
104 || (proc_pci_path && (access(proc_pci_path_default, R_OK) != 0)))
105 return r;
106
107 pacc = pci_alloc();
108
109 if (proc_pci_path) {
110 pci_set_param(pacc, "proc.path", proc_pci_path);
111 }
112
113
114 pci_init(pacc);
115 pacc->error = error_and_die;
116 pci_scan_bus(pacc);
117
118 r.nb = 0;
119 r.entries = malloc(sizeof(struct pciusb_entry) * MAX_DEVICES);
120
121 detect_xen(&r);
122
123 for (dev = pacc->devices; dev; dev = dev->next, r.nb++) {
124 if (r.nb >= allocated) {
125 allocated = r.nb*2;
126 r.entries = realloc(r.entries, sizeof(struct pciusb_entry) * allocated);
127 }
128 struct pciusb_entry *e = &r.entries[r.nb];
129 memset(buf, 0, CONFIG_SPACE_SIZE); // make sure not to retrieve values from previous devices
130 pci_setup_cache(dev, (u8*)buf, CONFIG_SPACE_SIZE);
131 pci_read_block(dev, 0, buf, CONFIG_SPACE_SIZE);
132 pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_CAPS);
133
134 pciusb_initialize(e);
135
136 asprintf(&e->text, "%s|%s",
137 pci_lookup_name(pacc, vendorbuf, sizeof(vendorbuf), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id),
138 pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id)
139 );
140 pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, dev->device_class),
141 e->class=strdup(classbuf);
142
143 e->vendor = dev->vendor_id;
144 e->device = dev->device_id;
145 e->pci_domain = dev->domain;
146 e->pci_bus = dev->bus;
147 e->pci_device = dev->dev;
148 e->pci_function = dev->func;
149
150 e->class_id = dev->device_class;
151 e->subvendor = pci_read_word(dev, PCI_SUBSYSTEM_VENDOR_ID);
152 e->subdevice = pci_read_word(dev, PCI_SUBSYSTEM_ID);
153 e->pci_revision = pci_read_byte(dev, PCI_REVISION_ID);
154
155 if ((e->subvendor == 0 && e->subdevice == 0) ||
156 (e->subvendor == e->vendor && e->subdevice == e->device)) {
157 e->subvendor = 0xffff;
158 e->subdevice = 0xffff;
159 }
160
161 if (pci_find_cap(dev,PCI_CAP_ID_EXP, PCI_CAP_NORMAL))
162 e->is_pciexpress = 1;
163
164 /* special case for realtek 8139 that has two drivers */
165 if (e->vendor == 0x10ec && e->device == 0x8139) {
166 if (e->pci_revision < 0x20)
167 e->module = strdup("8139too");
168 else
169 e->module = strdup("8139cp");
170 }
171
172 }
173
174 /* shrink to real size */
175 r.entries = realloc(r.entries, sizeof(struct pciusb_entry) * r.nb);
176
177 pci_cleanup(pacc);
178
179 if (pciusb_find_modules(&r, "pcitable", DO_NOT_LOAD, 1))
180 return r;
181
182 /* should not happen */
183 exit(1);
184 }

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.30