diff options
Diffstat (limited to 'Documentation/DocBook/uio-howto.tmpl')
-rw-r--r-- | Documentation/DocBook/uio-howto.tmpl | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index 8f6e3b2403c7..4d4ce0e61e42 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl | |||
@@ -25,6 +25,10 @@ | |||
25 | <year>2006-2008</year> | 25 | <year>2006-2008</year> |
26 | <holder>Hans-Jürgen Koch.</holder> | 26 | <holder>Hans-Jürgen Koch.</holder> |
27 | </copyright> | 27 | </copyright> |
28 | <copyright> | ||
29 | <year>2009</year> | ||
30 | <holder>Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)</holder> | ||
31 | </copyright> | ||
28 | 32 | ||
29 | <legalnotice> | 33 | <legalnotice> |
30 | <para> | 34 | <para> |
@@ -42,6 +46,13 @@ GPL version 2. | |||
42 | 46 | ||
43 | <revhistory> | 47 | <revhistory> |
44 | <revision> | 48 | <revision> |
49 | <revnumber>0.9</revnumber> | ||
50 | <date>2009-07-16</date> | ||
51 | <authorinitials>mst</authorinitials> | ||
52 | <revremark>Added generic pci driver | ||
53 | </revremark> | ||
54 | </revision> | ||
55 | <revision> | ||
45 | <revnumber>0.8</revnumber> | 56 | <revnumber>0.8</revnumber> |
46 | <date>2008-12-24</date> | 57 | <date>2008-12-24</date> |
47 | <authorinitials>hjk</authorinitials> | 58 | <authorinitials>hjk</authorinitials> |
@@ -809,6 +820,158 @@ framework to set up sysfs files for this region. Simply leave it alone. | |||
809 | 820 | ||
810 | </chapter> | 821 | </chapter> |
811 | 822 | ||
823 | <chapter id="uio_pci_generic" xreflabel="Using Generic driver for PCI cards"> | ||
824 | <?dbhtml filename="uio_pci_generic.html"?> | ||
825 | <title>Generic PCI UIO driver</title> | ||
826 | <para> | ||
827 | The generic driver is a kernel module named uio_pci_generic. | ||
828 | It can work with any device compliant to PCI 2.3 (circa 2002) and | ||
829 | any compliant PCI Express device. Using this, you only need to | ||
830 | write the userspace driver, removing the need to write | ||
831 | a hardware-specific kernel module. | ||
832 | </para> | ||
833 | |||
834 | <sect1 id="uio_pci_generic_binding"> | ||
835 | <title>Making the driver recognize the device</title> | ||
836 | <para> | ||
837 | Since the driver does not declare any device ids, it will not get loaded | ||
838 | automatically and will not automatically bind to any devices, you must load it | ||
839 | and allocate id to the driver yourself. For example: | ||
840 | <programlisting> | ||
841 | modprobe uio_pci_generic | ||
842 | echo "8086 10f5" > /sys/bus/pci/drivers/uio_pci_generic/new_id | ||
843 | </programlisting> | ||
844 | </para> | ||
845 | <para> | ||
846 | If there already is a hardware specific kernel driver for your device, the | ||
847 | generic driver still won't bind to it, in this case if you want to use the | ||
848 | generic driver (why would you?) you'll have to manually unbind the hardware | ||
849 | specific driver and bind the generic driver, like this: | ||
850 | <programlisting> | ||
851 | echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind | ||
852 | echo -n 0000:00:19.0 > /sys/bus/pci/drivers/uio_pci_generic/bind | ||
853 | </programlisting> | ||
854 | </para> | ||
855 | <para> | ||
856 | You can verify that the device has been bound to the driver | ||
857 | by looking for it in sysfs, for example like the following: | ||
858 | <programlisting> | ||
859 | ls -l /sys/bus/pci/devices/0000:00:19.0/driver | ||
860 | </programlisting> | ||
861 | Which if successful should print | ||
862 | <programlisting> | ||
863 | .../0000:00:19.0/driver -> ../../../bus/pci/drivers/uio_pci_generic | ||
864 | </programlisting> | ||
865 | Note that the generic driver will not bind to old PCI 2.2 devices. | ||
866 | If binding the device failed, run the following command: | ||
867 | <programlisting> | ||
868 | dmesg | ||
869 | </programlisting> | ||
870 | and look in the output for failure reasons | ||
871 | </para> | ||
872 | </sect1> | ||
873 | |||
874 | <sect1 id="uio_pci_generic_internals"> | ||
875 | <title>Things to know about uio_pci_generic</title> | ||
876 | <para> | ||
877 | Interrupts are handled using the Interrupt Disable bit in the PCI command | ||
878 | register and Interrupt Status bit in the PCI status register. All devices | ||
879 | compliant to PCI 2.3 (circa 2002) and all compliant PCI Express devices should | ||
880 | support these bits. uio_pci_generic detects this support, and won't bind to | ||
881 | devices which do not support the Interrupt Disable Bit in the command register. | ||
882 | </para> | ||
883 | <para> | ||
884 | On each interrupt, uio_pci_generic sets the Interrupt Disable bit. | ||
885 | This prevents the device from generating further interrupts | ||
886 | until the bit is cleared. The userspace driver should clear this | ||
887 | bit before blocking and waiting for more interrupts. | ||
888 | </para> | ||
889 | </sect1> | ||
890 | <sect1 id="uio_pci_generic_userspace"> | ||
891 | <title>Writing userspace driver using uio_pci_generic</title> | ||
892 | <para> | ||
893 | Userspace driver can use pci sysfs interface, or the | ||
894 | libpci libray that wraps it, to talk to the device and to | ||
895 | re-enable interrupts by writing to the command register. | ||
896 | </para> | ||
897 | </sect1> | ||
898 | <sect1 id="uio_pci_generic_example"> | ||
899 | <title>Example code using uio_pci_generic</title> | ||
900 | <para> | ||
901 | Here is some sample userspace driver code using uio_pci_generic: | ||
902 | <programlisting> | ||
903 | #include <stdlib.h> | ||
904 | #include <stdio.h> | ||
905 | #include <unistd.h> | ||
906 | #include <sys/types.h> | ||
907 | #include <sys/stat.h> | ||
908 | #include <fcntl.h> | ||
909 | #include <errno.h> | ||
910 | |||
911 | int main() | ||
912 | { | ||
913 | int uiofd; | ||
914 | int configfd; | ||
915 | int err; | ||
916 | int i; | ||
917 | unsigned icount; | ||
918 | unsigned char command_high; | ||
919 | |||
920 | uiofd = open("/dev/uio0", O_RDONLY); | ||
921 | if (uiofd < 0) { | ||
922 | perror("uio open:"); | ||
923 | return errno; | ||
924 | } | ||
925 | configfd = open("/sys/class/uio/uio0/device/config", O_RDWR); | ||
926 | if (uiofd < 0) { | ||
927 | perror("config open:"); | ||
928 | return errno; | ||
929 | } | ||
930 | |||
931 | /* Read and cache command value */ | ||
932 | err = pread(configfd, &command_high, 1, 5); | ||
933 | if (err != 1) { | ||
934 | perror("command config read:"); | ||
935 | return errno; | ||
936 | } | ||
937 | command_high &= ~0x4; | ||
938 | |||
939 | for(i = 0;; ++i) { | ||
940 | /* Print out a message, for debugging. */ | ||
941 | if (i == 0) | ||
942 | fprintf(stderr, "Started uio test driver.\n"); | ||
943 | else | ||
944 | fprintf(stderr, "Interrupts: %d\n", icount); | ||
945 | |||
946 | /****************************************/ | ||
947 | /* Here we got an interrupt from the | ||
948 | device. Do something to it. */ | ||
949 | /****************************************/ | ||
950 | |||
951 | /* Re-enable interrupts. */ | ||
952 | err = pwrite(configfd, &command_high, 1, 5); | ||
953 | if (err != 1) { | ||
954 | perror("config write:"); | ||
955 | break; | ||
956 | } | ||
957 | |||
958 | /* Wait for next interrupt. */ | ||
959 | err = read(uiofd, &icount, 4); | ||
960 | if (err != 4) { | ||
961 | perror("uio read:"); | ||
962 | break; | ||
963 | } | ||
964 | |||
965 | } | ||
966 | return errno; | ||
967 | } | ||
968 | |||
969 | </programlisting> | ||
970 | </para> | ||
971 | </sect1> | ||
972 | |||
973 | </chapter> | ||
974 | |||
812 | <appendix id="app1"> | 975 | <appendix id="app1"> |
813 | <title>Further information</title> | 976 | <title>Further information</title> |
814 | <itemizedlist> | 977 | <itemizedlist> |