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

Annotation of /ldetect/trunk/pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7781 - (hide 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 dmorgan 1357 #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 tv 2043 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 tv 7728 // fake two PCI controllers for xen
53 tv 7780 static void detect_xen(struct pciusb_entries *r) {
54 tv 7728 struct stat sb;
55     if (stat("/sys/bus/xen", &sb) != 0)
56     return;
57 tv 7781 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 tv 7728
66 tv 7781 // We're now sure to be in a Xen guest:
67    
68 tv 7728 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 tv 7736 e->device = 0xfffb; // fake
87 tv 7728 e->subvendor = 0;
88     e->subdevice = 0;
89     e->class_id = 0x0200;
90     e->module = strdup("xen_netfront");
91     }
92    
93 dmorgan 1357 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 tv 7092 size_t allocated = MAX_DEVICES;
101 dmorgan 1357
102 tv 2042 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 dmorgan 1357 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 tv 7728 detect_xen(&r);
122    
123 tv 7092 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 dmorgan 1357 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