Поиск базового адреса устройства для связи через inb() и outb()
Я пытаюсь установить связь с диском с помощью команд inb(), inw(), outb() и outw(), чтобы найти конкретную информацию о диске. Однако для использования этих команд мне нужны правильные порты ввода / вывода для устройства. Когда у меня есть правильные порты ввода / вывода, я очень легко могу найти информацию, которую ищу, однако я не знаю способа найти базовый адрес портов ввода / вывода устройства в Linux.
В DOS я могу использовать Hdat2, чтобы найти базовый адрес устройства, однако я пытаюсь найти адрес в Linux. Есть ли способ найти, какое устройство подключается к какому порту ввода / вывода в Linux?
В /proc есть файл ioports, который содержит некоторую информацию, но я не знаю, как связать эту информацию с конкретными устройствами.
Любая помощь будет принята с благодарностью. Спасибо!
4 ответа
Так что я нашел что-то, хотя это не самое элегантное решение, и оно определенно не работает везде, оно работало на моем оборудовании, поэтому я решил поделиться им.
Во-первых, вы должны получить адрес контроллера SATA из команды lspci, как показал Николай (ключ -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 соответствует хосту 0 на контроллере SATA в 0000:00:1f.2. Теперь, чтобы найти адрес, который мы можем использовать для общения с /dev/sda с помощью команд inb() и outb(), мы ищем файл с именем "resource" в /sys/bus/pci/devices/0000:00:1f 0,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 для отправки команд на устройство.
Если кто-нибудь знает какой-либо лучший способ сделать это, я все уши...
Кажется, путь в ядре 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
Вы получаете доступ к оборудованию из пользовательской программы или из модуля ядра?
Если вы делаете это из пространства пользователя, причина, по которой трудно найти информацию о физическом адресе, состоит в том, что никто не получает доступ к оборудованию таким образом; все, что должно касаться необработанного оборудования, живет в ядре.
Если вы пишете модуль ядра, вы получаете адресную информацию из структур ядра, а не путем доступа к /sys/...
Устройство, скорее всего, зависает от шины 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, третье издание. Глава 12: Драйверы PCI.
Редактировать:
Загляните в этот раздел и руководство по именованию в больших хранилищах, чтобы получить помощь по именованию дисков Linux.