2 * The PCI Library -- Configuration Access via /sys/bus/pci
4 * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
5 * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
7 * Can be freely distributed and used under the terms of the GNU GPL.
20 #include <sys/types.h>
26 sysfs_config(struct pci_access
*a
)
28 pci_define_param(a
, "sysfs.path", PCI_PATH_SYS_BUS_PCI
, "Path to the sysfs device tree");
32 sysfs_name(struct pci_access
*a
)
34 return pci_get_param(a
, "sysfs.path");
38 sysfs_detect(struct pci_access
*a
)
40 if (access(sysfs_name(a
), R_OK
))
42 a
->debug("...cannot open %s", sysfs_name(a
));
45 a
->debug("...using %s", sysfs_name(a
));
50 sysfs_init(struct pci_access
*a
)
57 sysfs_flush_cache(struct pci_access
*a
)
73 sysfs_cleanup(struct pci_access
*a
)
78 #define OBJNAMELEN 1024
80 sysfs_obj_name(struct pci_dev
*d
, char *object
, char *buf
)
82 int n
= snprintf(buf
, OBJNAMELEN
, "%s/devices/%04x:%02x:%02x.%d/%s",
83 sysfs_name(d
->access
), d
->domain
, d
->bus
, d
->dev
, d
->func
, object
);
84 if (n
< 0 || n
>= OBJNAMELEN
)
85 d
->access
->error("File name too long");
88 #define OBJBUFSIZE 1024
91 sysfs_get_string(struct pci_dev
*d
, char *object
, char *buf
, int mandatory
)
93 struct pci_access
*a
= d
->access
;
95 char namebuf
[OBJNAMELEN
];
97 sysfs_obj_name(d
, object
, namebuf
);
98 fd
= open(namebuf
, O_RDONLY
);
102 a
->error("Cannot open %s: %s", namebuf
, strerror(errno
));
105 n
= read(fd
, buf
, OBJBUFSIZE
);
108 a
->error("Error reading %s: %s", namebuf
, strerror(errno
));
110 a
->error("Value in %s too long", namebuf
);
116 sysfs_get_value(struct pci_dev
*d
, char *object
)
118 char buf
[OBJBUFSIZE
];
120 sysfs_get_string(d
, object
, buf
, 1);
121 return strtol(buf
, NULL
, 0);
125 sysfs_get_resources(struct pci_dev
*d
)
127 struct pci_access
*a
= d
->access
;
128 char namebuf
[OBJNAMELEN
], buf
[256];
132 sysfs_obj_name(d
, "resource", namebuf
);
133 file
= fopen(namebuf
, "r");
135 a
->error("Cannot open %s: %s", namebuf
, strerror(errno
));
136 for (i
= 0; i
< 7; i
++)
138 unsigned long long start
, end
, size
, flags
;
139 if (!fgets(buf
, sizeof(buf
), file
))
141 if (sscanf(buf
, "%llx %llx %llx", &start
, &end
, &flags
) != 3)
142 a
->error("Syntax error in %s", namebuf
);
144 size
= end
- start
+ 1;
147 flags
&= PCI_ADDR_FLAG_MASK
;
150 d
->base_addr
[i
] = start
| flags
;
155 d
->rom_base_addr
= start
| flags
;
162 static void sysfs_scan(struct pci_access
*a
)
166 struct dirent
*entry
;
169 n
= snprintf(dirname
, sizeof(dirname
), "%s/devices", sysfs_name(a
));
170 if (n
< 0 || n
>= (int) sizeof(dirname
))
171 a
->error("Directory name too long");
172 dir
= opendir(dirname
);
174 a
->error("Cannot open %s", dirname
);
175 while ((entry
= readdir(dir
)))
178 unsigned int dom
, bus
, dev
, func
;
180 /* ".", ".." or a special non-device perhaps */
181 if (entry
->d_name
[0] == '.')
184 d
= pci_alloc_dev(a
);
185 if (sscanf(entry
->d_name
, "%x:%x:%x.%d", &dom
, &bus
, &dev
, &func
) < 4)
186 a
->error("sysfs_scan: Couldn't parse entry name %s", entry
->d_name
);
193 sysfs_get_resources(d
);
194 d
->irq
= sysfs_get_value(d
, "irq");
196 * We could read these faster from the config registers, but we want to give
197 * the kernel a chance to fix up ID's and especially classes of broken devices.
199 d
->vendor_id
= sysfs_get_value(d
, "vendor");
200 d
->device_id
= sysfs_get_value(d
, "device");
201 d
->device_class
= sysfs_get_value(d
, "class") >> 8;
203 if (sysfs_get_string(d
, "label", buf
, 0))
204 d
->label
= pci_strdup(d
->access
, buf
);
206 d
->known_fields
= PCI_FILL_IDENT
| PCI_FILL_CLASS
| PCI_FILL_IRQ
| PCI_FILL_BASES
| PCI_FILL_ROM_BASE
| PCI_FILL_SIZES
;
214 sysfs_fill_slots(struct pci_access
*a
)
218 struct dirent
*entry
;
221 n
= snprintf(dirname
, sizeof(dirname
), "%s/slots", sysfs_name(a
));
222 if (n
< 0 || n
>= (int) sizeof(dirname
))
223 a
->error("Directory name too long");
224 dir
= opendir(dirname
);
228 while (entry
= readdir(dir
))
230 char namebuf
[OBJNAMELEN
], buf
[16];
232 unsigned int dom
, bus
, dev
;
236 /* ".", ".." or a special non-device perhaps */
237 if (entry
->d_name
[0] == '.')
240 n
= snprintf(namebuf
, OBJNAMELEN
, "%s/%s/%s", dirname
, entry
->d_name
, "address");
241 if (n
< 0 || n
>= OBJNAMELEN
)
242 a
->error("File name too long");
243 file
= fopen(namebuf
, "r");
245 * Old versions of Linux had a fakephp which didn't have an 'address'
246 * file. There's no useful information to be gleaned from these
247 * devices, pretend they're not there.
252 if (!fgets(buf
, sizeof(buf
), file
) || (res
= sscanf(buf
, "%x:%x:%x", &dom
, &bus
, &dev
)) < 3)
255 * In some cases, the slot is not tied to a specific device before
256 * a card gets inserted. This happens for example on IBM pSeries
257 * and we need not warn about it.
260 a
->warning("sysfs_fill_slots: Couldn't parse entry address %s", buf
);
264 for (d
= a
->devices
; d
; d
= d
->next
)
265 if (dom
== d
->domain
&& bus
== d
->bus
&& dev
== d
->dev
&& !d
->phy_slot
)
266 d
->phy_slot
= pci_strdup(a
, entry
->d_name
);
274 sysfs_fill_info(struct pci_dev
*d
, int flags
)
276 if ((flags
& PCI_FILL_PHYS_SLOT
) && !(d
->known_fields
& PCI_FILL_PHYS_SLOT
))
279 sysfs_fill_slots(d
->access
);
280 for (pd
= d
->access
->devices
; pd
; pd
= pd
->next
)
281 pd
->known_fields
|= PCI_FILL_PHYS_SLOT
;
284 if ((flags
& PCI_FILL_MODULE_ALIAS
) && !(d
->known_fields
& PCI_FILL_MODULE_ALIAS
))
286 char buf
[OBJBUFSIZE
];
287 if (sysfs_get_string(d
, "modalias", buf
, 0))
288 d
->module_alias
= pci_strdup(d
->access
, buf
);
291 return pci_generic_fill_info(d
, flags
);
294 /* Intent of the sysfs_setup() caller */
297 SETUP_READ_CONFIG
= 0,
298 SETUP_WRITE_CONFIG
= 1,
303 sysfs_setup(struct pci_dev
*d
, int intent
)
305 struct pci_access
*a
= d
->access
;
306 char namebuf
[OBJNAMELEN
];
308 if (a
->cached_dev
!= d
|| (intent
== SETUP_WRITE_CONFIG
&& !a
->fd_rw
))
310 sysfs_flush_cache(a
);
314 if (intent
== SETUP_READ_VPD
)
318 sysfs_obj_name(d
, "vpd", namebuf
);
319 a
->fd_vpd
= open(namebuf
, O_RDONLY
);
320 /* No warning on error; vpd may be absent or accessible only to root */
327 sysfs_obj_name(d
, "config", namebuf
);
328 a
->fd_rw
= a
->writeable
|| intent
== SETUP_WRITE_CONFIG
;
329 a
->fd
= open(namebuf
, a
->fd_rw
? O_RDWR
: O_RDONLY
);
331 a
->warning("Cannot open %s", namebuf
);
337 static int sysfs_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
339 int fd
= sysfs_setup(d
, SETUP_READ_CONFIG
);
344 res
= do_read(d
, fd
, buf
, len
, pos
);
347 d
->access
->warning("sysfs_read: read failed: %s", strerror(errno
));
355 static int sysfs_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
357 int fd
= sysfs_setup(d
, SETUP_WRITE_CONFIG
);
362 res
= do_write(d
, fd
, buf
, len
, pos
);
365 d
->access
->warning("sysfs_write: write failed: %s", strerror(errno
));
370 d
->access
->warning("sysfs_write: tried to write %d bytes at %d, but only %d succeeded", len
, pos
, res
);
376 #ifdef PCI_HAVE_DO_READ
378 /* pread() is not available and do_read() only works for a single fd, so we
379 * cannot implement read_vpd properly. */
380 static int sysfs_read_vpd(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
385 #else /* !PCI_HAVE_DO_READ */
387 static int sysfs_read_vpd(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
389 int fd
= sysfs_setup(d
, SETUP_READ_VPD
);
394 res
= pread(fd
, buf
, len
, pos
);
397 d
->access
->warning("sysfs_read_vpd: read failed: %s", strerror(errno
));
405 #endif /* PCI_HAVE_DO_READ */
407 static void sysfs_cleanup_dev(struct pci_dev
*d
)
409 struct pci_access
*a
= d
->access
;
411 if (a
->cached_dev
== d
)
412 sysfs_flush_cache(a
);
415 struct pci_methods pm_linux_sysfs
= {
417 "The sys filesystem on Linux",