Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
428 giacomo 1
/*
2
 * drivers/pci/pci-sysfs.c
3
 *
4
 * (C) Copyright 2002 Greg Kroah-Hartman
5
 * (C) Copyright 2002 IBM Corp.
6
 * (C) Copyright 2003 Matthew Wilcox
7
 * (C) Copyright 2003 Hewlett-Packard
8
 *
9
 * File attributes for PCI devices
10
 *
11
 * Modeled after usb's driverfs.c
12
 *
13
 */
14
 
15
 
16
#include <linux/config.h>
17
#include <linux/kernel.h>
18
#include <linux/pci.h>
19
#include <linux/stat.h>
20
 
21
#include "pci.h"
22
 
23
/* show configuration fields */
24
#define pci_config_attr(field, format_string)                           \
25
static ssize_t                                                          \
26
show_##field (struct device *dev, char *buf)                            \
27
{                                                                       \
28
        struct pci_dev *pdev;                                           \
29
                                                                        \
30
        pdev = to_pci_dev (dev);                                        \
31
        return sprintf (buf, format_string, pdev->field);               \
32
}                                                                       \
33
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
34
 
35
pci_config_attr(vendor, "0x%04x\n");
36
pci_config_attr(device, "0x%04x\n");
37
pci_config_attr(subsystem_vendor, "0x%04x\n");
38
pci_config_attr(subsystem_device, "0x%04x\n");
39
pci_config_attr(class, "0x%06x\n");
40
pci_config_attr(irq, "%u\n");
41
 
42
/* show resources */
43
static ssize_t
44
pci_show_resources(struct device * dev, char * buf)
45
{
46
        struct pci_dev * pci_dev = to_pci_dev(dev);
47
        char * str = buf;
48
        int i;
49
        int max = 7;
50
 
51
        if (pci_dev->subordinate)
52
                max = DEVICE_COUNT_RESOURCE;
53
 
54
        for (i = 0; i < max; i++) {
55
                str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
56
                               pci_resource_start(pci_dev,i),
57
                               pci_resource_end(pci_dev,i),
58
                               pci_resource_flags(pci_dev,i));
59
        }
60
        return (str - buf);
61
}
62
 
63
static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
64
 
65
static ssize_t
66
pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
67
{
68
        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
69
        unsigned int size = 64;
70
        loff_t init_off = off;
71
 
72
        /* Several chips lock up trying to read undefined config space */
73
        if (capable(CAP_SYS_ADMIN)) {
74
                size = 256;
75
        } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
76
                size = 128;
77
        }
78
 
79
        if (off > size)
80
                return 0;
81
        if (off + count > size) {
82
                size -= off;
83
                count = size;
84
        } else {
85
                size = count;
86
        }
87
 
88
        while (off & 3) {
89
                unsigned char val;
90
                pci_read_config_byte(dev, off, &val);
91
                buf[off - init_off] = val;
92
                off++;
93
                if (--size == 0)
94
                        break;
95
        }
96
 
97
        while (size > 3) {
98
                unsigned int val;
99
                pci_read_config_dword(dev, off, &val);
100
                buf[off - init_off] = val & 0xff;
101
                buf[off - init_off + 1] = (val >> 8) & 0xff;
102
                buf[off - init_off + 2] = (val >> 16) & 0xff;
103
                buf[off - init_off + 3] = (val >> 24) & 0xff;
104
                off += 4;
105
                size -= 4;
106
        }
107
 
108
        while (size > 0) {
109
                unsigned char val;
110
                pci_read_config_byte(dev, off, &val);
111
                buf[off - init_off] = val;
112
                off++;
113
                --size;
114
        }
115
 
116
        return count;
117
}
118
 
119
static ssize_t
120
pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
121
{
122
        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
123
        unsigned int size = count;
124
        loff_t init_off = off;
125
 
126
        if (off > 256)
127
                return 0;
128
        if (off + count > 256) {
129
                size = 256 - off;
130
                count = size;
131
        }
132
 
133
        while (off & 3) {
134
                pci_write_config_byte(dev, off, buf[off - init_off]);
135
                off++;
136
                if (--size == 0)
137
                        break;
138
        }
139
 
140
        while (size > 3) {
141
                unsigned int val = buf[off - init_off];
142
                val |= (unsigned int) buf[off - init_off + 1] << 8;
143
                val |= (unsigned int) buf[off - init_off + 2] << 16;
144
                val |= (unsigned int) buf[off - init_off + 3] << 24;
145
                pci_write_config_dword(dev, off, val);
146
                off += 4;
147
                size -= 4;
148
        }
149
 
150
        while (size > 0) {
151
                pci_write_config_byte(dev, off, buf[off - init_off]);
152
                off++;
153
                --size;
154
        }
155
 
156
        return count;
157
}
158
 
159
static struct bin_attribute pci_config_attr = {
160
        .attr = {
161
                .name = "config",
162
                .mode = S_IRUGO | S_IWUSR,
163
        },
164
        .size = 256,
165
        .read = pci_read_config,
166
        .write = pci_write_config,
167
};
168
 
169
void pci_create_sysfs_dev_files (struct pci_dev *pdev)
170
{
171
        struct device *dev = &pdev->dev;
172
 
173
        /* current configuration's attributes */
174
        device_create_file (dev, &dev_attr_vendor);
175
        device_create_file (dev, &dev_attr_device);
176
        device_create_file (dev, &dev_attr_subsystem_vendor);
177
        device_create_file (dev, &dev_attr_subsystem_device);
178
        device_create_file (dev, &dev_attr_class);
179
        device_create_file (dev, &dev_attr_irq);
180
        device_create_file (dev, &dev_attr_resource);
181
        sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
182
}