代码之家  ›  专栏  ›  技术社区  ›  Kevin S

通过inb()和outb()查找要通信的设备基址

  •  4
  • Kevin S  · 技术社区  · 16 年前

    我正在尝试使用inb()、inw()、outb()和outw()命令与磁盘驱动器通信,以便找到有关该驱动器的特定信息。但是,要使用这些命令,我需要设备的正确I/O端口。当我有正确的I/O端口时,我可以很容易地找到我要查找的信息,但是,我不知道如何在Linux中找到设备I/O端口的基址。

    在DOS中,我可以使用hdat2来查找设备的基址,但是,我尝试在Linux中查找该地址。有没有办法在Linux中找到哪个设备映射到哪个I/O端口?

    /proc中有一个名为ioports的文件,其中包含一些信息,但我不知道如何将这些信息与特定设备相关联。

    任何帮助都将不胜感激。谢谢!

    4 回复  |  直到 12 年前
        1
  •  4
  •   Kevin S    16 年前

    所以我确实找到了一些东西,虽然它不是最优雅的解决方案,而且肯定不适用于任何地方,但它已经在我的硬件上工作了,所以我想我会分享。

    首先,您必须从lspci命令中获取sata控制器的地址,如nikolai所示(-d只显示完整的域号):

    # lspci -D
    ...
    0000:00:1f.2 SATA controller: Intel Corporation 82801IR 6 port SATA AHCI Controller
    ...
    

    现在,使用这个地址(0000:00:1f.2),您可以进入/sys。

    在/sys/bus/pci/devices中,应列出您的设备:

    # ls -l /sys/bus/pci/devices
    ...
    lrwxrwxrwx 1 root root 0 Jan 14 12:35 0000:00:1f.2 -> ../../../devices/pci0000:00/0000:00:1f.2
    

    现在在这个目录中有几个hostx目录。

    # ls -l /sys/bus/pci/devices/0000\:00\:1f.2/
    ...
    drwxr-xr-x 4 root root    0 Jan 13 12:40 host0
    drwxr-xr-x 4 root root    0 Jan 13 12:40 host1
    drwxr-xr-x 3 root root    0 Jan 13 12:40 host2
    drwxr-xr-x 3 root root    0 Jan 13 12:40 host3
    drwxr-xr-x 3 root root    0 Jan 13 12:40 host4
    drwxr-xr-x 4 root root    0 Jan 14 08:21 host5
    ...
    

    在其中一个hostx目录中,将有一个targetx:x:x目录。这个targetx:x:x目录将有一个名为x:x:x:x的目录(x是可以变化的数字)。

    # ls -R /sys/bus/pci/devices/0000\:00\:1f.2/host0
    /sys/bus/pci/devices/0000:00:1f.2/host0:
    power  scsi_host:host0  target0:0:0  uevent
    
    /sys/bus/pci/devices/0000:00:1f.2/host0/target0:0:0:
    0:0:0:0  power  uevent
    ...
    

    在x:x:x:x目录中,有一个名为“block:sdx”的链接(其中x是字母)。此SDX是此目录对应的驱动器的名称。

    # ls -l /sys/bus/pci/devices/0000\:00\:1f.2/host0/target0\:0\:0/0\:0\:0\:0/
    lrwxrwxrwx 1 root root    0 Jan 14 15:01 block:sda -> ../../../../../../block/sda
    

    所以/dev/sda对应于0000:00:1f.2处SATA控制器上的主机0。现在,为了找到可以通过inb()和outb()命令与/dev/sda通信的地址,我们在/sys/bus/pci/devices/0000:00:1f.2/中查找名为“resource”的文件。

    # cat /sys/bus/pci/devices/0000\:00\:1f.2/resource
    0x000000000000fe00 0x000000000000fe07 0x0000000000000101
    0x000000000000fe10 0x000000000000fe13 0x0000000000000101
    0x000000000000fe20 0x000000000000fe27 0x0000000000000101
    0x000000000000fe30 0x000000000000fe33 0x0000000000000101
    0x000000000000fec0 0x000000000000fedf 0x0000000000000101
    0x00000000ff970000 0x00000000ff9707ff 0x0000000000000200
    0x0000000000000000 0x0000000000000000 0x0000000000000000
    

    我们要找的地址是fe00,在第一行。我们需要第一行,因为它是主机0,如果它是主机1,我们将查看第二行,主机2是第三行,依此类推。主机号由前面找到的hostx目录提供。资源文件中的每一行分为3列:

    第1列=起始地址 第2列=结束地址 第3列=标志

    所以这就是我如何从/dev/sda到0xfe00,以便向设备发送命令。

    如果有人知道更好的方法,我会全力以赴…

        2
  •  1
  •   Nikolai Fetissov    16 年前

    设备很可能挂在PCI总线上,所以 lspci(8) 是第一个看到的。然后找出下面的位置 /sys 描述了控制器。例如,这里我有:

    
    ~$ lspci
    ...
    03:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS 1078 (rev 04)
    ...
    ~$ ll /sys/bus/pci/devices/0000\:03\:00.0/
    total 0
    drwxr-xr-x 4 root root      0 Dec 16 11:57 ./
    drwxr-xr-x 6 root root      0 Dec 16 11:57 ../
    -rw-r--r-- 1 root root   4096 Dec 16 11:57 broken_parity_status
    lrwxrwxrwx 1 root root      0 Dec 16 11:57 bus -> ../../../../bus/pci/
    -r--r--r-- 1 root root   4096 Dec 16 11:57 class
    -rw-r--r-- 1 root root   4096 Dec 16 11:57 config
    -r--r--r-- 1 root root   4096 Dec 16 11:57 device
    lrwxrwxrwx 1 root root      0 Dec 16 11:57 driver -> ../../../../bus/pci/drivers/megaraid_sas/
    -rw------- 1 root root   4096 Dec 16 11:57 enable
    drwxr-xr-x 5 root root      0 Dec 16 11:57 host0/
    -r--r--r-- 1 root root   4096 Dec 16 11:57 irq
    -r--r--r-- 1 root root   4096 Dec 16 11:57 local_cpus
    -r--r--r-- 1 root root   4096 Dec 16 11:57 modalias
    -r--r--r-- 1 root root   4096 Dec 16 11:57 pools
    drwxr-xr-x 2 root root      0 Dec 16 11:57 power/
    -r--r--r-- 1 root root   4096 Dec 16 11:57 resource
    -rw------- 1 root root 262144 Dec 16 11:57 resource0
    -rw------- 1 root root    256 Dec 16 11:57 resource2
    -rw------- 1 root root 262144 Dec 16 11:57 resource3
    -r-------- 1 root root  32768 Dec 16 11:57 rom
    lrwxrwxrwx 1 root root      0 Dec 16 11:57 subsystem -> ../../../../bus/pci/
    -r--r--r-- 1 root root   4096 Dec 16 11:57 subsystem_device
    -r--r--r-- 1 root root   4096 Dec 16 11:57 subsystem_vendor
    --w------- 1 root root   4096 Dec 16 11:57 uevent
    -r--r--r-- 1 root root   4096 Dec 16 11:57 vendor
    

    这显示控制器的PCI配置空间。详情请参见 Linux Device Drivers, Third Edition. Chapter 12: PCI Drivers .

    编辑:

    看看这个 partition and mass-storage naming howto 有关Linux驱动器命名的帮助。

        3
  •  1
  •   Eric Seppanen    16 年前

    您是从用户空间程序还是从内核模块访问硬件?

    如果您是从用户空间进行的,那么很难找到物理地址信息的原因是没有人以这种方式访问硬件;任何需要接触原始硬件的东西都存在于内核中。

    如果您正在编写内核模块,则可以从内核结构中获取地址信息,而不是通过访问 /sys/...

        4
  •  1
  •   Gu.    13 年前

    路径似乎在内核3.10中发生了变化,这就是我如何找到相应的设备节点:

    $ ls -l /sys/bus/pci/devices/0000\:00\:1f.2/ata1/host0/target0\:0\:0/0\:0\:0\:0/block/
    total 0
    drwxr-xr-x 10 root root 0 Oct 17 08:35 sda
    
    $ ls -l /sys/bus/pci/devices/0000\:00\:1f.2/ata2/host1/target1\:0\:0/1\:0\:0\:0/block/
    total 0
    drwxr-xr-x 9 root root 0 Oct 17 08:35 sdb
    
    推荐文章