home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / BURKS / LINUX / HOWTO / mini / ioport.txt < prev    next >
Text File  |  1997-07-07  |  22KB  |  490 lines

  1.  
  2.         Linux I/O port programming mini-HOWTO
  3.  
  4.         Author: Riku Saikkonen <Riku.Saikkonen@hut.fi>
  5.         Last modified: Mar 30 1997
  6.  
  7. This document is Copyright 1995-1997 Riku Saikkonen. See the normal Linux
  8. HOWTO COPYRIGHT for details.
  9.  
  10.  
  11. This HOWTO document describes programming hardware I/O ports and waiting for
  12. small periods of time in user-mode Linux programs running on an Intel x86
  13. processor. This document is a descendant of the very small IO-Port
  14. mini-HOWTO by the same author.
  15.  
  16. If you have corrections or something to add, feel free to e-mail me
  17. (Riku.Saikkonen@hut.fi)...
  18.  
  19. Changes from the previous version (Aug 26 1996):
  20. Author's e-mail address changed.
  21. Ioperm() privileges are not transferred across fork()s, as I had thought.
  22. Added pointers (URLs) to information on quite a few topics.
  23. Other minor changes.
  24.  
  25.  
  26.         I/O ports in C programs, the normal way
  27.  
  28. Routines for accessing I/O ports are in /usr/include/asm/io.h (or
  29. linux/include/asm-i386/io.h in the kernel source distribution). The routines
  30. there are inline macros, so it is enough to #include <asm/io.h>; you do not
  31. need any additional libraries.
  32.  
  33. Because of a limitation in gcc (present at least in 2.7.2.1 and below), you
  34. _have to_ compile any source code that uses these routines with optimisation
  35. turned on (gcc -O1 or higher), or alternatively #define extern to be
  36. empty before #including <asm/io.h>.
  37.  
  38. For debugging, you can use "gcc -g -O" (at least with modern versions of
  39. gcc), though optimisation can sometimes make the debugger behave a bit
  40. strangely. If this bothers you, put the routines that use I/O port access in
  41. a separate source file and compile only that with optimisation turned on.
  42.  
  43. Before you access any ports, you must give your program permission to do it.
  44. This is done by calling the ioperm(2) function (declared in unistd.h, and
  45. defined in the kernel) somewhere near the start of your program (before any
  46. I/O port accesses). The syntax is ioperm(from,num,turn_on), where from is
  47. the first port number to give access to, and num the number of consecutive
  48. ports to give access to. For example, ioperm(0x300,5,1); would give access
  49. to ports 0x300 through 0x304 (a total of 5 ports). The last argument is a
  50. Boolean value specifying whether to give access to the program to the ports
  51. (true (1)) or to remove access (false (0)). You may call ioperm() multiple
  52. times to enable multiple non-consecutive ports. See the ioperm(2) manual
  53. page for details on the syntax.
  54.  
  55. The ioperm() call requires your program to have root privileges; thus you
  56. need to either run it as the root user, or make it setuid root. You can drop
  57. the root privileges after you have called ioperm() to enable the ports you
  58. want to use. You are not required to explicitly drop your port access
  59. privileges with ioperm(...,0); at the end of your program, it is done
  60. automatically as the program exits.
  61.  
  62. A setuid() to a non-root user does not disable the port access granted by
  63. ioperm(), but a fork() does.
  64.  
  65. Ioperm() can only give access to ports 0x000 through 0x3ff; for higher
  66. ports, you need to use iopl(2) (which gives you access to all ports at
  67. once). Use the level argument 3 (i.e. "iopl(3);") to give your program
  68. access to all I/O ports (so be careful -- accessing the wrong ports can do
  69. all sorts of nasty things to your computer). Again, you need root privileges
  70. to call iopl().
  71.  
  72. Then, to actually accessing the ports... To input a byte (8 bits) from a
  73. port, call inb(port);, it returns the byte it got. To output a byte, call
  74. outb(value, port); (notice the order of the parameters). To input a word (16
  75. bits) from ports x and x+1 (one byte from each to form the word, just like
  76. the assembler instruction INW), call inw(x);. To output a word to the two
  77. ports, outw(value,x);. If you're unsure of which port instructions
  78. (byte/word) to use, you probably want inb() and outb() -- most devices are
  79. designed for bytewise port access. Note that all port instructions take at
  80. least about a microsecond to execute.
  81.  
  82. The inb_p(), outb_p(), inw_p(), and outw_p() macros work otherwise
  83. identically to the ones above, but they do an additional short (about one
  84. microsecond) delay after the port access; you can make the delay four
  85. microseconds by #defining REALLY_SLOW_IO before #including <asm/io.h>. These
  86. macros normally (unless you #define SLOW_IO_BY_JUMPING, which probably isn't
  87. accurate) use a port output to port 0x80 for their delay, so you need to
  88. give access to port 0x80 with ioperm() first (outputs to port 0x80 should
  89. not affect any part of the system). For more versatile methods of delaying,
  90. read on.
  91.  
  92. There are man pages for ioperm(), iopl(), and the above macros in reasonably
  93. recent releases of the Linux man-pages distribution.
  94.  
  95.  
  96.         An alternate method for I/O port access
  97.  
  98. Another way to access I/O ports is to open() /dev/port (a character device,
  99. major number 1, minor 4) for reading and/or writing (the stdio f*()
  100. functions have internal buffering, so avoid them). Then lseek() to the
  101. appropriate byte in the file (file position 0 = port 0, file position 1 =
  102. port 1, and so on), and read() or write() a byte or word from or to it.
  103.  
  104. Of course, for this your program needs read/write access to /dev/port. This
  105. method is probably slower than the normal method above, but does not need
  106. optimisation nor ioperm() (nor root access, if you give a non-root user or
  107. group access to /dev/port).
  108.  
  109.  
  110.         Interrupts (IRQs) and DMA access
  111.  
  112. You cannot use IRQs or DMA directly from a user-mode program. You need to
  113. write a kernel driver; see the Linux Kernel Hacker's Guide
  114. (<URL:http://www.redhat.com:8080/HyperNews/get/khg.html>) for details and
  115. the kernel source code for examples.
  116.  
  117. You also cannot disable interrupts from within a user-mode program.
  118.  
  119.  
  120.         High-resolution timing: Delays
  121.  
  122. First of all, I should say that you cannot guarantee user-mode processes to
  123. have exact control of timing because of the multi-tasking, pre-emptive
  124. nature of Linux. Your process might be scheduled out at any time for
  125. anything from about 10 milliseconds to a few seconds (on a system with very
  126. high load). However, for most applications using I/O ports, this does not
  127. really matter. To minimise this, you may want to nice your process to a
  128. high-priority value (see the nice(2) manual page).
  129.  
  130. If you want more precise timing than normal user-mode processes give you,
  131. there are some provisions for user-mode `real time' support. Linux 2.x
  132. kernels have soft real time support; see the man page for
  133. sched_setscheduler(2) for details. There is a special kernel that supports
  134. hard real time; see <URL:http://luz.cs.nmt.edu/~rtlinux/> for more
  135. information on this.
  136.  
  137. Now, let me start with the easier timing calls. For delays of multiple
  138. seconds, your best bet is probably to use sleep(3). For delays of at least
  139. tens of milliseconds (about 10 ms seems to be the minimum delay), usleep(3)
  140. should work. These functions give the CPU to other processes, so CPU time
  141. isn't wasted. See the manual pages for details.
  142.  
  143. For delays of under about 50 milliseconds (depending on the speed of your
  144. processor and machine, and the system load), giving up the CPU doesn't work
  145. because the Linux scheduler usually takes at least about 10-30 milliseconds
  146. before it returns control to your process. Due to this, in small delays,
  147. usleep(3) usually delays somewhat more than the amount that you specify in
  148. the parameters, and at least about 10 ms.
  149.  
  150. For short delays (tens of us to 50 ms or so), a versatile method is to
  151. use udelay(), defined in /usr/include/asm/delay.h (linux/include/asm-i386/
  152. delay.h). Udelay() takes the number of microseconds to delay (an unsigned
  153. long) as its sole parameter, and returns nothing. It may take up to a few
  154. microseconds more time than the parameter specifies because of the overhead
  155. in the calculation of how long to wait (see delay.h for details).
  156.  
  157. To use udelay() outside of the kernel, you need to have the unsigned long
  158. variable loops_per_sec defined with the correct value. As far as I know, the
  159. only way to get this value from the kernel is to read /proc/cpuinfo for the
  160. BogoMips value and multiply that by 500000 to get (an imprecise)
  161. loops_per_sec.
  162.  
  163. In the 2.0.x series of Linux kernels, there is a ne