我有一个 PCI 设备,它有自己的驱动程序(未集成在 Linux 内核中)。我使用 收集了设备信息udevadm
。
udevadm info -a -p /sys/devices/pci0000:00/0000:00:1e.0/0000:0d:02.0
Udevadm info 从 devpath 指定的设备开始,然后遍历父设备链。它针对找到的每个设备打印 udev 规则键格式的所有可能属性。
要匹配的规则可以由设备的属性和来自单个父设备的属性组成。
looking at device '/devices/pci0000:00/0000:00:1e.0/0000:0d:02.0':
KERNEL=="0000:0d:02.0"
SUBSYSTEM=="pci"
DRIVER==""
ATTR{irq}=="10"
ATTR{subsystem_vendor}=="0xe1c5"
ATTR{broken_parity_status}=="0"
ATTR{class}=="0x078000"
ATTR{driver_override}=="(null)"
ATTR{consistent_dma_mask_bits}=="32"
ATTR{dma_mask_bits}=="32"
ATTR{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,000000ff"
ATTR{device}=="0x9030"
ATTR{enable}=="0"
ATTR{msi_bus}==""
ATTR{local_cpulist}=="0-7"
ATTR{vendor}=="0x10b5"
ATTR{subsystem_device}=="0x0005"
ATTR{numa_node}=="-1"
ATTR{d3cold_allowed}=="1"
looking at parent device '/devices/pci0000:00/0000:00:1e.0':
KERNELS=="0000:00:1e.0"
SUBSYSTEMS=="pci"
DRIVERS==""
ATTRS{irq}=="0"
ATTRS{subsystem_vendor}=="0x103c"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x060401"
ATTRS{driver_override}=="(null)"
ATTRS{consistent_dma_mask_bits}=="32"
ATTRS{dma_mask_bits}=="32"
ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,000000ff"
ATTRS{device}=="0x244e"
ATTRS{enable}=="1"
ATTRS{msi_bus}=="1"
ATTRS{local_cpulist}=="0-7"
ATTRS{vendor}=="0x8086"
ATTRS{subsystem_device}=="0x304b"
ATTRS{numa_node}=="-1"
ATTRS{d3cold_allowed}=="0"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
然后我创建99-elcus1553.rules
了/etc/udev/rules.d/
:
ACTION=="add",SUBSYSTEM=="pci",ATTR{vendor}=="0x10b5",ATTR{device}=="0x9030",RUN+="/home/qmor/elcus-1553driver-linux/trunk/loaddrv"
其中包含:
/sbin/rmmod tmk1553b
rm /dev/tmk1553b
/sbin/insmod tmk1553b.ko d0=1 t0="TAI" misc=1
chmod o+rwx /dev/tmk1553b
重启后,我没有/dev/tmk1553b
设备,这意味着文件规则不起作用。我做错了什么?
答案1
这里有几个问题:
0. 你走错了路模块加载。该规则可以正常工作,但它仍然是解决问题的错误工具。udev 已经内置了自动加载设备驱动程序模块的方法,例如 modaliases 和 modprobe.d;它们不限仅适用于树内驱动程序。
1. 你的 shell 脚本不是一个脚本。该…/trunk/loaddrv
文件必须标记为可执行文件(将其 chmod 为 a+x),并且必须具有#!
告诉内核使用哪个解释器的标题 - 在您的情况下,添加#!/bin/sh
到脚本的顶部。
2. 不知道模块在哪里。您有insmod tmk1553b.ko
。但是它应该在哪里查找该 .ko 文件?由于您没有指定完整路径,因此它会在“当前”目录中查找 - 该目录始终/
用于 udev 启动的程序。换句话说,规则不会这样做...
cd /home/qmor/elcus-1553driver-linux/trunk
./loaddrv
...它的作用是:
cd /
/home/qmor/elcus-1553driver-linux/trunk/loaddrv
好的,回到“0. 你走错了路带有模块加载”。
每个设备都有一个自动生成的模块别名(modalias)。 例如:
$ cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/modalias pci:v00001002d000068E4sv00001043sd00001C92bc03sc00i00
每个驱动模块都有一个匹配的别名列表,如下
modinfo
所示:filename: /lib/modules/3.19.0/kernel/drivers/gpu/drm/radeon/radeon.ko.gz description: ATI Radeon alias: pci:v00001002d000068E4sv*sd*bc*sc*i*
当出现设备时,udev 会扫描
/lib/modules
具有匹配模式别名的任何模块。
因此对于供应商 0x10b5 型号 0x9030 来说,它将是pci:v000010b5d00009030sv*sd*bc*sc*i*
。
将这些添加到您的 modprobe 配置中(/etc/modprobe.d/tmk1553b.conf
):
alias pci:v000010b5d00009030sv*sd*bc*sc*i* tmk1553b
options tmk1553b d0=1 t0=TAI misc=1
install tmk1553b /sbin/insmod /home/qmor/elcus-1553driver-linux/trunk/tmk1553b.ko
(如果您编写自己的模块,则需要MODULE_ALIAS("...")
宏。)