Subversion Repositories shark

Rev

Rev 587 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
587 giacomo 1
/*
2
 *      pci_syscall.c
3
 *
4
 * For architectures where we want to allow direct access
5
 * to the PCI config stuff - it would probably be preferable
6
 * on PCs too, but there people just do it by hand with the
7
 * magic northbridge registers..
8
 */
9
 
10
#include <linuxcomp.h>
11
 
12
#include <linux/sched.h>
13
#include <linux/errno.h>
14
#include <linux/pci.h>
15
#include <linux/smp_lock.h>
16
#include <asm/uaccess.h>
17
 
18
 
19
asmlinkage long
20
sys_pciconfig_read(unsigned long bus, unsigned long dfn,
21
                   unsigned long off, unsigned long len, void *buf)
22
{
23
        struct pci_dev *dev;
24
        u8 byte;
25
        u16 word;
26
        u32 dword;
27
        long err, cfg_ret;
28
 
29
        err = -EPERM;
30
        if (!capable(CAP_SYS_ADMIN))
31
                goto error;
32
 
33
        err = -ENODEV;
34
        dev = pci_find_slot(bus, dfn);
35
        if (!dev)
36
                goto error;
37
 
38
        lock_kernel();
39
        switch (len) {
40
        case 1:
41
                cfg_ret = pci_read_config_byte(dev, off, &byte);
42
                break;
43
        case 2:
44
                cfg_ret = pci_read_config_word(dev, off, &word);
45
                break;
46
        case 4:
47
                cfg_ret = pci_read_config_dword(dev, off, &dword);
48
                break;
49
        default:
50
                err = -EINVAL;
51
                unlock_kernel();
52
                goto error;
53
        };
54
        unlock_kernel();
55
 
56
        err = -EIO;
57
        if (cfg_ret != PCIBIOS_SUCCESSFUL)
58
                goto error;
59
 
60
        switch (len) {
61
        case 1:
62
                err = put_user(byte, (unsigned char *)buf);
63
                break;
64
        case 2:
65
                err = put_user(word, (unsigned short *)buf);
66
                break;
67
        case 4:
68
                err = put_user(dword, (unsigned int *)buf);
69
                break;
70
        };
71
        return err;
72
 
73
error:
74
        /* ??? XFree86 doesn't even check the return value.  They
75
           just look for 0xffffffff in the output, since that's what
76
           they get instead of a machine check on x86.  */
77
        switch (len) {
78
        case 1:
79
                put_user(-1, (unsigned char *)buf);
80
                break;
81
        case 2:
82
                put_user(-1, (unsigned short *)buf);
83
                break;
84
        case 4:
85
                put_user(-1, (unsigned int *)buf);
86
                break;
87
        };
88
        return err;
89
}
90
 
91
asmlinkage long
92
sys_pciconfig_write(unsigned long bus, unsigned long dfn,
93
                    unsigned long off, unsigned long len, void *buf)
94
{
95
        struct pci_dev *dev;
96
        u8 byte;
97
        u16 word;
98
        u32 dword;
99
        int err = 0;
100
 
101
        if (!capable(CAP_SYS_ADMIN))
102
                return -EPERM;
103
 
104
        dev = pci_find_slot(bus, dfn);
105
        if (!dev)
106
                return -ENODEV;
107
 
108
        lock_kernel();
109
        switch(len) {
110
        case 1:
111
                err = get_user(byte, (u8 *)buf);
112
                if (err)
113
                        break;
114
                err = pci_write_config_byte(dev, off, byte);
115
                if (err != PCIBIOS_SUCCESSFUL)
116
                        err = -EIO;
117
                break;
118
 
119
        case 2:
120
                err = get_user(word, (u16 *)buf);
121
                if (err)
122
                        break;
123
                err = pci_write_config_word(dev, off, word);
124
                if (err != PCIBIOS_SUCCESSFUL)
125
                        err = -EIO;
126
                break;
127
 
128
        case 4:
129
                err = get_user(dword, (u32 *)buf);
130
                if (err)
131
                        break;
132
                err = pci_write_config_dword(dev, off, dword);
133
                if (err != PCIBIOS_SUCCESSFUL)
134
                        err = -EIO;
135
                break;
136
 
137
        default:
138
                err = -EINVAL;
139
                break;
140
        };
141
        unlock_kernel();
142
 
143
        return err;
144
}