- 论坛徽章:
- 0
|
1. 基础知识:
1.1 在存取任何 I/O port之前,必須讓程式有如此做的權限. 要達成這個目的你可以在你的程式一
開始的地方 (但是要在任何 I/O port存取動作之前) 呼叫 ioperm() 這個函数 (該函数被声明於檔案
/usr/include/sys/io.h).
使用語法是:
ioperm(from, num, turn_on)
其
中 from 是第一個允許存取的 I/O port位址;num 是接著連續存取 I/O port位址的數目. 例如, ioperm(0x300,
5, 1) 的意思就是說允許存取port 0x300 到 0x304 (一共五個port位址). 而最後一個參數是一個布尔值用來指定是否給予程
式存取 I/O port的權限 (true (1)) 或是除去存取的權限 (false (0)).
函数 ioperm() 只能讓
你取得Port位址 0x000 到 0x3ff 的存取權限; 至於較高位址的Port, 你得使用函数 iopl() (該函数讓你一次可以存取所有
的Port位址). 將權限等級參數值設為 3 (例如, iopl(3)) 以便你的程式能夠存取 所有的 I/O Port。
1.2 获得读取权限后,就可以对I/O port进行读写了。
a.读
要從某個Port地址读取一個 byte (8 個 bits) 的資料, 可以调用函数 inb(port);类似的有:
inw (port) //读取 2 个 bytes
inl (port) //读取 4 个bytes
b.写
要向某個Port地址写入一個 byte (8 個 bits) 的資料,调用函数 outb(value, port);类似的有:
outw(value, port)
outl(value, port)
2. 应用实列:
2.1 源程序:
/* name: pci.c */
#include
#include
#include
#define IO_PORTS1 1 /* ioport 0x3ff && ioport 0);
if(PortAddr 0x3ff
![]()
{
tmpRet = iopl(IO_PERMON2);
privilege = IO_PORTS2;
}
else
return Ret;
if(tmpRet0);
assert(PortVal!=NULL);
if(PortAddr 0x3ff
![]()
{
tmpRet = iopl(IO_PERMON2);
privilege = IO_PORTS2;
}
else
return Ret;
if(tmpRet<0)
{
fprintf(stderr, "can't set the io port permission for reading !\n"
![]()
;
return Ret;
}
else
{
switch(size)
{
case 1: /*read one byte from the port */
*PortVal = inb(PortAddr);
break;
case 2: /*read one word from the port */
*PortVal = inw(PortAddr);
break;
case 4: /*read double words from the port */
*PortVal = inl(PortAddr);
break;
default:
Ret = 0;
break;
}
usleep(RW_DELAY);
Ret = 1;
}
if( privilege == IO_PORTS1
![]()
ioperm( (unsigned long)PortAddr, numperm, IO_PERMOFF
![]()
;
else if( privilege == IO_PORTS2
![]()
iopl(IO_PERMOFF);
return Ret;
}
int main (int argc, char * argv[])
{
WORD add_port = 0xcf8;
WORD data_port = 0xcfc;
DWORD addr = 0x80000000;
DWORD port_value;
BYTE size = 4;
int input;
printf("Please select the option number as follow:\n"
![]()
;
printf("1--bus 0:dev:0 fun:0 as address 0x80000000\n"
![]()
;
printf("2--bus 0:dev:1 fun:0 as address 0x80000800\n"
![]()
;
printf("3--input your own defined address value:\n"
![]()
;
scanf("%d",&input);
switch(input)
{
case 1:
addr=0x80000000;
break;
case 2:
addr=0x80000800;
break;
case 3:
printf("please input the 32 bits address in Hex format(such as 80007800): "
![]()
;
scanf ("%x", &addr);
break;
default:
printf("input invalid option num, exit program.\n"
![]()
;
return -1;
}
printf ("The addr is :%X\n", addr);
printf ("The add_port is : %X\n", add_port);
printf ("The data_port is : %X\n", data_port);
if (SetPortVal(add_port, addr, size))
{
if (GetPortVal(data_port, &port_value, size))
{
printf("port value is :%08X\n", port_value);
return 0;
}
}
return -1;
}
2.2 编译:
gcc –o pci pci.c
gcc 带参数 –o 指定输出的文件名,如不带参数则默认以a.out做为文件名;
如要加入调试信息,则带参数-g,然后用gdb命令进行调试:
gcc –o pci –g pci.c
gdb pci
有关gdb的用法参见相关资料;
2.3 运行:
输入: ./pci (注意: / 前有.表示当前目录下)
可以将结果和系统的pci信息对照,以检查结果是否正确:
more /proc/pci
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21164/showart_139141.html |
|