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");
89 sysfs_get_value(struct pci_dev
*d
, char *object
)
91 struct pci_access
*a
= d
->access
;
93 char namebuf
[OBJNAMELEN
], buf
[256];
95 sysfs_obj_name(d
, object
, namebuf
);
96 fd
= open(namebuf
, O_RDONLY
);
98 a
->error("Cannot open %s: %s", namebuf
, strerror(errno
));
99 n
= read(fd
, buf
, sizeof(buf
));
102 a
->error("Error reading %s: %s", namebuf
, strerror(errno
));
103 if (n
>= (int) sizeof(buf
))
104 a
->error("Value in %s too long", namebuf
);
106 return strtol(buf
, NULL
, 0);
110 sysfs_get_resources(struct pci_dev
*d
)
112 struct pci_access
*a
= d
->access
;
113 char namebuf
[OBJNAMELEN
], buf
[256];
117 sysfs_obj_name(d
, "resource", namebuf
);
118 file
= fopen(namebuf
, "r");
120 a
->error("Cannot open %s: %s", namebuf
, strerror(errno
));
121 for (i
= 0; i
< 7; i
++)
123 unsigned long long start
, end
, size
;
124 if (!fgets(buf
, sizeof(buf
), file
))
126 if (sscanf(buf
, "%llx %llx", &start
, &end
) != 2)
127 a
->error("Syntax error in %s", namebuf
);
129 size
= end
- start
+ 1;
134 d
->base_addr
[i
] = start
;
139 d
->rom_base_addr
= start
;
146 static void sysfs_scan(struct pci_access
*a
)
150 struct dirent
*entry
;
153 n
= snprintf(dirname
, sizeof(dirname
), "%s/devices", sysfs_name(a
));
154 if (n
< 0 || n
>= (int) sizeof(dirname
))
155 a
->error("Directory name too long");
156 dir
= opendir(dirname
);
158 a
->error("Cannot open %s", dirname
);
159 while ((entry
= readdir(dir
)))
162 unsigned int dom
, bus
, dev
, func
;
164 /* ".", ".." or a special non-device perhaps */
165 if (entry
->d_name
[0] == '.')
168 d
= pci_alloc_dev(a
);
169 if (sscanf(entry
->d_name
, "%x:%x:%x.%d", &dom
, &bus
, &dev
, &func
) < 4)
170 a
->error("sysfs_scan: Couldn't parse entry name %s", entry
->d_name
);
177 sysfs_get_resources(d
);
178 d
->irq
= sysfs_get_value(d
, "irq");
180 * We could read these faster from the config registers, but we want to give
181 * the kernel a chance to fix up ID's and especially classes of broken devices.
183 d
->vendor_id
= sysfs_get_value(d
, "vendor");
184 d
->device_id
= sysfs_get_value(d
, "device");
185 d
->device_class
= sysfs_get_value(d
, "class") >> 8;
186 d
->known_fields
= PCI_FILL_IDENT
| PCI_FILL_CLASS
| PCI_FILL_IRQ
| PCI_FILL_BASES
| PCI_FILL_ROM_BASE
| PCI_FILL_SIZES
;
194 sysfs_fill_slots(struct pci_access
*a
)
198 struct dirent
*entry
;
201 n
= snprintf(dirname
, sizeof(dirname
), "%s/slots", sysfs_name(a
));
202 if (n
< 0 || n
>= (int) sizeof(dirname
))
203 a
->error("Directory name too long");
204 dir
= opendir(dirname
);
208 while (entry
= readdir(dir
))
210 char namebuf
[OBJNAMELEN
], buf
[16];
212 unsigned int dom
, bus
, dev
;
215 /* ".", ".." or a special non-device perhaps */
216 if (entry
->d_name
[0] == '.')
219 n
= snprintf(namebuf
, OBJNAMELEN
, "%s/%s/%s", dirname
, entry
->d_name
, "address");
220 if (n
< 0 || n
>= OBJNAMELEN
)
221 a
->error("File name too long");
222 file
= fopen(namebuf
, "r");
225 a
->warning("sysfs_fill_slots: Cannot open %s: %s", namebuf
, strerror(errno
));
229 if (!fgets(buf
, sizeof(buf
), file
) || sscanf(buf
, "%x:%x:%x", &dom
, &bus
, &dev
) < 3)
230 a
->warning("sysfs_fill_slots: Couldn't parse entry address %s", buf
);
233 for (d
= a
->devices
; d
; d
= d
->next
)
234 if (dom
== d
->domain
&& bus
== d
->bus
&& dev
== d
->dev
&& !d
->phy_slot
)
236 d
->phy_slot
= pci_malloc(a
, strlen(entry
->d_name
) + 1);
237 strcpy(d
->phy_slot
, entry
->d_name
);
247 sysfs_fill_info(struct pci_dev
*d
, int flags
)
249 if ((flags
& PCI_FILL_PHYS_SLOT
) && !(d
->known_fields
& PCI_FILL_PHYS_SLOT
))
252 sysfs_fill_slots(d
->access
);
253 for (pd
= d
->access
->devices
; pd
; pd
= pd
->next
)
254 pd
->known_fields
|= PCI_FILL_PHYS_SLOT
;
256 return pci_generic_fill_info(d
, flags
);
259 /* Intent of the sysfs_setup() caller */
262 SETUP_READ_CONFIG
= 0,
263 SETUP_WRITE_CONFIG
= 1,
268 sysfs_setup(struct pci_dev
*d
, int intent
)
270 struct pci_access
*a
= d
->access
;
271 char namebuf
[OBJNAMELEN
];
273 if (a
->cached_dev
!= d
|| (intent
== SETUP_WRITE_CONFIG
&& !a
->fd_rw
))
275 sysfs_flush_cache(a
);
279 if (intent
== SETUP_READ_VPD
)
283 sysfs_obj_name(d
, "vpd", namebuf
);
284 a
->fd_vpd
= open(namebuf
, O_RDONLY
);
285 /* No warning on error; vpd may be absent or accessible only to root */
292 sysfs_obj_name(d
, "config", namebuf
);
293 a
->fd_rw
= a
->writeable
|| intent
== SETUP_WRITE_CONFIG
;
294 a
->fd
= open(namebuf
, a
->fd_rw
? O_RDWR
: O_RDONLY
);
296 a
->warning("Cannot open %s", namebuf
);
302 static int sysfs_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
304 int fd
= sysfs_setup(d
, SETUP_READ_CONFIG
);
309 res
= do_read(d
, fd
, buf
, len
, pos
);
312 d
->access
->warning("sysfs_read: read failed: %s", strerror(errno
));
320 static int sysfs_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
322 int fd
= sysfs_setup(d
, SETUP_WRITE_CONFIG
);
327 res
= do_write(d
, fd
, buf
, len
, pos
);
330 d
->access
->warning("sysfs_write: write failed: %s", strerror(errno
));
335 d
->access
->warning("sysfs_write: tried to write %d bytes at %d, but only %d succeeded", len
, pos
, res
);
341 #ifdef PCI_HAVE_DO_READ
343 /* pread() is not available and do_read() only works for a single fd, so we
344 * cannot implement read_vpd properly. */
345 static int sysfs_read_vpd(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
350 #else /* !PCI_HAVE_DO_READ */
352 static int sysfs_read_vpd(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
354 int fd
= sysfs_setup(d
, SETUP_READ_VPD
);
359 res
= pread(fd
, buf
, len
, pos
);
362 d
->access
->warning("sysfs_read_vpd: read failed: %s", strerror(errno
));
370 #endif /* PCI_HAVE_DO_READ */
372 static void sysfs_cleanup_dev(struct pci_dev
*d
)
374 struct pci_access
*a
= d
->access
;
376 if (a
->cached_dev
== d
)
377 sysfs_flush_cache(a
);
380 struct pci_methods pm_linux_sysfs
= {
382 "The sys filesystem on Linux",