【问题标题】:Finding device base address to communicate via inb() and outb()查找设备基地址以通过 in() 和 out() 进行通信
【发布时间】:2010-01-04 16:54:01
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: linux-device-driver firmware hardware-interface base-address hardware-port


    【解决方案1】:

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

    首先,您必须像 Nikolai 显示的那样从 lspci 命令获取 SATA 控制器的地址(-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 对应于 SATA 控制器上的主机 0 在 0000:00:1f.2。现在要找到可以通过 inb() 和 outb() 命令与 /dev/sda 通信的地址,我们在 /sys/bus/pci/devices/0000:00:1f 中查找名为“resource”的文件.2/.

    # 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】:

      设备很可能挂在 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 驱动器命名的帮助。

      【讨论】:

      • 感谢 Nikolai,Linux 设备驱动程序书的链接真的很有帮助。当我拥有 PCI 设备的签名时,我了解如何获取我正在寻找的 I/O 端口的地址。但是,我不明白您是如何从“/dev/sda”转到“0000:03:00.0”的?再次感谢您的帮助!
      • 您可以通过查看符号链接 /sys/block/sda/devicesda 转到 pci id。
      【解决方案3】:

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

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

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

      【讨论】:

      • 感谢 Eric,我是从用户空间执行此操作的。我讨厌我必须与驱动器通信的方式,但这是硬件供应商允许用户找到我正在寻找的信息的唯一方式。
      【解决方案4】:

      路径似乎在内核 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
      

      【讨论】:

        猜你喜欢
        • 2020-11-01
        • 2012-08-16
        • 2015-08-30
        • 1970-01-01
        • 2018-05-19
        • 1970-01-01
        • 2013-08-15
        • 2011-05-30
        • 2021-03-13
        相关资源
        最近更新 更多