home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lxapi32.zip / Linux / PCI / syscall.c < prev   
C/C++ Source or Header  |  2000-01-12  |  3KB  |  145 lines

  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/sched.h>
  11. #include <linux/errno.h>
  12. #include <linux/pci.h>
  13. #include <linux/smp_lock.h>
  14. #include <asm/uaccess.h>
  15.  
  16.  
  17. asmlinkage long
  18. sys_pciconfig_read(unsigned long bus, unsigned long dfn,
  19.            unsigned long off, unsigned long len, void *buf)
  20. {
  21.     struct pci_dev *dev;
  22.     u8 byte;
  23.     u16 word;
  24.     u32 dword;
  25.     long err, cfg_ret;
  26.  
  27.     err = -EPERM;
  28.     if (!capable(CAP_SYS_ADMIN))
  29.         goto error;
  30.  
  31.     err = -ENODEV;
  32.     dev = pci_find_slot(bus, dfn);
  33.     if (!dev)
  34.         goto error;
  35.  
  36.     lock_kernel();
  37.     switch (len) {
  38.     case 1:
  39.         cfg_ret = pci_read_config_byte(dev, off, &byte);
  40.         break;
  41.     case 2:
  42.         cfg_ret = pci_read_config_word(dev, off, &word);
  43.         break;
  44.     case 4:
  45.         cfg_ret = pci_read_config_dword(dev, off, &dword);
  46.         break;
  47.     default:
  48.         err = -EINVAL;
  49.         unlock_kernel();
  50.         goto error;
  51.     };
  52.     unlock_kernel();
  53.  
  54.     err = -EIO;
  55.     if (cfg_ret != PCIBIOS_SUCCESSFUL)
  56.         goto error;
  57.  
  58.     switch (len) {
  59.     case 1:
  60.         err = put_user(byte, (unsigned char *)buf);
  61.         break;
  62.     case 2:
  63.         err = put_user(word, (unsigned short *)buf);
  64.         break;
  65.     case 4:
  66.         err = put_user(dword, (unsigned int *)buf);
  67.         break;
  68.     };
  69.     return err;
  70.  
  71. error:
  72.     /* ??? XFree86 doesn't even check the return value.  They
  73.        just look for 0xffffffff in the output, since that's what
  74.        they get instead of a machine check on x86.  */
  75.     switch (len) {
  76.     case 1:
  77.         put_user(-1, (unsigned char *)buf);
  78.         break;
  79.     case 2:
  80.         put_user(-1, (unsigned short *)buf);
  81.         break;
  82.     case 4:
  83.         put_user(-1, (unsigned int *)buf);
  84.         break;
  85.     };
  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, void *buf)
  92. {
  93.     struct pci_dev *dev;
  94.     u8 byte;
  95.     u16 word;
  96.     u32 dword;
  97.     int err = 0;
  98.  
  99.     if (!capable(CAP_SYS_ADMIN))
  100.         return -EPERM;
  101.     if (!pcibios_present())
  102.         return -ENOSYS;
  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. }
  145.