Linux 即插即用文档¶
- 作者:
Adam Belay <ambx1@neo.rr.com>
- 上次更新时间:
2002 年 10 月 16 日
概述¶
即插即用提供了一种检测和设置传统设备或以其他方式不可配置的设备的资源的方法。Linux 即插即用层为兼容的驱动程序提供这些服务。
用户界面¶
Linux 即插即用用户界面提供了一种为不支持 Linux 即插即用的传统驱动程序和用户级别驱动程序激活 PnP 设备的方法。用户界面集成到 sysfs 中。
除了标准的 sysfs 文件外,以下文件也会在每个设备的目录中创建:- id - 显示支持的 EISA ID 列表 - options - 显示可能的资源配置 - resources - 显示当前分配的资源并允许更改资源
激活设备¶
# echo "auto" > resources
这将调用自动资源配置系统来激活设备
手动激活设备¶
# echo "manual <depnum> <mode>" > resources
<depnum> - the configuration number
<mode> - static or dynamic
static = for next boot
dynamic = now
禁用设备¶
# echo "disable" > resources
示例
假设您需要激活软盘控制器。
更改到正确的目录,在我的例子中是 /driver/bus/pnp/devices/00:0f
# cd /driver/bus/pnp/devices/00:0f # cat name PC standard floppy disk controller
检查设备是否已激活
# cat resources DISABLED
注意字符串 “DISABLED”。这意味着设备未激活。
检查设备可能的配置(可选)
# cat options Dependent: 01 - Priority acceptable port 0x3f0-0x3f0, align 0x7, size 0x6, 16-bit address decoding port 0x3f7-0x3f7, align 0x0, size 0x1, 16-bit address decoding irq 6 dma 2 8-bit compatible Dependent: 02 - Priority acceptable port 0x370-0x370, align 0x7, size 0x6, 16-bit address decoding port 0x377-0x377, align 0x0, size 0x1, 16-bit address decoding irq 6 dma 2 8-bit compatible
现在激活设备
# echo "auto" > resources
最后检查设备是否已激活
# cat resources io 0x3f0-0x3f5 io 0x3f7-0x3f7 irq 6 dma 2
还有一系列内核参数
pnp_reserve_irq=irq1[,irq2] ....
pnp_reserve_dma=dma1[,dma2] ....
pnp_reserve_io=io1,size1[,io2,size2] ....
pnp_reserve_mem=mem1,size1[,mem2,size2] ....
统一即插即用层¶
所有即插即用驱动程序、协议和服务都会在一个名为即插即用层的中心位置汇合。该层负责 PnP 驱动程序和 PnP 协议之间的信息交换。因此,它会自动将命令转发到正确的协议。这使得编写 PnP 驱动程序变得容易得多。
以下函数可从即插即用层获得
- pnp_get_protocol
将使用次数加一
- pnp_put_protocol
将使用次数减一
- pnp_register_protocol
使用此函数注册新的 PnP 协议
- pnp_unregister_protocol
使用此函数从即插即用层中删除 PnP 协议
- pnp_register_driver
将 PnP 驱动程序添加到即插即用层
这包括驱动程序模型集成,成功返回零,失败返回负错误编号;如果您需要知道有多少设备绑定到驱动程序,请计算对 .add() 方法的调用
- pnp_unregister_driver
从即插即用层中删除 PnP 驱动程序
即插即用协议¶
本节包含有关 PnP 协议开发人员的信息。
以下协议目前在计算领域中可用
- PNPBIOS
用于串行和并行端口等系统设备。
- ISAPNP
为 ISA 总线提供 PnP 支持
- ACPI
在其众多用途中,ACPI 提供了有关系统级设备的信息。
它旨在取代 PNPBIOS。Linux 即插即用目前不支持它,但计划在不久的将来支持。
Linux PnP 协议的要求:1. 该协议必须使用 EISA ID 2. 该协议必须通知 PnP 层设备的当前配置
设置资源的能力是可选的,但首选。
以下是 PnP 协议相关函数
- pnp_add_device
使用此函数将 PnP 设备添加到 PnP 层
仅当 pnp_dev 结构中设置了所有需要的值时才调用此函数
- pnp_init_device
调用此函数以初始化 PnP 结构
- pnp_remove_device
调用此函数以从即插即用层中删除设备。如果设备仍在使用,则将失败。将自动释放设备和相关结构使用的内存
- pnp_add_id
将 EISA ID 添加到指定设备支持的 ID 列表中
有关更多信息,请查阅诸如 /drivers/pnp/pnpbios/core.c 等协议的源代码。
Linux 即插即用驱动程序¶
本节包含有关 Linux PnP 驱动程序开发人员的信息。
新方法¶
首先列出支持的 EISA ID
例如
static const struct pnp_id pnp_dev_table[] = { /* Standard LPT Printer Port */ {.id = "PNP0400", .driver_data = 0}, /* ECP Printer Port */ {.id = "PNP0401", .driver_data = 0}, {.id = ""} };
请注意,字符 'X' 可以用作函数部分(最后四个字符)的通配符。
例如
/* Unknown PnP modems */ { "PNPCXXX", UNKNOWN_DEV },
可以选择定义支持的 PnP 卡 ID。例如
static const struct pnp_id pnp_card_table[] = { { "ANYDEVS", 0 }, { "", 0 } };
可以选择定义探测和删除函数。如果驱动程序已经有一种可靠的方法来检测资源(例如 parport_pc 驱动程序),则不定义这些函数可能是有意义的。
例如
static int serial_pnp_probe(struct pnp_dev * dev, const struct pnp_id *card_id, const struct pnp_id *dev_id) { . . .
例如
static void serial_pnp_remove(struct pnp_dev * dev) { . . .
有关更多信息,请参阅 /drivers/serial/8250_pnp.c。
创建一个驱动程序结构
例如
static struct pnp_driver serial_pnp_driver = { .name = "serial", .card_id_table = pnp_card_table, .id_table = pnp_dev_table, .probe = serial_pnp_probe, .remove = serial_pnp_remove, };
name 和 id_table 不能为 NULL。
注册驱动程序
例如
static int __init serial8250_pnp_init(void) { return pnp_register_driver(&serial_pnp_driver); }
旧方法¶
创建了一系列兼容性函数,以便轻松转换 ISAPNP 驱动程序。它们应该仅作为临时解决方案。
它们如下
struct pnp_dev *pnp_find_dev(struct pnp_card *card,
unsigned short vendor,
unsigned short function,
struct pnp_dev *from)