2 * drivers/pci/pci-sysfs.c
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
9 * File attributes for PCI devices
11 * Modeled after usb's driverfs.c
16 #include <linux/config.h>
17 #include <linux/kernel.h>
18 #include <linux/pci.h>
19 #include <linux/stat.h>
23 /* show configuration fields */
24 #define pci_config_attr(field, format_string) \
26 field##_show(struct device *dev, char *buf) \
28 struct pci_dev *pdev; \
30 pdev = to_pci_dev (dev); \
31 return sprintf (buf, format_string, pdev->field); \
34 pci_config_attr(vendor, "0x%04x\n");
35 pci_config_attr(device, "0x%04x\n");
36 pci_config_attr(subsystem_vendor, "0x%04x\n");
37 pci_config_attr(subsystem_device, "0x%04x\n");
38 pci_config_attr(class, "0x%06x\n");
39 pci_config_attr(irq, "%u\n");
43 resource_show(struct device * dev, char * buf)
45 struct pci_dev * pci_dev = to_pci_dev(dev);
50 if (pci_dev->subordinate)
51 max = DEVICE_COUNT_RESOURCE;
53 for (i = 0; i < max; i++) {
54 str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
55 pci_resource_start(pci_dev,i),
56 pci_resource_end(pci_dev,i),
57 pci_resource_flags(pci_dev,i));
62 struct device_attribute pci_dev_attrs[] = {
66 __ATTR_RO(subsystem_vendor),
67 __ATTR_RO(subsystem_device),
74 pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
76 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
77 unsigned int size = 64;
78 loff_t init_off = off;
80 /* Several chips lock up trying to read undefined config space */
81 if (capable(CAP_SYS_ADMIN)) {
83 } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
89 if (off + count > size) {
98 pci_read_config_byte(dev, off, &val);
99 buf[off - init_off] = val;
107 pci_read_config_dword(dev, off, &val);
108 buf[off - init_off] = val & 0xff;
109 buf[off - init_off + 1] = (val >> 8) & 0xff;
110 buf[off - init_off + 2] = (val >> 16) & 0xff;
111 buf[off - init_off + 3] = (val >> 24) & 0xff;
118 pci_read_config_byte(dev, off, &val);
119 buf[off - init_off] = val;
128 pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
130 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
131 unsigned int size = count;
132 loff_t init_off = off;
134 if (off > dev->cfg_size)
136 if (off + count > dev->cfg_size) {
137 size = dev->cfg_size - off;
142 pci_write_config_byte(dev, off, buf[off - init_off]);
149 unsigned int val = buf[off - init_off];
150 val |= (unsigned int) buf[off - init_off + 1] << 8;
151 val |= (unsigned int) buf[off - init_off + 2] << 16;
152 val |= (unsigned int) buf[off - init_off + 3] << 24;
153 pci_write_config_dword(dev, off, val);
159 pci_write_config_byte(dev, off, buf[off - init_off]);
167 static struct bin_attribute pci_config_attr = {
170 .mode = S_IRUGO | S_IWUSR,
171 .owner = THIS_MODULE,
174 .read = pci_read_config,
175 .write = pci_write_config,
178 static struct bin_attribute pcie_config_attr = {
181 .mode = S_IRUGO | S_IWUSR,
182 .owner = THIS_MODULE,
185 .read = pci_read_config,
186 .write = pci_write_config,
189 void pci_create_sysfs_dev_files (struct pci_dev *pdev)
191 if (pdev->cfg_size < 4096)
192 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
194 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
196 /* add platform-specific attributes */
197 pcibios_add_platform_entries(pdev);