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