I/O port에 접근하기 위해 필요한 루틴들은 /usr/include/asm/io.h에 모두 포함되어 있으므로 단순히 C프로그램에서 #include 를 포함하기만 하면 된다. 다른 라이브러리는 필요없다. 

그리고 gcc로 컴파일할 때 최적화 옵션(gcc -O1 혹은 그 이상)을 잊지 말아야 한다. 
또한 디버깅을 위해서는 디버거 옵션(gcc -g)을 넣는 것도 중요하다. 

정리하자면 컴파일할 때는 다음의 옵션을 꼭 넣는다. 
% gcc -g -O2 ... 

Linux에서는 어떤 port에 접근하려고 할 때 프로그램에 접근 권한을 주어야 한다. 
이런 기능은 ioperm()이라는 함수에 의해서 이루어진다. 
ioperm()은 unistd.h에 선언되어 있으므로 사용하려면 이를 포함해야 한다. 

문법은 ioperm(from, num, turn_on)으로 from은 접근 권한을 주는 첫 번째 포트번호이고, num은 from으로부터 연속되는 포트의 갯수이다. 

예를 들어, ioperm(0x300, 5, 1)이면 0x300 포트부터 0x304번 포트까지의 접근 권한을 주는 것이다. 
turn_on에 Boolean으로 1을 주면 허가, 0을 주면 접근을 금지 시킨다. 

ioperm이라는 함수는 프로그램이 root의 권한을 가지고 있어야 실행된다. 그리고 ioperm 에서 접근허가 된 포트라도 프로그램이 끝나면 자동적으로 접근금지가 되므로 굳이 ioperm( , ,0)을 줄 필요는 없다. 

ioperm()은 0x000부터 0x3FF 까지의 포트에만 접근할 수 있게 한다. 

더 높은 포트에 접근하려고 하면 iopl()이라는 함수를 사용하여야 한다. 
iopl()은 모든 포트에 대한 접근허가를 단 한번에 준다. 

그러므로 조심하여야 한다. 잘못된 포트로의 접근은 켬퓨터에 치명적인 문제를 일으킬 수 있다. 

포트에 실질적으로 값을 쓰고 읽는 기능을 주는 함수는 inb()/outb()이다. 

원하는 포트(port)에서 한 바이트(8bit)를 읽기 위해서는 inb(port)를, 쓰기 위해서는 outb(value, port)를 사용하는 데 value는 주고자 하는 값이다. 

두 바이트씩 즉 16bit씩 읽고 쓰기 위해서는 inw(port)/outw(value, port)를 사용하는데, 이는 실질적으로 port로 지정한 포트와 그 다음 포트를 합쳐서 읽고 쓰는 것이다. 

또한 32bit씩 읽고자 한다면 inl(port)/outl(value, port)를 사용하며 이는 지정된 port 에서 연속적으로 이어서 4포트를 한꺼번에 읽고 쓰는 것이다. 

포트를  읽고 쓸 때는 근사적으로 1microsecond(백만분의 1초)가 소요된다. 

또한 포트에 접근한 후에 값을 읽고 쓰는 것을 보다 확실히 하기 위해서 약간의 delay시간을 줄 수 있는 데, 이에 쓰이는 함수는 inb_p()/outb_p()와 같이 함수 끝에 _p를 붙이는 것이다. 

이는 pause를 의미하며, delay시간은 io.h에 정의되어 있는 매크로를 사용하여 조종되어질 수 있고, 초기치는 약 4 microsecond 이다. 

이를 바꾸는 방법은 #define REALLY_SLOW_IO (value) 이므로 이를 이용하면 된다. 
그런데 이 pause시간을 정하는 매크로는 0x80포트를 통하여 이루어 지므로 이에 대한 접근권한을 주는 것을 잊지 말아야 한다.

출처 : http://gnudevel.tistory.com/33http://gnudevel.tistory.com/33

+ Recent posts