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
)) 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 intpci_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 intpci_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 intsprint_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
); 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 intpci_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
);