syscall.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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