分类: LINUX
2006-06-30 11:41:06
一般而言,在Linux下进行设备自动检测是根据设备的总线类型进行的。现在的微机系统上最常见的总线类型有PCI、SERIAL、USB、PCMCIA、PARPORT、ISA、SCSI等。对于检测过程,一般不是通过c语言的库函数直接对设备进行访问,并读取设备的信息,而是通过内核的/proc文件系统进行。这种检测方式,充分利用了内核中关于硬件的多种检测函数,具有高效、稳定的特点,并且在内核版本升级之后,使程序的变化也为最小。对于大多数现在流行的系统硬件,在插入适当的模块之后,内核会在/proc文件系统中生成相应的描述文件。检测过程就是读取这样的文件,并将其信息进行相应的处理,从中提取出设备标识、设备描述、设备工作状态等信息。
由于涉及到对/proc文件系统的访问,并可能在检测过程开始时插入需要的设备模块,所以需要用户以root用户方式执行下面所说的操作。
在检测过程结束的时候,用户一般能够得到设备的唯一标识(制造商标识和设备标识)和设备的当前的状态信息。这时就需要一个设备数据库,这个数据库将设备的唯一标识和对应的设备驱动程序对应起来,然后由此生成/etc/modules.conf中的对应表项及其他配置脚本,完成整个的硬件配置过程。
对于每个pci设备都由一个总线号、一个设备号和一个功能号确定。PCI设备可以访问三类地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。前两者可由PCI总线上的所有设备共享。PCI的配置空间由256个字节构成,其布局是标准化的。下表显示的是配置空间中前64字节的每个配置寄存器的分布情况:
Vendor ID | Device ID | ||
Command Reg | Status Reg | ||
Revision ID | Class Code | ||
Cache Line | Latency Timer | Header Type | BIST |
Base Address 0 | |||
Base Address 1 | |||
Base Address 2 | |||
Base Address 3 | |||
Base Address 4 | |||
Base Address 5 | |||
CardBus CIS pointer | |||
Subsystem Vendor ID | Subsystem Device ID | ||
Expansion ROM Base Add | |||
Reserved(PCI Capability List) | |||
Reserved | |||
IRQ Line | IRQ Pin | Min_Gnt | Max_Lat |
class code
设备的类型标识,类寄存器是16位的值。它的高八位确定基类,如SCSI设备的分类码位0x0100。Linux系统的定义见
|
Base Address 0- Base Address 5
表示此卡占用的内存范围。
IRQ Line
指定的设备所使用的中断号,它在系统启动时由固件复制。
IRQ Pin
PCI卡有4个物理引脚,用于把中断从卡上发送到PCI总线上。为0表示设备不支持中断,非0表示使用哪一个终端引脚。此信息可让中断处理子系统处理来自该设备的中断。
关于pci设备的其他信息,您可以参考PCI Local Bus Specification。
一个pci设备可映射到最多六个地址区段。每个区段由内存或I/O位置组成。区段的大小和当前位置由配置寄存器报告。
检测pci设备先要打开文件/proc/bus/pci/devices,例如存在下列数据:
|
上面的数据表示一个pci设备,对于第一个数字0039(十六进制表示),高八位表示总线号(bus),对于低三位表示功能号(function),剩余的五位表示设备号(device)。也就是说,0039表示,总线0,设备号为7,功能号为1。由此,内核生成设备对应的文件/proc/bus/pci/bus/device.function。此文件为256个字节,对应读出的设备配置信息,第十字节开始的双字节表示设备的类型。第二个数字80867111表示,设备的vendorid为8086,deviceid为7111。通过查询设备配置数据库可知设备标识80867111表示Intel Corporation|82371AB PIIX4 IDE控制器。第三个数字表示占用的irq。
用户可以通过察看/proc/pci文件,可以获得系统连接的pci设备的基本信息描述,或者用户也可以使用命令lspci(需要安装包pciutils)来察看PCI设备较为详细的描述信息。但是为了使内核显示上述信息,必须要在编译内核时加入PCI设备名数据库,这会使内核增大约80KB。
关于Linux系统PCI设备的进一步信息您可以阅读
在每个ISAPNP设备加电启动之后,都会进行一个自动配置过程,它的主要步骤如下:
pnp软件使用一系列规范定义的命令标识和配置设备,这些命令由三个8位端口发出(不支持16位的配置端口)。写到这些端口中任何一个的打开系统中pnp逻辑的数据序列对所有卡生效。这个数据序列被称作初始键。
所有卡响应同样的I/O端口寻址,因此为了一次只寻址一个卡pnp软件需要一种隔离机制。隔离协议使用独一无二的标号一次区别一个卡。在隔离之后,pnp软件对每个卡指定一个句柄,由它对应确定的pnp卡。
每个卡上支持可读的资源数据结构,用以描述卡上支持的和功能请求的资源。此结构允许每个ISA卡有多个功能,每个功能作为一个逻辑设备来定义。每个逻辑设备提供pnp资源信息,pnp标准寄存器独立配置每个逻辑设备。
隔离操作之后,pnp软件读取每个卡的资源数据结构。在所有的资源的能力和需求已知之后,系统发出一个资源仲裁来裁决每个卡的资源分配并使用命令寄存器指定每个资源类型。
在资源被指派之后,I/O冲突检测机制执行。命令集也包括激活/禁止卡的功能的命令集。在配置之后,pnp卡离开配置模式。如果向卡重新发出初始化键值,则可以重新使能配置模式(防止配置信息被故意删除)。
对于isa pnp设备有三个八位端口被用于存取isapnp卡的配置空间。配置空间由一系列8位寄存器组成。这些寄存器被用于发送命令,检测状态,存取资源数据信息和配置pnp硬件。
Port Name | Location | Type |
ADDRESS | 0x0279 (Printer status port) | Write-only |
WRITE_DATA | 0x0A79 (Printer status port 0x0800) | Write-only |
READ_DATA | Relocatable in range 0x0203 to 0x03FF | Read-only |
在访问pnp寄存器之前,首先写寄存器地址到地址端口,紧接着从READ_DATA端口读或者从WRITE_DATA端口写。地址端口也是初始键的写目标。
隔离机制的关键是每个卡都有一个独一无二的编号(serial identifier)。serial identifier是一个72位独一无二、非0的数字,由两个32位域和一个8位校验位组成。头32位是制造商标识,另32位可以是任何值。只要不存在任何两块编号相同的卡。
在隔离过程结束时,当前控制的卡被指定一个句柄,称为Card Select Number(CSN),用于以后检索此卡。在卡响应其他的命令之前,此卡必须被指定一个CSN。
CSN是一个8位寄存器,加电使所有卡的此寄存器置为0x0。一旦卡的隔离操作结束,此卡的CSN寄存器被指定一个独一无二的值,以使pnp软件能区别所用的卡。isapnp状态如下:
关于ISAPNP设备的详细的硬件信息,您可以参考 ISAPNP Specification
ISA设备的自动检测是指对支持Plug and Play ISA规范1.0的ISA设备的检测,对不支持此规范的ISA设备,此检测过程是无法工作的。这时的硬件检测和配置是完全要根据用户的个人经验进行。在进行下述检测过程之前,对于基于2.2.X内核的Linux系统,需要用户安装包isapnptools。对于2.4.x内核,则用户只需在编译内核时加入 ISA Plug and Play support即可。在检测开始之前,必须由用户手动插入模块(modprobe)isapnp.o或者isa-pnp.o(由内核版本决定)。在用户插入上述模块之后,内核会自动生成/proc下对应的描述文件。这些描述文件包括/proc/isapnp,/proc/bus/isapnp/devices,/proc/bus/isapnp/ csn。
例如, 在系统中存在OPL3-SA3类型的声卡时,未挂接设备驱动程序的情况下,/proc/isapnp文件内容如下:
|
上述信息的第一行表示此ISA设备的板卡数,其后的YMH0020表示板卡标识。以" Logical Device"为行首的小节代表不同的逻辑设备(一块isapnp卡上可以存在多个逻辑设备)。" Device is not active "表示此设备的驱动程序未加载,在设备的驱动程序加载后此处显示" Device is active "。在装入设备对应的驱动程序后,其后的字段以"Active"开始表示设备所占用的资源。例如
|
此文件再往下的部分列出的是此卡可以占用的地址空间,一般是一组资源配置方案,上面的例子就包含三组可选的资源配置方案,分别是缺省方案、可选配置方案1(Alternate resources 0:1)和可选配置方案2(Alternate resources 0:2)。
存储设备主要是指硬盘,光驱等能够进行告诉数据存取的设备。我们最常见的存储设备按照总线类型分类主要包括ide,scsi这两种。对于ide设备,Linux系统一般是使用hd*来表示,*是按照连接的总线位置顺序编号。一般而言,我们现在所使用的微机有两个ide接口,并且每个接口上只能连接两个设备,一个为主设备而另一个为从设备。对于连接在ide0上的主设备它的设备名为hda,而对于在ide0上的从设备它的设备名为hdb。以此类推,连接在ide1上的主、从设备的设备名分别为hdc和hdd。
一般而言,现有的linux发行版都将对ide设备的支持加入内核,所以在系统启动之后,相应的设备模块已经在内核中了,所以检测过程只需对/proc/ide下相应的文件进行访问就行了。对于scsi设备,对它们的支持一般都不打入内核,所以要想使scsi设备在Linux下生效必须先插入对应的设备驱动模块。这就要求用户在创建lilo时必须在/etc/lilo.conf中加入一行"initrd=",它连接的由命令mkinitrd生成系统启动映像。例如,在使用Adaptec,AIC-7850的scsi芯片组时,使用模块aic7xxx,此时需要进行如下步骤: mkinitrd --ifneeded /boot/initrd-2.4.3.img 2.4.3 --with=aic7xxx
然后编辑/etc/lilo.conf,加入行: initrd=/boot/initrd-2.4.3.img
重新运行lilo,启动后,这时就会在目录/proc/scsi下出现设备的对应描述文件。只要检索这些文件就可以完成对设备的检测。
physical 16383/16/63
logical 1583/255/63(cylinders/heads/sectors)
表示这块ide硬盘的柱面数,头数和扇区数
|
|
( 待续)