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 <linux/errno.h> 11 #include <linux/pci.h> 12 #include <linux/smp_lock.h> 13 #include <linux/syscalls.h> 14 #include <asm/uaccess.h> 15 #include "pci.h" 16 17 asmlinkage long 18 sys_pciconfig_read(unsigned long bus, unsigned long dfn, 19 unsigned long off, unsigned long len, 20 void __user *buf) 21 { 22 struct pci_dev *dev; 23 u8 byte; 24 u16 word; 25 u32 dword; 26 long err; 27 long cfg_ret; 28 29 if (!capable(CAP_SYS_ADMIN)) 30 return -EPERM; 31 32 err = -ENODEV; 33 dev = pci_get_bus_and_slot(bus, dfn); 34 if (!dev) 35 goto error; 36 37 switch (len) { 38 case 1: 39 cfg_ret = pci_user_read_config_byte(dev, off, &byte); 40 break; 41 case 2: 42 cfg_ret = pci_user_read_config_word(dev, off, &word); 43 break; 44 case 4: 45 cfg_ret = pci_user_read_config_dword(dev, off, &dword); 46 break; 47 default: 48 err = -EINVAL; 49 goto error; 50 }; 51 52 err = -EIO; 53 if (cfg_ret != PCIBIOS_SUCCESSFUL) 54 goto error; 55 56 switch (len) { 57 case 1: 58 err = put_user(byte, (unsigned char __user *)buf); 59 break; 60 case 2: 61 err = put_user(word, (unsigned short __user *)buf); 62 break; 63 case 4: 64 err = put_user(dword, (unsigned int __user *)buf); 65 break; 66 } 67 pci_dev_put(dev); 68 return err; 69 70 error: 71 /* ??? XFree86 doesn't even check the return value. They 72 just look for 0xffffffff in the output, since that's what 73 they get instead of a machine check on x86. */ 74 switch (len) { 75 case 1: 76 put_user(-1, (unsigned char __user *)buf); 77 break; 78 case 2: 79 put_user(-1, (unsigned short __user *)buf); 80 break; 81 case 4: 82 put_user(-1, (unsigned int __user *)buf); 83 break; 84 } 85 pci_dev_put(dev); 86 return err; 87 } 88 89 asmlinkage long 90 sys_pciconfig_write(unsigned long bus, unsigned long dfn, 91 unsigned long off, unsigned long len, 92 void __user *buf) 93 { 94 struct pci_dev *dev; 95 u8 byte; 96 u16 word; 97 u32 dword; 98 int err = 0; 99 100 if (!capable(CAP_SYS_ADMIN)) 101 return -EPERM; 102 103 dev = pci_get_bus_and_slot(bus, dfn); 104 if (!dev) 105 return -ENODEV; 106 107 switch(len) { 108 case 1: 109 err = get_user(byte, (u8 __user *)buf); 110 if (err) 111 break; 112 err = pci_user_write_config_byte(dev, off, byte); 113 if (err != PCIBIOS_SUCCESSFUL) 114 err = -EIO; 115 break; 116 117 case 2: 118 err = get_user(word, (u16 __user *)buf); 119 if (err) 120 break; 121 err = pci_user_write_config_word(dev, off, word); 122 if (err != PCIBIOS_SUCCESSFUL) 123 err = -EIO; 124 break; 125 126 case 4: 127 err = get_user(dword, (u32 __user *)buf); 128 if (err) 129 break; 130 err = pci_user_write_config_dword(dev, off, dword); 131 if (err != PCIBIOS_SUCCESSFUL) 132 err = -EIO; 133 break; 134 135 default: 136 err = -EINVAL; 137 break; 138 } 139 pci_dev_put(dev); 140 return err; 141 } 142