如何在LINUX下实现硬件的自动检测

如何在LINUX下实现硬件的自动检测

 

用过Linux的人都知道在Linux上硬件的配置过程是非常繁杂的。比如说,对于一块普通的pci网卡,您可能先要知道它的芯片类型,网卡生产厂商,然后猜出它对应的硬件驱动模块,然后再使用modprobeinsmod)插入这个模块,再然后还要生成一系列的配置脚本,最后才能使其正常工作。这还只是一块网卡的配置过程,但是对于不胜枚举的其他硬件,如显卡、声卡、modemisdn设备、usb设备、pcmcia设备,而它们的配置方法和生成的配置脚本都不尽相同,因此对于一个普通用户要想全部掌握这些配置过程是相当困难的。硬件的自动检测是进行Linux下设备自动配置过程的前提。本文的内容是先从硬件在Linux下的内核描述信息开始,着重介绍如何实现硬件的自动检测。

设备检测的一般介绍

一般而言,在Linux下进行设备自动检测是根据设备的总线类型进行的。现在的微机系统上最常见的总线类型有PCISERIALUSBPCMCIAPARPORTISASCSI等。对于检测过程,一般不是通过c语言的库函数直接对设备进行访问,并读取设备的信息,而是通过内核的/proc文件系统进行。这种检测方式,充分利用了内核中关于硬件的多种检测函数,具有高效、稳定的特点,并且在内核版本升级之后,使程序的变化也为最小。对于大多数现在流行的系统硬件,在插入适当的模块之后,内核会在/proc文件系统中生成相应的描述文件。检测过程就是读取这样的文件,并将其信息进行相应的处理,从中提取出设备标识、设备描述、设备工作状态等信息。

由于涉及到对/proc文件系统的访问,并可能在检测过程开始时插入需要的设备模块,所以需要用户以root用户方式执行下面所说的操作。

在检测过程结束的时候,用户一般能够得到设备的唯一标识(制造商标识和设备标识)和设备的当前的状态信息。这时就需要一个设备数据库,这个数据库将设备的唯一标识和对应的设备驱动程序对应起来,然后由此生成/etc/modules.conf中的对应表项及其他配置脚本,完成整个的硬件配置过程。

 

PCI设备的自动检测

2.1 PCI设备简介

对于每个pci设备都由一个总线号、一个设备号和一个功能号确定。PCI设备可以访问三类地址空间:PCII/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设备的分类码位0x0100Linux系统的定义见<linux/pci.h>中的声明。现在摘录如下:

#define PCI_CLASS_NOT_DEFINED           0x0000

#define PCI_CLASS_NOT_DEFINED_VGA       0x0001

 

#define PCI_BASE_CLASS_STORAGE          0x01

#define PCI_CLASS_STORAGE_SCSI          0x0100

#define PCI_CLASS_STORAGE_IDE           0x0101

#define PCI_CLASS_STORAGE_FLOPPY        0x0102

#define PCI_CLASS_STORAGE_IPI           0x0103

#define PCI_CLASS_STORAGE_RAID          0x0104

#define PCI_CLASS_STORAGE_OTHER         0x0180

 

#define PCI_BASE_CLASS_NETWORK          0x02

#define PCI_CLASS_NETWORK_ETHERNET      0x0200

#define PCI_CLASS_NETWORK_TOKEN_RING        0x0201

#define PCI_CLASS_NETWORK_FDDI          0x0202

#define PCI_CLASS_NETWORK_ATM           0x0203

#define PCI_CLASS_NETWORK_OTHER         0x0280

 

#define PCI_BASE_CLASS_DISPLAY          0x03

#define PCI_CLASS_DISPLAY_VGA           0x0300

#define PCI_CLASS_DISPLAY_XGA           0x0301

#define PCI_CLASS_DISPLAY_OTHER         0x0380

 

#define PCI_BASE_CLASS_MULTIMEDIA       0x04

#define PCI_CLASS_MULTIMEDIA_VIDEO      0x0400

#define PCI_CLASS_MULTIMEDIA_AUDIO      0x0401

#define PCI_CLASS_MULTIMEDIA_OTHER      0x0480

 

#define PCI_BASE_CLASS_MEMORY           0x05

#define  PCI_CLASS_MEMORY_RAM           0x0500

#define  PCI_CLASS_MEMORY_FLASH         0x0501

#define  PCI_CLASS_MEMORY_OTHER         0x0580

 

#define PCI_BASE_CLASS_BRIDGE           0x06

#define  PCI_CLASS_BRIDGE_HOST          0x0600

#define  PCI_CLASS_BRIDGE_ISA           0x0601

#define  PCI_CLASS_BRIDGE_EISA          0x0602

#define  PCI_CLASS_BRIDGE_MC            0x0603

#define  PCI_CLASS_BRIDGE_PCI           0x0604

#define  PCI_CLASS_BRIDGE_PCMCIA        0x0605

#define  PCI_CLASS_BRIDGE_NUBUS         0x0606

#define  PCI_CLASS_BRIDGE_CARDBUS       0x0607

#define  PCI_CLASS_BRIDGE_OTHER         0x0680

 

#define PCI_BASE_CLASS_COMMUNICATION        0x07

#define PCI_CLASS_COMMUNICATION_SERIAL      0x0700

#define PCI_CLASS_COMMUNICATION_PARALLEL    0x0701

#define PCI_CLASS_COMMUNICATION_OTHER       0x0780

 

#define PCI_BASE_CLASS_SYSTEM           0x08

#define PCI_CLASS_SYSTEM_PIC            0x0800

#define PCI_CLASS_SYSTEM_DMA            0x0801

#define PCI_CLASS_SYSTEM_TIMER          0x0802

#define PCI_CLASS_SYSTEM_RTC            0x0803

#define PCI_CLASS_SYSTEM_OTHER          0x0880

 

#define PCI_BASE_CLASS_INPUT            0x09

#define PCI_CLASS_INPUT_KEYBOARD        0x0900

#define PCI_CLASS_INPUT_PEN         0x0901

#define PCI_CLASS_INPUT_MOUSE           0x0902

#define PCI_CLASS_INPUT_OTHER           0x0980

 

#define PCI_BASE_CLASS_DOCKING          0x 0a

#define PCI_CLASS_DOCKING_GENERIC       0x 0a 00

#define PCI_CLASS_DOCKING_OTHER         0x 0a 01

 

#define PCI_BASE_CLASS_PROCESSOR        0x0b

#define PCI_CLASS_PROCESSOR_386         0x0b00

#define PCI_CLASS_PROCESSOR_486         0x0b01

#define PCI_CLASS_PROCESSOR_PENTIUM     0x0b02

#define PCI_CLASS_PROCESSOR_ALPHA       0x0b10

#define PCI_CLASS_PROCESSOR_POWERPC     0x0b20

#define PCI_CLASS_PROCESSOR_CO          0x0b40

 

#define PCI_BASE_CLASS_SERIAL           0x 0c

#define PCI_CLASS_SERIAL_FIREWIRE       0x 0c 00

#define PCI_CLASS_SERIAL_ACCESS         0x 0c 01

#define PCI_CLASS_SERIAL_SSA            0x 0c 02

#define PCI_CLASS_SERIAL_USB            0x 0c 03

#define PCI_CLASS_SERIAL_FIBER          0x 0c 04

#define PCI_CLASS_SERIAL_SMBUS          0x 0c 05

 

#define PCI_BASE_CLASS_INTELLIGENT      0x0e

#define PCI_CLASS_INTELLIGENT_I2O       0x0e00

 

#define PCI_CLASS_HOT_SWAP_CONTROLLER       0xff00

 

#define PCI_CLASS_OTHERS            0xff

 

Base Address 0- Base Address 5
表示此卡占用的内存范围。

IRQ Line
指定的设备所使用的中断号,它在系统启动时由固件复制。

IRQ Pin
PCI
卡有4个物理引脚,用于把中断从卡上发送到PCI总线上。为0表示设备不支持中断,非0表示使用哪一个终端引脚。此信息可让中断处理子系统处理来自该设备的中断。

关于pci设备的其他信息,您可以参考PCI Local Bus Specification

2.2 LinuxPCI设备的检测过程

一个pci设备可映射到最多六个地址区段。每个区段由内存或I/O位置组成。区段的大小和当前位置由配置寄存器报告。

检测pci设备先要打开文件/proc/bus/pci/devices,例如存在下列数据:

003980867111    0000000000000000000000000000000000000f 0010000000000000000

 

上面的数据表示一个pci设备,对于第一个数字0039(十六进制表示),高八位表示总线号(bus),对于低三位表示功能号(function),剩余的五位表示设备号(device)。也就是说,0039表示,总线0,设备号为7,功能号为1。由此,内核生成设备对应的文件/proc/bus/pci/bus/device.function。此文件为256个字节,对应读出的设备配置信息,第十字节开始的双字节表示设备的类型。第二个数字80867111表示,设备的vendorid8086deviceid7111。通过查询设备配置数据库可知设备标识80867111表示Intel Corporation|82371AB PIIX4 IDE控制器。第三个数字表示占用的irq

用户可以通过察看/proc/pci文件,可以获得系统连接的pci设备的基本信息描述,或者用户也可以使用命令lspci(需要安装包pciutils)来察看PCI设备较为详细的描述信息。但是为了使内核显示上述信息,必须要在编译内核时加入PCI设备名数据库,这会使内核增大约80KB

关于Linux系统PCI设备的进一步信息您可以阅读 http://www.linuxdoc.org/HOWTO/PCI-HOWTO.html

 

ISAPNP设备的自动检测

3.1 ISAPNP设备简介

在每个ISAPNP设备加电启动之后,都会进行一个自动配置过程,它的主要步骤如下:

  • 设置所有的isapnp卡为配置模式
  • 每次隔离一个isapnp
  • 指定一个句柄并读取卡的资源数据结构
  • 在所有的卡的资源需求和兼容性被决定之后,使用句柄指派每个卡无冲突的资源
  • 激活所有的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

0x 0A 79 (Printer status port + 0x0800)

Write-only

READ_DATA

Relocatable in range 0x0203 to 0x03FF

Read-only

Table 1. 自动配置端口

  • 地址端口(ADDRESS Port

在访问pnp寄存器之前,首先写寄存器地址到地址端口,紧接着从READ_DATA端口读或者从WRITE_DATA端口写。地址端口也是初始键的写目标。

隔离机制的关键是每个卡都有一个独一无二的编号(serial identifier)。serial identifier是一个72位独一无二、非0的数字,由两个32位域和一个8位校验位组成。头32位是制造商标识,另32位可以是任何值。只要不存在任何两块编号相同的卡。



Figure 1. Shifting of Serial Identifier

在隔离过程结束时,当前控制的卡被指定一个句柄,称为Card Select NumberCSN),用于以后检索此卡。在卡响应其他的命令之前,此卡必须被指定一个CSN

CSN是一个8位寄存器,加电使所有卡的此寄存器置为0x0。一旦卡的隔离操作结束,此卡的CSN寄存器被指定一个独一无二的值,以使pnp软件能区别所用的卡。isapnp状态如下:

  • Wait for Key
    在加电重设之后或在响应重设与等待命令之后所有卡进入此状态。在此状态下没有命令被激活直到初始键被检测。 Wait for Key在正常系统操作过程中是pnp卡的缺省状态。在配置和激活操作之后,软件应设置所有的卡到此状态。
  • Sleep
    在此状态,pnp卡等待Wake[CSN]命令。此命令会由CSN值设置一个或多个卡进入IsolationConfig状态。在Wake[CSN]命令的写数据位[7:0]的值与卡的CSN匹配时,卡离开Sleep状态。若Wake[CSN]命令写数据为0,所有的没有指定CSN的卡会进入Isolation状态。若Wake[CSN]命令写数据为非0Wake[CSN]命令的CSN参数与卡上分派的CSN匹配的卡会进入Config状态。
  • Isolation
    在此状态,pnp卡响应对隔离寄存器的读请求。一旦卡被隔离,独一无二的CSN被指定,CSN作为卡的唯一标识用于在Wake[CSN]命令中选择此卡。一旦写入CSN,卡过渡到Config状态。
  • Config
    在此状态的卡会响应所有的配置命令,包括读卡的资源配置信息以及编程卡的资源选择。

 

关于ISAPNP设备的详细的硬件信息,您可以参考 ISAPNP Specification

3.2 Linux系统下ISAPNP设备的自动检测

ISA设备的自动检测是指对支持Plug and Play ISA规范1.0ISA设备的检测,对不支持此规范的ISA设备,此检测过程是无法工作的。这时的硬件检测和配置是完全要根据用户的个人经验进行。在进行下述检测过程之前,对于基于2.2.X内核的Linux系统,需要用户安装包isapnptools。对于2.4.x内核,则用户只需在编译内核时加入 ISA Plug and Play support即可。在检测开始之前,必须由用户手动插入模块(modprobeisapnp.o或者isa-pnp.o(由内核版本决定)。在用户插入上述模块之后,内核会自动生成/proc下对应的描述文件。这些描述文件包括/proc/isapnp/proc/bus/isapnp/devices/proc/bus/isapnp/ csn

例如,在系统中存在OPL3-SA3类型的声卡时,未挂接设备驱动程序的情况下,/proc/isapnp文件内容如下:

Card 1 'YMH0020:OPL3-SA3 Sound Board' PnP version 1.0

  Logical device 0 'YMH0021:Unknown'

    Device is not active

    Active DMA 0,0

    Resources 0

      Priority preferred

      Port 0x220-0x220, align 0xf, size 0x10, 16-bit address decoding

      Port 0x530-0x530, align 0x7, size 0x8, 16-bit address decoding

      Port 0x388-0x388, align 0x7, size 0x8, 16-bit address decoding

      Port 0x330-0x330, align 0x1, size 0x2, 16-bit address decoding

      Port 0x370-0x370, align 0x1, size 0x2, 16-bit address decoding

      IRQ 5 High-Edge

      DMA 0 8-bit byte-count type-A

      DMA 1 8-bit byte-count type-A

      Alternate resources 0:1

        Priority acceptable

        Port 0x240-0x240, align 0xf, size 0x10, 16-bit address decoding

        Port 0xe80-0xe80, align 0x7, size 0x8, 16-bit address decoding

        Port 0x388-0x388, align 0x7, size 0x8, 16-bit address decoding

        Port 0x300-0x300, align 0x1, size 0x2, 16-bit address decoding

        Port 0x100-0xffe, align 0x1, size 0x2, 16-bit address decoding

        IRQ 5,7,2/9,10,11 High-Edge

        DMA 0,1,3 8-bit byte-count type-A

        DMA 0,1,3 8-bit byte-count type-A

      Alternate resources 0:2

        Priority functional

        Port 0x220-0x280, align 0xf, size 0x10, 16-bit address decoding

        Port 0x530-0xf48, align 0x7, size 0x8, 16-bit address decoding

        Port 0x388-0x 3f 8, align 0x7, size 0x8, 16-bit address decoding

        Port 0x300-0x334, align 0x1, size 0x2, 16-bit address decoding

        Port 0x100-0xffe, align 0x1, size 0x2, 16-bit address decoding

        IRQ 3,5,7,2/9,10,11 High-Edge

        DMA 0,1,3 8-bit byte-count type-A

        DMA 0,1,3 8-bit byte-count type-A

  Logical device 1 'YMH0022:Unknown'

    Compatible device PNPb 02f

    Device is not active

    Active DMA 0,0

    Resources 0

      Priority preferred

      Port 0x201-0x201, align 0x0, size 0x1, 16-bit address decoding

      Alternate resources 0:1

        Priority functional

        Port 0x201-0x211, align 0xf, size 0x1, 16-bit address decoding

 

上述信息的第一行表示此ISA设备的板卡数,其后的YMH0020表示板卡标识。以" Logical Device"为行首的小节代表不同的逻辑设备(一块isapnp卡上可以存在多个逻辑设备)。" Device is not active "表示此设备的驱动程序未加载,在设备的驱动程序加载后此处显示" Device is active "。在装入设备对应的驱动程序后,其后的字段以"Active"开始表示设备所占用的资源。例如

   Active port 0x240,0xe80,0x388,0x300,0x100(占用的端口号)

    Active IRQ 5 [0x2] (占用的中断号)

    Active DMA 1,3    (占用的DMA

 

此文件再往下的部分列出的是此卡可以占用的地址空间,一般是一组资源配置方案,上面的例子就包含三组可选的资源配置方案,分别是缺省方案、可选配置方案1Alternate resources 0:1)和可选配置方案2Alternate resources 0:2)。

 

存储设备的自动检测

存储设备主要是指硬盘,光驱等能够进行告诉数据存取的设备。我们最常见的存储设备按照总线类型分类主要包括idescsi这两种。对于ide设备,Linux系统一般是使用hd*来表示,*是按照连接的总线位置顺序编号。一般而言,我们现在所使用的微机有两个ide接口,并且每个接口上只能连接两个设备,一个为主设备而另一个为从设备。对于连接在ide0上的主设备它的设备名为hda,而对于在ide0上的从设备它的设备名为hdb。以此类推,连接在ide1上的主、从设备的设备名分别为hdchdd

一般而言,现有的linux发行版都将对ide设备的支持加入内核,所以在系统启动之后,相应的设备模块已经在内核中了,所以检测过程只需对/proc/ide下相应的文件进行访问就行了。对于scsi设备,对它们的支持一般都不打入内核,所以要想使scsi设备在Linux下生效必须先插入对应的设备驱动模块。这就要求用户在创建lilo时必须在/etc/lilo.conf中加入一行"initrd=",它连接的由命令mkinitrd生成系统启动映像。例如,在使用AdaptecAIC-7850scsi芯片组时,使用模块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下出现设备的对应描述文件。只要检索这些文件就可以完成对设备的检测。

  • ide设备的检测过程

1.       查找/proc/ide/下名为的hd**为通配符,可为a,b,…)的目录(目录名为设备名)。

2.       打开文件/proc/ide/hd*/media,此文件的只由一行构成,其内容为cdromdisktapefloppy,此文件的内容表示此IDE设备的类型。

3.       打开文件/proc/ide/hd*/model,由此文件得到详细的设备描述信息。例如:ST 313021A ,表示希捷硬盘,型号为ST 313021A

4.       打开文件/proc/ide/hd*/geometry,这个文件描述的是硬盘的几何信息。例如

physical 16383/16/63
logical 1583/255/63
cylinders/heads/sectors
表示这块ide硬盘的柱面数,头数和扇区数

5.       由命令mknod path, b, major, minor,创建设备结点。对于从/dev/hda/dev/hdh的设备结点的主次设备号为:

/dev/hda        major = 3, minor = 0

/dev/hdb        major = 3, minor = 64

/dev/hdc        major = 22, minor = 0

/dev/hdd        major = 22, minor = 64

/dev/hde        major = 33, minor = 0

/dev/hdf        major = 33, minor = 64

/dev/hdg        major = 34, minor = 0

/dev/hdh        major = 34, minor = 64

6.        

  • scsi设备的检测过程

1.       读入/proc/scsi/scsi文件,其文件结构:

Attached devices:

Host: scsi****  Channel: **** Id: **** Lun: ****

  Vendor:   XXXXXXX Modelxxxxxx Rev

  Type:     Direct-Access(类型为hd,设备名为sd*

                Sequential-Access(类型为tape,设备名为st*

                CD-ROM  (类型为cdrom,设备名为scd*

                Scanner (类型为scanner,设备名为sg*

                Printer (类型为printer,设备名为sg*)

                其他设备(设备名为sg*

 

USB设备的自动检测

5.1 USB设备检测的一般过程

USB设备检测也是通过/proc目录下的USB文件系统进行的。为了使一个USB设备能够正常工作,必须要现在系统中插入USB桥接器模块。在检测开始时,一般要先检测是否存在/proc/bus/usb目录,若不存在则尝试插入USB桥接模块。

现在一般的USB桥接器模块有两种类型,UHCIOHCI。在决定插入那一个桥接器模块时,可以察看/proc/pci文件来决定。打开此文件,您若发现USB节为 I/O at 0xHHHH格式(例如出现 I/O at 0xe000 [0xe 01f ]),HHHH16进制数,则桥接器类型为UHCI。若是它为 32 bit memory at 0xHH000000形式(例如出现32 bit memory at 0xee000000),HH16进制数,则桥接器类型为OHCI。但是若您的桥接器类型不满足上述任何一种情况,唯一的解决办法就是您尝试插入这两种模块,直到成功为止。一般而言,UHCI类型的桥接器它的插入模块是uhciusb-uhci(由内核版本决定);而对于OHCI类型的桥接器它的插入模块是ohciusb-ohci

您在正确的插入了桥接器模块之后,这时/proc文件系统下就会出现USB设备目录,不过这时这个目录是空的,没有任何文件。这时您就必须挂接usbdevfs文件系统,然后通过此文件系统检测连接的设备。在成功挂接usb文件系统之后,就会生成文件/proc/bus/usb/devices/proc/bus/usb/drivers和目录/proc/bus/usb/busNo。挂接usbdevfs文件您可以通过如下操作实现:
mount -t usbdevfs none /proc/bus/usb
或在/etc/fstab上加入
none /proc/bus/usb usbdevfs defaults 0 0

然后通过/proc/bus/usb/devices文件的内容,您就可以获得连接的设备信息,包括设备标识和制造商标是等信息。

usb设备类型描述:

5-1 usb设备类码

设备规范

设备类码

接口类码

应用程序特定

-

0xFE

声音接口

0x00

0x01

通信设备

0x02

-

CDC控制接口e

-

0x02

CDC数据接口

-

0x 0A

HID

0x00

0x03

HUB

0x09

0x09

批量存储设备

0x00

0x08

监视器

same as HID

same as HID

电源设备

same as HID

same as HID

物理设备

-

0x05

打印机

-

0x07

供应商特定

-

0xFF

5.2 usb文件系统简介

T = 总线拓扑结构(Lev, Prnt, Port, Cnt,
),是指USB设备和主机之间的连接方式
B =
带宽 (仅用于USB主控制器)
D =
设备描述信息
P =
产品标识信息
S =
串描述符
C =
配置描述信息 (* 表示活动配置)
I =
接口描述信息
E =
终端点描述信息

一般格式:
d =
十进制数
x =
十六进制数
s =
字符串

拓扑信息

T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd

|   |       |       |         |        |        |         |         |__最大子设备

|   |       |       |         |        |        |         |__设备速度(Mbps

|   |       |       |         |        |        |__设备编号

|   |       |       |         |        |__这层的设备数

|   |       |       |         |__此设备的父连接器/端口

|   |       |       |__父设备号

|   |       |__此总线在拓扑结构中的层次

|   |__总线编号

|__拓扑信息标志

 

带宽信息

B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd

|   |                            |           |__同步请求编号

|   |                            |__中断请求号

|   |__分配给此总线的总带宽

|__带宽信息标志

 

设备描述信息和产品标识信息

D:  Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd

P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx

 

D:  Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd

|   |          |               |        |        |        |__配置编号

|   |          |               |        |        |______缺省终端点的最大包尺寸

|   |          |               |        |                  

|   |          |               |        |__设备协议

|   |          |               |__设备子类型

|   |          |__设备类型

|   |__设备USB版本

|__设备信息标志编号#1

 

P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx

|   |             |              |__产品修订号

|   |             |__产品标识编码

|   |__制造商标识编码

|__设备信息标志编号#2

 

串描述信息

S:  Manufacturer=ssss

|   |__设备上读出的制造商信息

|__串描述信息

 

S:  Product=ssss

|   |__设备上读出的产品描述信息,对于USB主控制器此字段为"USB *HCI Root Hub"

|__串描述信息

 

S:  SerialNumber=ssss

|   |__设备上读出的序列号,对于USB主控制器它是一个生成的字符串,表示设备标识

|__串描述信息

 

配置描述信息

C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA

|   |         |        |       |__最大电流(mA

|   |         |        |__属性

|   |         |__配置编号

|   |__接口数

|__配置信息标志

 

接口描述信息(可为多个)

I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss

|   |       |        |        |                |       |        |__驱动名

|   |       |        |        |                |       |__接口协议

|   |       |        |        |                |__接口子类

|   |       |        |        |__接口类

|   |       |        |__中断点数

|   |       |__可变设置编号

|   |__接口编号

|__接口信息标志

 

终端点描述信息

E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms

E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms

|   |          |              |           |__间隔

|   |          |              |__终端点最大包尺寸

|   |          |__属性(终端点类型)

|   |__终端点地址(I=In,O=Out)

|__终端点信息标志

 

举个例子,这是在连接了一个USB键盘时的配置情况。

 

T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh=

2

B: Alloc= 41/900 us ( 5%), #Int= 3, #Iso= 0

D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1

P: Vendor=0000 ProdID=0000 Rev= 0.00

S: Product=USB UHCI Root Hub

S: SerialNumber=e000

C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA

I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00

Driver=hub

E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms

T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh=

3

D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1

P: Vendor=07e4 ProdID=a961 Rev= 0.01

S: Manufacturer=ALCOR

S: Product=Movado USB Keyboard

C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA

I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00

Driver=hub

E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms

T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh=

0

D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1

P: Vendor=07e4 ProdID=a961 Rev= 0.01

S: Manufacturer=ALCOR

S: Product=Movado USB Keyboard

C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr= 0mA

I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=01

Driver=hid

E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl= 10ms

I: If#= 1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00

Driver=hid

E: Ad=82(I) Atr=03(Int.) MxPS= 4 Ivl=255ms

 

它的物理拓扑可用下图来表示:


对于Linux下的usb设备而言,T:(总线拓扑)行用于生成连接在hub上的设备的描述信息,I:(接口信息)行可用于决定每个设备所用的驱动程序,C:(配置信息)可用于列出设备使用最大电流。

对于Linux下的usb设备,您可以访问 http://www.linux-usb.org获取更详细的信息。

 

并行设备的自动检测

6.1 并行设备检测的一般过程

Linux下要实现连接在并口上的设备检测,要求设备必须是支持IEEE 1284协议的。对于不支持IEEE 1284通讯协议的并行设备,是无法完成自动检测的。同样在定制系统内核时,也必须在并行端口支持(Parallel port support)选项中选中IEEE 1284 transfer mode这一项。在并口检测开始时,检测程序应检查是否存在/proc/sys/dev/parport目录(针对2.4.x内核),若不存在则尝试插入模块parport。加载parport模块一般有三种方式:

  • 静态插入模块
    insmod parport.o
    insmod parport_pc.o io=0x3bc,0x378,0x278 irq=none,7,auto
    废除系统缺省的检测值
  • kmod/etc/modules.conf)加载
    alias parport_lowlevel parport_pc
    options parport_pc io=0x378,0x278 irq=7,auto
    内核的并口探测程序用于获得IEEE 1284设备标识信息。在并口被检测时,连接到其上的设备被分析。探测的信息在/proc/sys/dev/parport/
  • 在编译并口代码进入内核之后,使用内核加在参数
    如:加入LILO命令行
    parport=0x3bc parport=0x378,7 parport=0x278,auto,nofifo
    parport=0
    禁止内核parport支持
    parport=auto
    内核自动检测

在成功的插入了此模块之后,这时/proc文件系统下就会存在目录/proc/sys/dev/parport,但是此时此目录下的文件大部分为空,没有任何内容。这时您就可以根据并口连接的设备,尝试插入相应的内核驱动模块。例如,当连接并口打印机时,您可以插入模块lp。使用如下命令:
insmod lp parport=0
(对于打印机连接在并口0(LPT1)

在成功插入此模块之后,而且在连接的并口设备支持IEEE 1284协议时,这时此目录下的autoprobemodes等文件会出现设备上读出的设备描述以及设备配置信息。由此信息,您可以在CUPS中选择对应的打印机驱动程序,完成打印机的配置。

6.2 /proc/sys/dev/parport/文件结构

目录树:

parport

|-- default

|   |-- spintime

|   `-- timeslice

|-- parport0

|   |-- autoprobe

|   |-- autoprobe0

|   |-- autoprobe1

|   |-- autoprobe2

|   |-- autoprobe3

|   |-- devices

|   |   |-- active

|   |   `-- lp

|   |       `-- timeslice

|   |-- base-addr

|   |-- irq

|   |-- dma

|   |-- modes

|   `-- spintime

`-- parport1

    |-- autoprobe

    |-- autoprobe0

    |-- autoprobe1

    |-- autoprobe2

    |-- autoprobe3

    |-- devices

    |   |-- active

    |   `-- ppa

    |       `-- timeslice

    |-- base-addr

    |-- irq

    |-- dma

    |-- modes

    `-- spintime

 

文件

文件内容

devices/active

使用那个端口的设备驱动程序列表。在当前使用端口的设备前会出现一个"+"号。串"none"意味着没有设备驱动程序使用这个端口。

base-addr

并行端口的基地址或再不只一个端口时由tab分隔的多个基地址。

irq

并行端口的IRQ,若不使用时则用-1

dma

并行端口的dma通道,若没有使则用-1

modes

并行端口的硬件模式PCSPP PC风格的SPP寄存器可用(标准并行端口)TRISTATE 端口是双向的COMPAT 打印机的硬件加速可用EPP EPP协议的硬件加速可用(增强并行端口)ECP ECP协议的硬件加速可用DMA DMA可用

autoprobe

已经获得的IEEE-1284设备标识信息

autoprobe[0-3]

从遵循IEEE-1284.3的雏菊链路设备取出的设备信息

spintime

忙循环等待外设响应的微秒数。调节此值可以改善外设的性能。这是端口级的设置。它应用于此端口上的所有设备

timeslice

设备驱动程序允许保持端口声明的微秒数。这只是一个建议,驱动程序在必要时可以忽略。

default/*

在注册新端口时,它取出缺省的spintime。在注册新设备时,它取出缺省时间片。

例如,在系统连接了HP LaserJet 6L 打印机之后,此目录下关键文件的内容为:

/proc/sys/dev/parport/parport0/autoprobe

CLASS:PRINTER;                      (连接的设备为打印机)

MODEL:HP LaserJet 6L ;               (打印机类型描述)

MANUFACTURER:Hewlett-Packard;       (制造商类型)

DESCRIPTION:Hewlett-Packard LaserJet 6L Printer;

 

/proc/sys/dev/parport/parport0/modes

PCSPP,TRISTATE

 

/proc/sys/dev/parport/parport0/base-addr

888 1912

 

/proc/sys/dev/parport/parport0/irq

-1

 

/proc/sys/dev/parport/parport0/dma

-1

 

PCMCIA设备自动检测

因为PCMCIA设备主要用于笔记本电脑,所以在您使用普通的台式电脑时,您无需安装包pcmcia-cs。在笔记本电脑上安装了pcmcia-cs包之后,为了实现PCMCIA设备的自动检测,您可以先查找系统中是否存在/proc/bus/pccard目录,如果不存在此目录则尝试插入pcmcia_core

在成功插入了此模块之后,/proc/bus/pccard目录就生成了。此后,您就可以检查pci的系统设备,找到系统桥接器,根据桥接器类型获得您需要插入的桥接器模块。例如,在我的系统上,桥接器为Texas Instruments PCI1251,则它的桥接器为i82365。在Linux系统下,适用的桥接器模块一般只有i82365tcic两种。若无法获得准确的桥接器驱动程序,您可以尝试着插入两种模块,直到成功时为止。

然后为了能够实时的配置您的pccard,您需要启动服务pcmcia
/etc/rc.d/init.d/pcmcia start

并由此服务启动程序cardmgrcardmgr监视pcmcia槽上,卡的插入和弹出操作。在卡插入之后,cardmgr查询卡的配置数据库。若发现卡能够被标识,相应的设备驱动程序则会自动加载。在弹出卡之后,卡的驱动程序会自动的关闭并卸载。当卡插入之后,每个槽上的卡信息和设备信息都被记录在/var/lib/pcmcia/stab文件中。

7.1 /proc/bus/pccard目录结构

/proc/bus/pccard/{irq,ioport,memory}
包含资源分配表

/proc/bus/pccard/drivers
这会列出所有当前加载的pcmcia客户驱动程序,包括静态连接到内核的模块

/proc/bus/pccard/*/info
对于每个socket,描述socket主控制器和它的性能,*为对应的socket编号

/proc/bus/pccard/*/exca
Intel i82365sl
兼容的寄存器集的ExCA控制器的转储

/proc/bus/pccard/*/{pci,cardbus}
对于cardbus桥,桥的pci配置空间的转储和桥的cardbus配置寄存器的转储

7.2 pcmcia配置文件

/etc/pcmcia/config实际上是一个针对pcmcia设备的配置数据库,它的内容主要是指定卡驱动程序加载时所需的模块。例如
device "serial_cs"
class "serial" module "misc/serial", "serial_cs"
表示在插入serial_cs时,需要先插入模块misc/serialserial_cs

pcmcia主机控制器的主要类型为

  • Databook TCIC-2
  • Intel i82365SL-compatible

当前pcmcia设备包括5IO设备类型包括networkSCSIcdromfixed disk,和serial以及2种内存设备类型memoryFTL。对于每一种类型,在/etc/pcmcia/目录下存在两个配置脚本,例如,对于scsi设备都存在一个主配置脚本(/etc/pcmcia/scsi)和选项配置脚本(/etc/pcmcia/scsi.opts)。

7.3 pcmcia启动脚本(/etc/sysconfig/pcmcia

PCMCIA
yes表示启动PCMCIA支持

PCIC
标识PCCard接口控制驱动模块。一般有两种类型:tcici82365,缺省是i82365

PCIC_OPTS
PCIC
模块的选项

例如:PCIC_OPTS="irq_list=5,9,10""do_scan=0" 完全禁止中断检测

CORE_OPTS
pcmcia_core
模块的选项。见man pcmcia_core

CARDMGR_OPTS
cardmgr
守护程序的选项。见man cardmgr

SCHEME
设置pccard的配置方案。

cardmgr处理/etc/pcmcia/config.opts中的io端口范围。但在极少的情况下,从设备读可以阻碍系统功能而导致死锁。在CORE_OPTS中加入probe_io=0,可以禁止此操作。使用i82365tcic驱动程序时,irq_list选项可用于限制测试的中断。cs_irq用于明确设置中断以检测卡状态改变。若不能使用中断,可以使用poll_interval=100100表示轮询间隔为1秒)设置轮询。这些选项应置入/etc/rc.d/rc.pcmcia/etc/sysconfig/pcmcia"PCIC_OPTS="行。

7.4 cardmgrcardctl的使用

cardmgr基于/etc/pcmcia/config中的信息来配置卡。cardmgr为每个socket记录设备信息,此信息存于/var/lib/pcmcia/stab中。例如:

Socket 0: Adaptec APA-1460 SlimSCSI

    0       scsi    aha152x_cs      0       sda     8       0

    0       scsi    aha152x_cs      1       scd0    11      0

Socket 1: Serial or Modem Card

    1       serial  serial_cs       0       ttyS1   5       65

 

第一个域表示socket,第二个是设备类型,第三个是设备名,第四个用于关联多个设备和一个驱动程序时的设备编号。第五个是设备名。最后两个域标是设备的主、次设备号。
cardctl
可用于监视和控制当前pcmcia socket的状态。
cardctl config
,显示socket配置,包括电源,中断,I/O配置。例如:

Socket 0:

      not configured

    Socket 1:

      Vcc = 5.0, Vpp1 = 0.0, Vpp2 = 0.0

      Card type is memory and I/O

      IRQ 3 is dynamic shared, level mode, enabled

      Speaker output is enabled

      Function 0:

        Config register base = 0x0800

          Option = 0x63, status = 0x08

        I/O window 1: 0x0280 to 0x02bf, auto sized

        I/O window 2: 0x 02f 8 to 0x02ff, 8 bit

 

cardctl indent,得到卡的标识信息,包括产品标识信息,制造商标识代码,功能标识代码:

Socket 0:

      no product info available

    Socket 1:

      product info: "LINKSYS", "PCMLM336", "A", "0040052D6400"

      manfid: 0x0143, 0xc0ab

      function: 0 (multifunction)

 

cardctl suspendcardctl resume用于无需卸载相关驱动程序的情况下关闭卡。cardctl reset用于尝试重设和重新配置卡。cardctl insertcardctl eject用于仿真卡的物理的插入和删除动作。推荐在退出卡之前,执行cardctl eject命令。/etc/rc.d/rc.pcmcia stop会卸载所有的pcmcia包。

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值