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