OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [drivers/] [pci/] [proc.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *      $Id: proc.c,v 1.13 1998/05/12 07:36:07 mj Exp $
3
 *
4
 *      Procfs interface for the PCI bus.
5
 *
6
 *      Copyright (c) 1997--1999 Martin Mares <mj@ucw.cz>
7
 */
8
 
9
#include <linux/init.h>
10
#include <linux/pci.h>
11
#include <linux/module.h>
12
#include <linux/proc_fs.h>
13
#include <linux/seq_file.h>
14
#include <linux/capability.h>
15
#include <asm/uaccess.h>
16
#include <asm/byteorder.h>
17
#include "pci.h"
18
 
19
static int proc_initialized;    /* = 0 */
20
 
21
static loff_t
22
proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
23
{
24
        loff_t new = -1;
25
        struct inode *inode = file->f_path.dentry->d_inode;
26
 
27
        mutex_lock(&inode->i_mutex);
28
        switch (whence) {
29
        case 0:
30
                new = off;
31
                break;
32
        case 1:
33
                new = file->f_pos + off;
34
                break;
35
        case 2:
36
                new = inode->i_size + off;
37
                break;
38
        }
39
        if (new < 0 || new > inode->i_size)
40
                new = -EINVAL;
41
        else
42
                file->f_pos = new;
43
        mutex_unlock(&inode->i_mutex);
44
        return new;
45
}
46
 
47
static ssize_t
48
proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
49
{
50
        const struct inode *ino = file->f_path.dentry->d_inode;
51
        const struct proc_dir_entry *dp = PDE(ino);
52
        struct pci_dev *dev = dp->data;
53
        unsigned int pos = *ppos;
54
        unsigned int cnt, size;
55
 
56
        /*
57
         * Normal users can read only the standardized portion of the
58
         * configuration space as several chips lock up when trying to read
59
         * undefined locations (think of Intel PIIX4 as a typical example).
60
         */
61
 
62
        if (capable(CAP_SYS_ADMIN))
63
                size = dp->size;
64
        else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
65
                size = 128;
66
        else
67
                size = 64;
68
 
69
        if (pos >= size)
70
                return 0;
71
        if (nbytes >= size)
72
                nbytes = size;
73
        if (pos + nbytes > size)
74
                nbytes = size - pos;
75
        cnt = nbytes;
76
 
77
        if (!access_ok(VERIFY_WRITE, buf, cnt))
78
                return -EINVAL;
79
 
80
        if ((pos & 1) && cnt) {
81
                unsigned char val;
82
                pci_user_read_config_byte(dev, pos, &val);
83
                __put_user(val, buf);
84
                buf++;
85
                pos++;
86
                cnt--;
87
        }
88
 
89
        if ((pos & 3) && cnt > 2) {
90
                unsigned short val;
91
                pci_user_read_config_word(dev, pos, &val);
92
                __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
93
                buf += 2;
94
                pos += 2;
95
                cnt -= 2;
96
        }
97
 
98
        while (cnt >= 4) {
99
                unsigned int val;
100
                pci_user_read_config_dword(dev, pos, &val);
101
                __put_user(cpu_to_le32(val), (unsigned int __user *) buf);
102
                buf += 4;
103
                pos += 4;
104
                cnt -= 4;
105
        }
106
 
107
        if (cnt >= 2) {
108
                unsigned short val;
109
                pci_user_read_config_word(dev, pos, &val);
110
                __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
111
                buf += 2;
112
                pos += 2;
113
                cnt -= 2;
114
        }
115
 
116
        if (cnt) {
117
                unsigned char val;
118
                pci_user_read_config_byte(dev, pos, &val);
119
                __put_user(val, buf);
120
                buf++;
121
                pos++;
122
                cnt--;
123
        }
124
 
125
        *ppos = pos;
126
        return nbytes;
127
}
128
 
129
static ssize_t
130
proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
131
{
132
        struct inode *ino = file->f_path.dentry->d_inode;
133
        const struct proc_dir_entry *dp = PDE(ino);
134
        struct pci_dev *dev = dp->data;
135
        int pos = *ppos;
136
        int size = dp->size;
137
        int cnt;
138
 
139
        if (pos >= size)
140
                return 0;
141
        if (nbytes >= size)
142
                nbytes = size;
143
        if (pos + nbytes > size)
144
                nbytes = size - pos;
145
        cnt = nbytes;
146
 
147
        if (!access_ok(VERIFY_READ, buf, cnt))
148
                return -EINVAL;
149
 
150
        if ((pos & 1) && cnt) {
151
                unsigned char val;
152
                __get_user(val, buf);
153
                pci_user_write_config_byte(dev, pos, val);
154
                buf++;
155
                pos++;
156
                cnt--;
157
        }
158
 
159
        if ((pos & 3) && cnt > 2) {
160
                unsigned short val;
161
                __get_user(val, (unsigned short __user *) buf);
162
                pci_user_write_config_word(dev, pos, le16_to_cpu(val));
163
                buf += 2;
164
                pos += 2;
165
                cnt -= 2;
166
        }
167
 
168
        while (cnt >= 4) {
169
                unsigned int val;
170
                __get_user(val, (unsigned int __user *) buf);
171
                pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
172
                buf += 4;
173
                pos += 4;
174
                cnt -= 4;
175
        }
176
 
177
        if (cnt >= 2) {
178
                unsigned short val;
179
                __get_user(val, (unsigned short __user *) buf);
180
                pci_user_write_config_word(dev, pos, le16_to_cpu(val));
181
                buf += 2;
182
                pos += 2;
183
                cnt -= 2;
184
        }
185
 
186
        if (cnt) {
187
                unsigned char val;
188
                __get_user(val, buf);
189
                pci_user_write_config_byte(dev, pos, val);
190
                buf++;
191
                pos++;
192
                cnt--;
193
        }
194
 
195
        *ppos = pos;
196
        i_size_write(ino, dp->size);
197
        return nbytes;
198
}
199
 
200
struct pci_filp_private {
201
        enum pci_mmap_state mmap_state;
202
        int write_combine;
203
};
204
 
205
static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
206
{
207
        const struct proc_dir_entry *dp = PDE(inode);
208
        struct pci_dev *dev = dp->data;
209
#ifdef HAVE_PCI_MMAP
210
        struct pci_filp_private *fpriv = file->private_data;
211
#endif /* HAVE_PCI_MMAP */
212
        int ret = 0;
213
 
214
        switch (cmd) {
215
        case PCIIOC_CONTROLLER:
216
                ret = pci_domain_nr(dev->bus);
217
                break;
218
 
219
#ifdef HAVE_PCI_MMAP
220
        case PCIIOC_MMAP_IS_IO:
221
                fpriv->mmap_state = pci_mmap_io;
222
                break;
223
 
224
        case PCIIOC_MMAP_IS_MEM:
225
                fpriv->mmap_state = pci_mmap_mem;
226
                break;
227
 
228
        case PCIIOC_WRITE_COMBINE:
229
                if (arg)
230
                        fpriv->write_combine = 1;
231
                else
232
                        fpriv->write_combine = 0;
233
                break;
234
 
235
#endif /* HAVE_PCI_MMAP */
236
 
237
        default:
238
                ret = -EINVAL;
239
                break;
240
        };
241
 
242
        return ret;
243
}
244
 
245
#ifdef HAVE_PCI_MMAP
246
static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
247
{
248
        struct inode *inode = file->f_path.dentry->d_inode;
249
        const struct proc_dir_entry *dp = PDE(inode);
250
        struct pci_dev *dev = dp->data;
251
        struct pci_filp_private *fpriv = file->private_data;
252
        int ret;
253
 
254
        if (!capable(CAP_SYS_RAWIO))
255
                return -EPERM;
256
 
257
        ret = pci_mmap_page_range(dev, vma,
258
                                  fpriv->mmap_state,
259
                                  fpriv->write_combine);
260
        if (ret < 0)
261
                return ret;
262
 
263
        return 0;
264
}
265
 
266
static int proc_bus_pci_open(struct inode *inode, struct file *file)
267
{
268
        struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
269
 
270
        if (!fpriv)
271
                return -ENOMEM;
272
 
273
        fpriv->mmap_state = pci_mmap_io;
274
        fpriv->write_combine = 0;
275
 
276
        file->private_data = fpriv;
277
 
278
        return 0;
279
}
280
 
281
static int proc_bus_pci_release(struct inode *inode, struct file *file)
282
{
283
        kfree(file->private_data);
284
        file->private_data = NULL;
285
 
286
        return 0;
287
}
288
#endif /* HAVE_PCI_MMAP */
289
 
290
static const struct file_operations proc_bus_pci_operations = {
291
        .llseek         = proc_bus_pci_lseek,
292
        .read           = proc_bus_pci_read,
293
        .write          = proc_bus_pci_write,
294
        .ioctl          = proc_bus_pci_ioctl,
295
#ifdef HAVE_PCI_MMAP
296
        .open           = proc_bus_pci_open,
297
        .release        = proc_bus_pci_release,
298
        .mmap           = proc_bus_pci_mmap,
299
#ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
300
        .get_unmapped_area = get_pci_unmapped_area,
301
#endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
302
#endif /* HAVE_PCI_MMAP */
303
};
304
 
305
/* iterator */
306
static void *pci_seq_start(struct seq_file *m, loff_t *pos)
307
{
308
        struct pci_dev *dev = NULL;
309
        loff_t n = *pos;
310
 
311
        for_each_pci_dev(dev) {
312
                if (!n--)
313
                        break;
314
        }
315
        return dev;
316
}
317
 
318
static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
319
{
320
        struct pci_dev *dev = v;
321
 
322
        (*pos)++;
323
        dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
324
        return dev;
325
}
326
 
327
static void pci_seq_stop(struct seq_file *m, void *v)
328
{
329
        if (v) {
330
                struct pci_dev *dev = v;
331
                pci_dev_put(dev);
332
        }
333
}
334
 
335
static int show_device(struct seq_file *m, void *v)
336
{
337
        const struct pci_dev *dev = v;
338
        const struct pci_driver *drv;
339
        int i;
340
 
341
        if (dev == NULL)
342
                return 0;
343
 
344
        drv = pci_dev_driver(dev);
345
        seq_printf(m, "%02x%02x\t%04x%04x\t%x",
346
                        dev->bus->number,
347
                        dev->devfn,
348
                        dev->vendor,
349
                        dev->device,
350
                        dev->irq);
351
        /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
352
        for (i=0; i<7; i++) {
353
                resource_size_t start, end;
354
                pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
355
                seq_printf(m, "\t%16llx",
356
                        (unsigned long long)(start |
357
                        (dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
358
        }
359
        for (i=0; i<7; i++) {
360
                resource_size_t start, end;
361
                pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
362
                seq_printf(m, "\t%16llx",
363
                        dev->resource[i].start < dev->resource[i].end ?
364
                        (unsigned long long)(end - start) + 1 : 0);
365
        }
366
        seq_putc(m, '\t');
367
        if (drv)
368
                seq_printf(m, "%s", drv->name);
369
        seq_putc(m, '\n');
370
        return 0;
371
}
372
 
373
static struct seq_operations proc_bus_pci_devices_op = {
374
        .start  = pci_seq_start,
375
        .next   = pci_seq_next,
376
        .stop   = pci_seq_stop,
377
        .show   = show_device
378
};
379
 
380
static struct proc_dir_entry *proc_bus_pci_dir;
381
 
382
int pci_proc_attach_device(struct pci_dev *dev)
383
{
384
        struct pci_bus *bus = dev->bus;
385
        struct proc_dir_entry *e;
386
        char name[16];
387
 
388
        if (!proc_initialized)
389
                return -EACCES;
390
 
391
        if (!bus->procdir) {
392
                if (pci_proc_domain(bus)) {
393
                        sprintf(name, "%04x:%02x", pci_domain_nr(bus),
394
                                        bus->number);
395
                } else {
396
                        sprintf(name, "%02x", bus->number);
397
                }
398
                bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
399
                if (!bus->procdir)
400
                        return -ENOMEM;
401
        }
402
 
403
        sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
404
        e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir);
405
        if (!e)
406
                return -ENOMEM;
407
        e->proc_fops = &proc_bus_pci_operations;
408
        e->data = dev;
409
        e->size = dev->cfg_size;
410
        dev->procent = e;
411
 
412
        return 0;
413
}
414
 
415
int pci_proc_detach_device(struct pci_dev *dev)
416
{
417
        struct proc_dir_entry *e;
418
 
419
        if ((e = dev->procent)) {
420
                if (atomic_read(&e->count))
421
                        return -EBUSY;
422
                remove_proc_entry(e->name, dev->bus->procdir);
423
                dev->procent = NULL;
424
        }
425
        return 0;
426
}
427
 
428
#if 0
429
int pci_proc_attach_bus(struct pci_bus* bus)
430
{
431
        struct proc_dir_entry *de = bus->procdir;
432
 
433
        if (!proc_initialized)
434
                return -EACCES;
435
 
436
        if (!de) {
437
                char name[16];
438
                sprintf(name, "%02x", bus->number);
439
                de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
440
                if (!de)
441
                        return -ENOMEM;
442
        }
443
        return 0;
444
}
445
#endif  /*  0  */
446
 
447
int pci_proc_detach_bus(struct pci_bus* bus)
448
{
449
        struct proc_dir_entry *de = bus->procdir;
450
        if (de)
451
                remove_proc_entry(de->name, proc_bus_pci_dir);
452
        return 0;
453
}
454
 
455
static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
456
{
457
        return seq_open(file, &proc_bus_pci_devices_op);
458
}
459
static const struct file_operations proc_bus_pci_dev_operations = {
460
        .open           = proc_bus_pci_dev_open,
461
        .read           = seq_read,
462
        .llseek         = seq_lseek,
463
        .release        = seq_release,
464
};
465
 
466
static int __init pci_proc_init(void)
467
{
468
        struct proc_dir_entry *entry;
469
        struct pci_dev *dev = NULL;
470
        proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
471
        entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
472
        if (entry)
473
                entry->proc_fops = &proc_bus_pci_dev_operations;
474
        proc_initialized = 1;
475
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
476
                pci_proc_attach_device(dev);
477
        }
478
        return 0;
479
}
480
 
481
__initcall(pci_proc_init);
482
 
483
#ifdef CONFIG_HOTPLUG
484
EXPORT_SYMBOL(pci_proc_detach_bus);
485
#endif
486
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.