文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Linux下读写I/O port

Linux下读写I/O port

时间:2006-07-11  来源:tree20000

 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 <stdio.h>
#include <assert.h>
#include <sys/io.h>

#define IO_PORTS1         1       /* ioport <= 0x3ff */
#define IO_PORTS2         2       /* ioport >0x3ff && ioport < 0xffff */
#define IO_PERMOFF        0
#define IO_PERMON         1 
#define IO_PERMON2        3

#define RW_DELAY    10000 /*delay 100000 microseconds for reading and writing I/O ports. */
#ifndef BOOL
typedef unsigned char BOOL;
#endif

#ifndef BYTE
typedef unsigned char   BYTE;
#endif

#ifndef DWORD
typedef unsigned long   DWORD;
#endif

#ifndef INT
typedef unsigned int INT;
#endif

#ifndef ULONG
typedef unsigned long   ULONG;
#endif

#ifndef WORD
typedef unsigned short  WORD;
#endif
/*
** Function : Write the value of the specified I/O port by giving the length and the
**            starting address.
** Parameter: PortAddr: the port address
**            PortVal : the value to set
**            size    : size = 1 for reading 1 byte, 2 for word, 4 for double words
** Return   : 1 returned if success, or  0  returned
*/
BOOL SetPortVal(WORD PortAddr, DWORD PortVal, BYTE size)
{
    BOOL  Ret     = 0;
    INT   tmpRet  = 0;
    ULONG numperm = 1;
    INT privilege = 0;
    assert(PortAddr>0);
    if(PortAddr <=0x3ff)
    {
        tmpRet = ioperm((ULONG)PortAddr, numperm, IO_PERMON);
        privilege = IO_PORTS1;
    }
    else if( PortAddr > 0x3ff screen.width/2)this.style.width=screen.width/2;" border="0">
    {
        tmpRet = iopl(IO_PERMON2);
        privilege = IO_PORTS2;
    }
    else
        return Ret;
    if(tmpRet<0)
    {
        fprintf(stderr, "can't set the io port permission for setting !\n"screen.width/2)this.style.width=screen.width/2;" border="0">;
        return Ret;
    }
    else
    {
        switch(size)
        {
            case 1: /*write one byte to the port */
                outb(PortVal, PortAddr);
                break;
           case 2: /*write one word to the port */
                outw(PortVal, PortAddr);
                break;
            case 4: /*write double words to the port */
                outl(PortVal, PortAddr);
                break;
            default:
                Ret = 0;
                break;
        }
        usleep(RW_DELAY);
        Ret = 1;
    }
    if( privilege == IO_PORTS1 screen.width/2)this.style.width=screen.width/2;" border="0">
        ioperm((ULONG)PortAddr, numperm, IO_PERMOFF);
    else if(privilege == IO_PORTS2 screen.width/2)this.style.width=screen.width/2;" border="0">
        iopl(IO_PERMOFF);
    return Ret;
}

/*
** Function : Read the value of the specified I/O port by giving the lenght and the 
**            starting address.
** Parameter: PortAddr : the port address
**            PortVal  : value from port
**            size     : size = 1 for reading 1 byte, 2 for word, 4 for double words
** Return   : 1 returned if success, or 0 returned. 
*/
BOOL GetPortVal(WORD PortAddr, DWORD * PortVal, BYTE size)
{
    BOOL  Ret     = 0;
    int   tmpRet  = 0;
    unsigned long numperm = 1;
    int privilege = 0; 
    assert(PortAddr>0);
    assert(PortVal!=NULL);
    if(PortAddr <=0x3ff)
    {
        tmpRet = ioperm((unsigned long)PortAddr, numperm, IO_PERMON);
        privilege = IO_PORTS1;
    }
    else if( PortAddr > 0x3ff screen.width/2)this.style.width=screen.width/2;" border="0">
    {
        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"screen.width/2)this.style.width=screen.width/2;" border="0">;
        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 screen.width/2)this.style.width=screen.width/2;" border="0">
        ioperm( (unsigned long)PortAddr, numperm, IO_PERMOFF screen.width/2)this.style.width=screen.width/2;" border="0">;
    else if( privilege == IO_PORTS2 screen.width/2)this.style.width=screen.width/2;" border="0">
        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"screen.width/2)this.style.width=screen.width/2;" border="0">;
    printf("1--bus 0:dev:0 fun:0 as address 0x80000000\n"screen.width/2)this.style.width=screen.width/2;" border="0">;
    printf("2--bus 0:dev:1 fun:0 as address 0x80000800\n"screen.width/2)this.style.width=screen.width/2;" border="0">;
    printf("3--input your own defined address value:\n"screen.width/2)this.style.width=screen.width/2;" border="0">;
    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): "screen.width/2)this.style.width=screen.width/2;" border="0">;
                  scanf ("%x", &addr);
    break;
           default:
                  printf("input invalid option num, exit program.\n"screen.width/2)this.style.width=screen.width/2;" border="0">;
                  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
相关阅读 更多 +
排行榜 更多 +
龙珠格斗火柴人

龙珠格斗火柴人

飞行射击 下载
荒野恐龙猎手安卓版

荒野恐龙猎手安卓版

飞行射击 下载
超凡坦克英雄

超凡坦克英雄

飞行射击 下载