2 * $Id: proc.c,v 1.13 1998/05/12 07:36:07 mj Exp $
4 * Procfs interface for the PCI bus.
6 * Copyright (c) 1997--1999 Martin Mares <mj@suse.cz>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/pci.h>
12 #include <linux/proc_fs.h>
13 #include <linux/init.h>
15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h>
18 #define PCI_CFG_SPACE_SIZE 256
21 proc_bus_pci_lseek(struct file
*file
, loff_t off
, int whence
)
30 new = file
->f_pos
+ off
;
33 new = PCI_CFG_SPACE_SIZE
+ off
;
38 if (new < 0 || new > PCI_CFG_SPACE_SIZE
)
40 return (file
->f_pos
= new);
44 proc_bus_pci_read(struct file
*file
, char *buf
, size_t nbytes
, loff_t
*ppos
)
46 const struct inode
*ino
= file
->f_dentry
->d_inode
;
47 const struct proc_dir_entry
*dp
= ino
->u
.generic_ip
;
48 struct pci_dev
*dev
= dp
->data
;
49 unsigned int pos
= *ppos
;
50 unsigned int cnt
, size
;
53 * Normal users can read only the standardized portion of the
54 * configuration space as several chips lock up when trying to read
55 * undefined locations (think of Intel PIIX4 as a typical example).
58 if (capable(CAP_SYS_ADMIN
))
59 size
= PCI_CFG_SPACE_SIZE
;
60 else if (dev
->hdr_type
== PCI_HEADER_TYPE_CARDBUS
)
69 if (pos
+ nbytes
> size
)
73 if (!access_ok(VERIFY_WRITE
, buf
, cnt
))
76 if ((pos
& 1) && cnt
) {
78 pci_read_config_byte(dev
, pos
, &val
);
85 if ((pos
& 3) && cnt
> 2) {
87 pci_read_config_word(dev
, pos
, &val
);
88 __put_user(cpu_to_le16(val
), (unsigned short *) buf
);
96 pci_read_config_dword(dev
, pos
, &val
);
97 __put_user(cpu_to_le32(val
), (unsigned int *) buf
);
105 pci_read_config_word(dev
, pos
, &val
);
106 __put_user(cpu_to_le16(val
), (unsigned short *) buf
);
114 pci_read_config_byte(dev
, pos
, &val
);
115 __put_user(val
, buf
);
126 proc_bus_pci_write(struct file
*file
, const char *buf
, size_t nbytes
, loff_t
*ppos
)
128 const struct inode
*ino
= file
->f_dentry
->d_inode
;
129 const struct proc_dir_entry
*dp
= ino
->u
.generic_ip
;
130 struct pci_dev
*dev
= dp
->data
;
134 if (pos
>= PCI_CFG_SPACE_SIZE
)
136 if (nbytes
>= PCI_CFG_SPACE_SIZE
)
137 nbytes
= PCI_CFG_SPACE_SIZE
;
138 if (pos
+ nbytes
> PCI_CFG_SPACE_SIZE
)
139 nbytes
= PCI_CFG_SPACE_SIZE
- pos
;
142 if (!access_ok(VERIFY_READ
, buf
, cnt
))
145 if ((pos
& 1) && cnt
) {
147 __get_user(val
, buf
);
148 pci_write_config_byte(dev
, pos
, val
);
154 if ((pos
& 3) && cnt
> 2) {
156 __get_user(val
, (unsigned short *) buf
);
157 pci_write_config_word(dev
, pos
, le16_to_cpu(val
));
165 __get_user(val
, (unsigned int *) buf
);
166 pci_write_config_dword(dev
, pos
, le32_to_cpu(val
));
174 __get_user(val
, (unsigned short *) buf
);
175 pci_write_config_word(dev
, pos
, le16_to_cpu(val
));
183 __get_user(val
, buf
);
184 pci_write_config_byte(dev
, pos
, val
);
194 static struct file_operations proc_bus_pci_operations
= {
195 llseek
: proc_bus_pci_lseek
,
196 read
: proc_bus_pci_read
,
197 write
: proc_bus_pci_write
,
200 #if BITS_PER_LONG == 32
201 #define LONG_FORMAT "\t%08lx"
203 #define LONG_FORMAT "\t%16lx"
207 get_pci_dev_info(char *buf
, char **start
, off_t pos
, int count
)
209 const struct pci_dev
*dev
;
214 pci_for_each_dev(dev
) {
215 const struct pci_driver
*drv
= pci_dev_driver(dev
);
216 len
= sprintf(buf
, "%02x%02x\t%04x%04x\t%x",
222 /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
224 len
+= sprintf(buf
+len
, LONG_FORMAT
,
225 dev
->resource
[i
].start
| (dev
->resource
[i
].flags
& PCI_REGION_FLAG_MASK
));
227 len
+= sprintf(buf
+len
, LONG_FORMAT
, dev
->resource
[i
].start
< dev
->resource
[i
].end
?
228 dev
->resource
[i
].end
- dev
->resource
[i
].start
+ 1 : 0);
231 len
+= sprintf(buf
+len
, "%s", drv
->name
);
236 *start
= buf
+ (pos
- (at
- len
));
243 * proc_file_read() gives us 1KB of slack so it's OK if the
244 * above printfs write a little beyond the buffer end (we
245 * never write more than 1KB beyond the buffer end).
250 return (count
> cnt
) ? cnt
: count
;
253 static struct proc_dir_entry
*proc_bus_pci_dir
;
255 int pci_proc_attach_device(struct pci_dev
*dev
)
257 struct pci_bus
*bus
= dev
->bus
;
258 struct proc_dir_entry
*de
, *e
;
261 if (!(de
= bus
->procdir
)) {
262 sprintf(name
, "%02x", bus
->number
);
263 de
= bus
->procdir
= proc_mkdir(name
, proc_bus_pci_dir
);
267 sprintf(name
, "%02x.%x", PCI_SLOT(dev
->devfn
), PCI_FUNC(dev
->devfn
));
268 e
= dev
->procent
= create_proc_entry(name
, S_IFREG
| S_IRUGO
| S_IWUSR
, de
);
271 e
->proc_fops
= &proc_bus_pci_operations
;
273 e
->size
= PCI_CFG_SPACE_SIZE
;
277 int pci_proc_detach_device(struct pci_dev
*dev
)
279 struct proc_dir_entry
*e
;
281 if ((e
= dev
->procent
)) {
284 remove_proc_entry(e
->name
, dev
->bus
->procdir
);
292 * Backward compatible /proc/pci interface.
296 * Convert some of the configuration space registers of the device at
297 * address (bus,devfn) into a string (possibly several lines each).
298 * The configuration string is stored starting at buf[len]. If the
299 * string would exceed the size of the buffer (SIZE), 0 is returned.
301 static int sprint_dev_config(struct pci_dev
*dev
, char *buf
, int size
)
304 unsigned char latency
, min_gnt
, max_lat
, *class;
307 pci_read_config_dword(dev
, PCI_CLASS_REVISION
, &class_rev
);
308 pci_read_config_byte (dev
, PCI_LATENCY_TIMER
, &latency
);
309 pci_read_config_byte (dev
, PCI_MIN_GNT
, &min_gnt
);
310 pci_read_config_byte (dev
, PCI_MAX_LAT
, &max_lat
);
311 if (len
+ 160 > size
)
313 len
+= sprintf(buf
+ len
, " Bus %2d, device %3d, function %2d:\n",
314 dev
->bus
->number
, PCI_SLOT(dev
->devfn
), PCI_FUNC(dev
->devfn
));
315 class = pci_class_name(class_rev
>> 16);
317 len
+= sprintf(buf
+len
, " %s", class);
319 len
+= sprintf(buf
+len
, " Class %04x", class_rev
>> 16);
320 len
+= sprintf(buf
+len
, ": %s (rev %d).\n", dev
->name
, class_rev
& 0xff);
325 len
+= sprintf(buf
+ len
, " IRQ %d.\n", dev
->irq
);
328 if (latency
|| min_gnt
|| max_lat
) {
331 len
+= sprintf(buf
+ len
, " Master Capable. ");
333 len
+= sprintf(buf
+ len
, "Latency=%d. ", latency
);
335 len
+= sprintf(buf
+ len
, "No bursts. ");
337 len
+= sprintf(buf
+ len
, "Min Gnt=%d.", min_gnt
);
339 len
+= sprintf(buf
+ len
, "Max Lat=%d.", max_lat
);
340 len
+= sprintf(buf
+ len
, "\n");
343 for (reg
= 0; reg
< 6; reg
++) {
344 struct resource
*res
= dev
->resource
+ reg
;
345 unsigned long base
, end
, flags
;
355 if (flags
& PCI_BASE_ADDRESS_SPACE_IO
) {
356 len
+= sprintf(buf
+ len
,
357 " I/O at 0x%lx [0x%lx].\n",
360 const char *pref
, *type
= "unknown";
362 if (flags
& PCI_BASE_ADDRESS_MEM_PREFETCH
)
366 switch (flags
& PCI_BASE_ADDRESS_MEM_TYPE_MASK
) {
367 case PCI_BASE_ADDRESS_MEM_TYPE_32
:
368 type
= "32 bit"; break;
369 case PCI_BASE_ADDRESS_MEM_TYPE_1M
:
370 type
= "20 bit"; break;
371 case PCI_BASE_ADDRESS_MEM_TYPE_64
:
372 type
= "64 bit"; break;
374 len
+= sprintf(buf
+ len
,
375 " %srefetchable %s memory at "
376 "0x%lx [0x%lx].\n", pref
, type
,
386 * Return list of PCI devices as a character string for /proc/pci.
387 * BUF is a buffer that is PAGE_SIZE bytes long.
389 static int pci_read_proc(char *buf
, char **start
, off_t off
,
390 int count
, int *eof
, void *data
)
392 int nprinted
, len
, begin
= 0;
395 len
= sprintf(buf
, "PCI devices found:\n");
398 pci_for_each_dev(dev
) {
399 nprinted
= sprint_dev_config(dev
, buf
+ len
, PAGE_SIZE
- len
);
405 if (len
+begin
< off
) {
409 if (len
+begin
>= off
+count
)
422 static int __init
pci_proc_init(void)
426 proc_bus_pci_dir
= proc_mkdir("pci", proc_bus
);
427 create_proc_info_entry("devices", 0, proc_bus_pci_dir
,
429 pci_for_each_dev(dev
) {
430 pci_proc_attach_device(dev
);
432 create_proc_read_entry("pci", 0, NULL
, pci_read_proc
, NULL
);
437 __initcall(pci_proc_init
);