1 /* 2 * drivers/pci/pci-sysfs.c 3 * 4 * (C) Copyright 2002-2004 Greg Kroah-Hartman <greg@kroah.com> 5 * (C) Copyright 2002-2004 IBM Corp. 6 * (C) Copyright 2003 Matthew Wilcox 7 * (C) Copyright 2003 Hewlett-Packard 8 * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com> 9 * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com> 10 * 11 * File attributes for PCI devices 12 * 13 * Modeled after usb's driverfs.c 14 * 15 */ 16 17 18 #include <linux/config.h> 19 #include <linux/kernel.h> 20 #include <linux/pci.h> 21 #include <linux/stat.h> 22 #include <linux/topology.h> 23 #include <linux/mm.h> 24 25 #include "pci.h" 26 27 static int sysfs_initialized; /* = 0 */ 28 29 /* show configuration fields */ 30 #define pci_config_attr(field, format_string) \ 31 static ssize_t \ 32 field##_show(struct device *dev, char *buf) \ 33 { \ 34 struct pci_dev *pdev; \ 35 \ 36 pdev = to_pci_dev (dev); \ 37 return sprintf (buf, format_string, pdev->field); \ 38 } 39 40 pci_config_attr(vendor, "0x%04x\n"); 41 pci_config_attr(device, "0x%04x\n"); 42 pci_config_attr(subsystem_vendor, "0x%04x\n"); 43 pci_config_attr(subsystem_device, "0x%04x\n"); 44 pci_config_attr(class, "0x%06x\n"); 45 pci_config_attr(irq, "%u\n"); 46 47 static ssize_t local_cpus_show(struct device *dev, char *buf) 48 { 49 cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus); 50 int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); 51 strcat(buf,"\n"); 52 return 1+len; 53 } 54 55 /* show resources */ 56 static ssize_t 57 resource_show(struct device * dev, char * buf) 58 { 59 struct pci_dev * pci_dev = to_pci_dev(dev); 60 char * str = buf; 61 int i; 62 int max = 7; 63 64 if (pci_dev->subordinate) 65 max = DEVICE_COUNT_RESOURCE; 66 67 for (i = 0; i < max; i++) { 68 str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n", 69 pci_resource_start(pci_dev,i), 70 pci_resource_end(pci_dev,i), 71 pci_resource_flags(pci_dev,i)); 72 } 73 return (str - buf); 74 } 75 76 struct device_attribute pci_dev_attrs[] = { 77 __ATTR_RO(resource), 78 __ATTR_RO(vendor), 79 __ATTR_RO(device), 80 __ATTR_RO(subsystem_vendor), 81 __ATTR_RO(subsystem_device), 82 __ATTR_RO(class), 83 __ATTR_RO(irq), 84 __ATTR_RO(local_cpus), 85 __ATTR_NULL, 86 }; 87 88 static ssize_t 89 pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) 90 { 91 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); 92 unsigned int size = 64; 93 loff_t init_off = off; 94 u8 *data = (u8*) buf; 95 96 /* Several chips lock up trying to read undefined config space */ 97 if (capable(CAP_SYS_ADMIN)) { 98 size = dev->cfg_size; 99 } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { 100 size = 128; 101 } 102 103 if (off > size) 104 return 0; 105 if (off + count > size) { 106 size -= off; 107 count = size; 108 } else { 109 size = count; 110 } 111 112 if ((off & 1) && size) { 113 u8 val; 114 pci_read_config_byte(dev, off, &val); 115 data[off - init_off] = val; 116 off++; 117 size--; 118 } 119 120 if ((off & 3) && size > 2) { 121 u16 val; 122 pci_read_config_word(dev, off, &val); 123 data[off - init_off] = val & 0xff; 124 data[off - init_off + 1] = (val >> 8) & 0xff; 125 off += 2; 126 size -= 2; 127 } 128 129 while (size > 3) { 130 u32 val; 131 pci_read_config_dword(dev, off, &val); 132 data[off - init_off] = val & 0xff; 133 data[off - init_off + 1] = (val >> 8) & 0xff; 134 data[off - init_off + 2] = (val >> 16) & 0xff; 135 data[off - init_off + 3] = (val >> 24) & 0xff; 136 off += 4; 137 size -= 4; 138 } 139 140 if (size >= 2) { 141 u16 val; 142 pci_read_config_word(dev, off, &val); 143 data[off - init_off] = val & 0xff; 144 data[off - init_off + 1] = (val >> 8) & 0xff; 145 off += 2; 146 size -= 2; 147 } 148 149 if (size > 0) { 150 u8 val; 151 pci_read_config_byte(dev, off, &val); 152 data[off - init_off] = val; 153 off++; 154 --size; 155 } 156 157 return count; 158 } 159 160 static ssize_t 161 pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) 162 { 163 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); 164 unsigned int size = count; 165 loff_t init_off = off; 166 u8 *data = (u8*) buf; 167 168 if (off > dev->cfg_size) 169 return 0; 170 if (off + count > dev->cfg_size) { 171 size = dev->cfg_size - off; 172 count = size; 173 } 174 175 if ((off & 1) && size) { 176 pci_write_config_byte(dev, off, data[off - init_off]); 177 off++; 178 size--; 179 } 180 181 if ((off & 3) && size > 2) { 182 u16 val = data[off - init_off]; 183 val |= (u16) data[off - init_off + 1] << 8; 184 pci_write_config_word(dev, off, val); 185 off += 2; 186 size -= 2; 187 } 188 189 while (size > 3) { 190 u32 val = data[off - init_off]; 191 val |= (u32) data[off - init_off + 1] << 8; 192 val |= (u32) data[off - init_off + 2] << 16; 193 val |= (u32) data[off - init_off + 3] << 24; 194 pci_write_config_dword(dev, off, val); 195 off += 4; 196 size -= 4; 197 } 198 199 if (size >= 2) { 200 u16 val = data[off - init_off]; 201 val |= (u16) data[off - init_off + 1] << 8; 202 pci_write_config_word(dev, off, val); 203 off += 2; 204 size -= 2; 205 } 206 207 if (size) { 208 pci_write_config_byte(dev, off, data[off - init_off]); 209 off++; 210 --size; 211 } 212 213 return count; 214 } 215 216 #ifdef HAVE_PCI_LEGACY 217 /** 218 * pci_read_legacy_io - read byte(s) from legacy I/O port space 219 * @kobj: kobject corresponding to file to read from 220 * @buf: buffer to store results 221 * @off: offset into legacy I/O port space 222 * @count: number of bytes to read 223 * 224 * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific 225 * callback routine (pci_legacy_read). 226 */ 227 ssize_t 228 pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) 229 { 230 struct pci_bus *bus = to_pci_bus(container_of(kobj, 231 struct class_device, 232 kobj)); 233 234 /* Only support 1, 2 or 4 byte accesses */ 235 if (count != 1 && count != 2 && count != 4) 236 return -EINVAL; 237 238 return pci_legacy_read(bus, off, (u32 *)buf, count); 239 } 240 241 /** 242 * pci_write_legacy_io - write byte(s) to legacy I/O port space 243 * @kobj: kobject corresponding to file to read from 244 * @buf: buffer containing value to be written 245 * @off: offset into legacy I/O port space 246 * @count: number of bytes to write 247 * 248 * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific 249 * callback routine (pci_legacy_write). 250 */ 251 ssize_t 252 pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) 253 { 254 struct pci_bus *bus = to_pci_bus(container_of(kobj, 255 struct class_device, 256 kobj)); 257 /* Only support 1, 2 or 4 byte accesses */ 258 if (count != 1 && count != 2 && count != 4) 259 return -EINVAL; 260 261 return pci_legacy_write(bus, off, *(u32 *)buf, count); 262 } 263 264 /** 265 * pci_mmap_legacy_mem - map legacy PCI memory into user memory space 266 * @kobj: kobject corresponding to device to be mapped 267 * @attr: struct bin_attribute for this file 268 * @vma: struct vm_area_struct passed to mmap 269 * 270 * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap 271 * legacy memory space (first meg of bus space) into application virtual 272 * memory space. 273 */ 274 int 275 pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, 276 struct vm_area_struct *vma) 277 { 278 struct pci_bus *bus = to_pci_bus(container_of(kobj, 279 struct class_device, 280 kobj)); 281 282 return pci_mmap_legacy_page_range(bus, vma); 283 } 284 #endif /* HAVE_PCI_LEGACY */ 285 286 #ifdef HAVE_PCI_MMAP 287 /** 288 * pci_mmap_resource - map a PCI resource into user memory space 289 * @kobj: kobject for mapping 290 * @attr: struct bin_attribute for the file being mapped 291 * @vma: struct vm_area_struct passed into the mmap 292 * 293 * Use the regular PCI mapping routines to map a PCI resource into userspace. 294 * FIXME: write combining? maybe automatic for prefetchable regions? 295 */ 296 static int 297 pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, 298 struct vm_area_struct *vma) 299 { 300 struct pci_dev *pdev = to_pci_dev(container_of(kobj, 301 struct device, kobj)); 302 struct resource *res = (struct resource *)attr->private; 303 enum pci_mmap_state mmap_type; 304 305 vma->vm_pgoff += res->start >> PAGE_SHIFT; 306 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; 307 308 return pci_mmap_page_range(pdev, vma, mmap_type, 0); 309 } 310 311 /** 312 * pci_create_resource_files - create resource files in sysfs for @dev 313 * @dev: dev in question 314 * 315 * Walk the resources in @dev creating files for each resource available. 316 */ 317 static void 318 pci_create_resource_files(struct pci_dev *pdev) 319 { 320 int i; 321 322 /* Expose the PCI resources from this device as files */ 323 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 324 struct bin_attribute *res_attr; 325 326 /* skip empty resources */ 327 if (!pci_resource_len(pdev, i)) 328 continue; 329 330 res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); 331 if (res_attr) { 332 memset(res_attr, 0, sizeof(*res_attr) + 10); 333 pdev->res_attr[i] = res_attr; 334 /* Allocated above after the res_attr struct */ 335 res_attr->attr.name = (char *)(res_attr + 1); 336 sprintf(res_attr->attr.name, "resource%d", i); 337 res_attr->size = pci_resource_len(pdev, i); 338 res_attr->attr.mode = S_IRUSR | S_IWUSR; 339 res_attr->attr.owner = THIS_MODULE; 340 res_attr->mmap = pci_mmap_resource; 341 res_attr->private = &pdev->resource[i]; 342 sysfs_create_bin_file(&pdev->dev.kobj, res_attr); 343 } 344 } 345 } 346 347 /** 348 * pci_remove_resource_files - cleanup resource files 349 * @dev: dev to cleanup 350 * 351 * If we created resource files for @dev, remove them from sysfs and 352 * free their resources. 353 */ 354 static void 355 pci_remove_resource_files(struct pci_dev *pdev) 356 { 357 int i; 358 359 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 360 struct bin_attribute *res_attr; 361 362 res_attr = pdev->res_attr[i]; 363 if (res_attr) { 364 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); 365 kfree(res_attr); 366 } 367 } 368 } 369 #else /* !HAVE_PCI_MMAP */ 370 static inline void pci_create_resource_files(struct pci_dev *dev) { return; } 371 static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } 372 #endif /* HAVE_PCI_MMAP */ 373 374 /** 375 * pci_write_rom - used to enable access to the PCI ROM display 376 * @kobj: kernel object handle 377 * @buf: user input 378 * @off: file offset 379 * @count: number of byte in input 380 * 381 * writing anything except 0 enables it 382 */ 383 static ssize_t 384 pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) 385 { 386 struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); 387 388 if ((off == 0) && (*buf == '0') && (count == 2)) 389 pdev->rom_attr_enabled = 0; 390 else 391 pdev->rom_attr_enabled = 1; 392 393 return count; 394 } 395 396 /** 397 * pci_read_rom - read a PCI ROM 398 * @kobj: kernel object handle 399 * @buf: where to put the data we read from the ROM 400 * @off: file offset 401 * @count: number of bytes to read 402 * 403 * Put @count bytes starting at @off into @buf from the ROM in the PCI 404 * device corresponding to @kobj. 405 */ 406 static ssize_t 407 pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) 408 { 409 struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); 410 void __iomem *rom; 411 size_t size; 412 413 if (!pdev->rom_attr_enabled) 414 return -EINVAL; 415 416 rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ 417 if (!rom) 418 return 0; 419 420 if (off >= size) 421 count = 0; 422 else { 423 if (off + count > size) 424 count = size - off; 425 426 memcpy_fromio(buf, rom + off, count); 427 } 428 pci_unmap_rom(pdev, rom); 429 430 return count; 431 } 432 433 static struct bin_attribute pci_config_attr = { 434 .attr = { 435 .name = "config", 436 .mode = S_IRUGO | S_IWUSR, 437 .owner = THIS_MODULE, 438 }, 439 .size = 256, 440 .read = pci_read_config, 441 .write = pci_write_config, 442 }; 443 444 static struct bin_attribute pcie_config_attr = { 445 .attr = { 446 .name = "config", 447 .mode = S_IRUGO | S_IWUSR, 448 .owner = THIS_MODULE, 449 }, 450 .size = 4096, 451 .read = pci_read_config, 452 .write = pci_write_config, 453 }; 454 455 int pci_create_sysfs_dev_files (struct pci_dev *pdev) 456 { 457 if (!sysfs_initialized) 458 return -EACCES; 459 460 if (pdev->cfg_size < 4096) 461 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); 462 else 463 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); 464 465 pci_create_resource_files(pdev); 466 467 /* If the device has a ROM, try to expose it in sysfs. */ 468 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 469 struct bin_attribute *rom_attr; 470 471 rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); 472 if (rom_attr) { 473 memset(rom_attr, 0x00, sizeof(*rom_attr)); 474 pdev->rom_attr = rom_attr; 475 rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); 476 rom_attr->attr.name = "rom"; 477 rom_attr->attr.mode = S_IRUSR; 478 rom_attr->attr.owner = THIS_MODULE; 479 rom_attr->read = pci_read_rom; 480 rom_attr->write = pci_write_rom; 481 sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 482 } 483 } 484 /* add platform-specific attributes */ 485 pcibios_add_platform_entries(pdev); 486 487 return 0; 488 } 489 490 /** 491 * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files 492 * @pdev: device whose entries we should free 493 * 494 * Cleanup when @pdev is removed from sysfs. 495 */ 496 void pci_remove_sysfs_dev_files(struct pci_dev *pdev) 497 { 498 if (pdev->cfg_size < 4096) 499 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); 500 else 501 sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); 502 503 pci_remove_resource_files(pdev); 504 505 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 506 if (pdev->rom_attr) { 507 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); 508 kfree(pdev->rom_attr); 509 } 510 } 511 } 512 513 static int __init pci_sysfs_init(void) 514 { 515 struct pci_dev *pdev = NULL; 516 517 sysfs_initialized = 1; 518 for_each_pci_dev(pdev) 519 pci_create_sysfs_dev_files(pdev); 520 521 return 0; 522 } 523 524 __initcall(pci_sysfs_init); 525