mailto:dave@lafn.org
版权所有 (c) 1998-2007 David S. Lawyer mailto:dave@lafn.org
请随意复制和分发(出售或赠送)本文档的任何格式。请将任何更正和意见发送给文档维护者。您可以创建衍生作品并分发它,前提是您
如果您正在考虑制作翻译作品以外的衍生作品,则请求您与当前的维护者讨论您的计划。
虽然我没有故意误导您,但本文档中可能存在许多错误。请告知我这些错误。由于这是免费文档,因此显而易见,我对任何错误不承担法律责任。
任何品牌名称(以大写字母开头,例如 MS Windows)都应假定为商标)。此类商标属于其各自的所有者。
请告知我事实、观点、逻辑、拼写、语法、清晰度、链接等方面的任何错误。但首先,如果日期超过几个月,请检查以确保您拥有最新版本。请将您认为属于本文档的任何信息发送给我。
我还没有研究各种 Linux 驱动程序和内核用于实现即插即用的代码。但我已经对其进行了一些采样(尤其是某些注释)。因此,这份 HOWTO 仍然不完整。它需要更多地解释“热交换”、“热插拔”以及内核 2.6 的新 PnP 软件。Linux PnP 的历史没有得到很好的涵盖。此外,它不涵盖火线。它可能有一些不准确之处(请告知我哪里错了)。在这份 HOWTO 中,我有时使用 ?? 来表示我真的不知道答案。
即插即用-HOWTO 的新版本应每年左右出现一次,并且可以在 LDP 镜像站点浏览和/或下载。有关镜像站点列表,请参阅:https://tldp.cn/mirrors.html。提供各种格式。如果您只想快速查看最新版本的日期,请查看:https://tldp.cn/HOWTO/Plug-and-Play-HOWTO.html。您现在阅读的版本是:v1.15,2007 年 8 月。
有关追溯到第一个版本的完整修订历史,请参阅源文件(linuxdoc 格式),网址为 http://cvsview.tldp.org/index.cgi/LDP/howto/linuxdoc/Plug-and-Play-HOWTO.sgml
即插即用 (PnP) 是一种自动检测设备(如磁盘、声卡、以太网卡、调制解调器等)的系统。它可以找到 PCI 总线上的所有设备以及旧 ISA 总线上支持 PnP 的所有设备。在 PnP 之前,许多设备是通过非 PnP 方法自动搜索的,但有时找不到。PnP 提供了一种查找所有支持 PnP 的设备的方法。它还对它们进行一些低级配置。非 PnP 设备(或未正确 PnP 配置的 PnP 设备)通常可以通过非 PnP 方法检测到。PCI 总线本质上是 PnP,而旧 ISA 总线最初不是 PnP,但在之后添加了 PnP 支持。因此,有时 PnP 仅用于表示旧 ISA 总线的 PnP。例如,当您看到来自“isapnp”的启动时消息并且显示:“即插即用设备”时,它仅表示 ISA 即插即用设备。在这份 HOWTO 中,PnP 表示 ISA 和 PCI 总线的 PnP。
随着时间的推移,Linux 内核在支持 PnP 方面变得越来越好。在 20 世纪末,人们可能会说 Linux 并不是真正的 PnP 操作系统。但有人声称,对于内核的 2.6 版本,Linux 现在是完全 PnP 的(前提是内核是在适当的 PnP 支持下构建的)。虽然 PnP 系统不像 MS Windows 那样集中化(带有注册表),但分散式的 Linux PnP 似乎工作正常。
Linux 确实会跟踪设备驱动程序请求的资源分配,如果它认为会导致冲突,则会拒绝任何请求。内核还提供设备驱动程序可以调用的程序来执行自己的即插即用。内核还读取所有 PnP 设备的所有配置寄存器,并维护设备驱动程序可以查阅的表。此表帮助驱动程序找到其硬件。内核 2.6 为“热插拔”提供了更好的支持。
您的 PC 的 BIOS 硬件也可能做一些即插即用工作。因此,如果一切 PnP 方面都工作正常,您可以使用计算机而无需了解任何关于即插即用的知识。但是,如果某些 Linux 支持的设备无法工作(因为它们没有被 PnP 正确发现或配置),那么您可能需要阅读这份 HOWTO 的一些内容。您不仅会了解 PnP,还会了解计算机内部如何进行通信。如果您拥有一台带有 PCI 总线但没有 ISA 总线的现代计算机,您可以跳过或略读有关 ISA 总线的部分。
如果您在设备方面遇到问题,请查看启动时显示的消息(使用 Shift-PageUp 向后浏览)。如果这也没有显示来自 BIOS 的早期消息,请使用“Pause”键。请参阅 暂停
检查以确保您拥有设备的正确驱动程序,并且驱动程序正在被找到和使用。如果驱动程序是一个模块,请键入“lsmod”(以 root 用户身份)以查看它是否已加载(正在使用)。如果它不是模块,则它应该内置在内核中。
这份 HOWTO 不涵盖查找和安装设备驱动程序的问题。也许它应该涵盖。一个问题是,某个品牌的卡(或其他物理设备)可能不会说明其中使用了哪种芯片。驱动程序名称通常与芯片名称相同,而不是品牌名称。检查驱动程序的一种方法是查看内核文档、另一个 HOWTO 或 Internet 上是否讨论了它。警告:此类文档可能已过时。
PCI 总线计算机(没有 ISA 总线)显着减少了可能出错的事情的数量。对于 ISA 总线以及内核对 ISA Pnp 的支持不足(在内核 2.4 之前),可能出错的事情要多得多。请记住,有时似乎与 PnP 相关的问题实际上是由于硬件缺陷或硬件不完全符合 PnP 规范造成的。
如果您不理解本节,请阅读下一节 硬件设备及其通信
简化来说,即插即用告诉软件(设备驱动程序)在哪里找到各种硬件(设备),例如调制解调器、网卡、声卡等。即插即用的任务是将物理设备与操作它们的软件(设备驱动程序)进行匹配,并在每个物理设备及其驱动程序之间建立通信通道。为了实现这一点,PnP 在硬件中分配和设置以下“总线资源”:I/O 地址、内存区域、IRQ、DMA 通道(仅限 LPC 和 ISA 总线)。这 4 件事有时被称为“一级资源”或简称为“资源”。Pnp 维护其所做工作的记录,并允许设备驱动程序获取此信息。如果您不理解这 4 种总线资源是什么,请阅读本 HOWTO 的以下小节:I/O 地址、IRQ、DMA 通道、内存范围。《Linux Gazette》中关于其中 3 种总线资源的文章是 IRQ、DMA 和基地址简介。一旦分配了这些总线资源(并且如果安装了正确的驱动程序),实际的驱动程序及其在 /dev 目录中的“文件”就可以使用了。
这种 PnP 总线资源的分配有时被称为“配置”,但这只是一种低级类型的配置。/etc 目录中有许多配置文件,但几乎所有配置文件都不是用于 PnP 配置。因此,大多数硬件设备的配置与 PnP 或总线资源无关。例如,通过“初始化字符串”初始化调制解调器或设置其速度不是 PnP。因此,在谈论 PnP 时,“配置”仅表示某种类型的配置。虽然其他文档(例如 MS Windows 的文档)仅将总线资源称为“资源”,但我有时使用术语“总线资源”而不是仅使用“资源”,以便将其与其他各种资源区分开来。
PnP 是一个由各种软件和硬件完成的过程。如果只有一个程序在 Linux 中处理 PnP,那将很简单。但是对于 Linux,每个设备驱动程序都使用内核提供的软件来完成自己的 PnP。PC 的 BIOS 硬件在首次启动 PC 时执行 PnP。而且它比这复杂得多。
计算机由 CPU/处理器(用于计算)和 RAM 内存(用于存储程序和数据以进行快速访问)组成。此外,还有许多设备,例如各种类型的磁盘驱动器、显卡、键盘、网络设备、调制解调器卡、声音设备、USB 总线、串行和并行端口等。在过去,大多数设备都在插入 PC 插槽的卡上。如今,许多以前是卡的设备现在都在板载,因为它们包含在主板上的芯片中。还有一个电源来提供电能,主板上的各种总线将设备连接到 CPU,以及一个机箱来容纳所有这些。
插入主板的卡可能包含多个设备。内存芯片有时也被认为是设备,但在本 HOWTO 中使用的意义上,它们不是即插即用。
为了使计算机系统正常工作,每个设备都必须在其“设备驱动程序”的控制下。这是操作系统的一部分(可能作为模块加载)并在 CPU 上运行的软件。设备驱动程序与 /dev 目录中的“特殊文件”相关联,尽管它们实际上不是文件。它们的名称如 hda3(硬盘驱动器 a 上的第三个分区)、ttyS1(第二个串口)、eth0(第一个以太网卡)等。
eth0 设备用于以太网卡(网卡)。以前它是 /dev/eth0,但现在它只是内核中的一个虚拟设备。eth0 指的是什么取决于您拥有的以太网卡的类型。如果驱动程序是一个模块,则此分配很可能在一个内部内核表中,但可能会在 /etc/modules.conf 中找到(称为“别名”)。例如,如果您有一个使用“tulip”芯片的以太网卡,您可以将“alias eth0 tulip”放入 /etc/modules.conf 中,以便当您的计算机请求 eth0 时,它可以找到 tulip 驱动程序。但是,现代内核通常可以找到正确的驱动程序模块,因此您很少需要自己指定它。
为了控制设备,CPU(在设备驱动程序的控制下)向各种设备发送命令和数据,并从中读取状态和数据。为了做到这一点,每个设备驱动程序都必须知道它控制的设备的地址。知道这样的地址相当于建立一个通信通道,即使物理“通道”实际上是 PC 内部的数据总线,它与其他许多设备共享。
这个通信通道实际上比上面描述的要复杂一些。“地址”实际上是一个地址范围,因此有时使用“范围”一词代替“地址”。甚至可能有一个设备的多个范围(没有重叠)。此外,通道还有一个反向部分(称为中断),允许设备向其设备驱动程序发送紧急“帮助”请求。
PCI 总线有 3 个地址空间:I/O、主内存(IO 内存)和配置。旧的 ISA 总线缺少真正的“配置”地址空间。只有 I/O 和 IO 内存空间用于设备 IO。配置地址是固定的,无法更改,因此不需要分配。有关更多详细信息,请参阅 PCI 配置地址空间
当 CPU 想要访问设备时,它会将设备的地址放在计算机的主要总线(对于 PCI:地址/数据总线)上。所有类型的地址(例如 I/O 和主内存)共享 PC 内部的同一总线。但是,PC 总线中某些专用导线上电压的存在与否会告诉地址位于哪个“空间”中:I/O、主内存(请参阅 内存范围)或配置(仅限 PCI)。这有点过于简化,因为告诉 PCI 设备它是配置空间访问实际上比上面描述的更复杂。有关详细信息,请参阅 PCI 配置地址空间。有关寻址的更多详细信息,请参阅 地址详情。
设备的地址存储在其物理设备中的寄存器中。它们可以由软件更改,并且可以禁用,以便设备根本没有地址。但 PCI 配置地址除外,它无法更改或禁用。
设备最初位于 I/O 地址空间中,但如今它们可以使用主内存中的空间。I/O 地址有时简称为“I/O”、“IO”、“i/o”或“io”。术语“I/O 端口”或“I/O 范围”也经常使用。不要将这些 IO 端口与位于主内存中的“IO 内存”混淆。分配 I/O 地址(或某些其他总线资源,例如 ISA 总线上的中断)主要有两个步骤
通常,设备驱动程序会同时执行这两项操作(某种程度上)。如果设备驱动程序发现地址已预先设置(可能由 BIOS 设置)并且愿意接受该地址,则它实际上不需要设置 I/O 地址。一旦驱动程序发现先前设置的地址或自己设置地址,那么它显然知道地址是什么,因此无需让驱动程序知道地址 —— 它已经知道了。
上面的两步过程(1. 在硬件中设置地址。2. 让驱动程序知道它。)有点像在街道上找到某人的门牌号的两部分问题。必须在房屋正面安装一个号码,以便可以找到它,然后可能想去此地址的人必须获取(并写下)此门牌号,以便他们可以找到房屋。对于计算机,设备硬件必须首先将其地址放入其硬件中的特殊寄存器中(贴上门牌号),然后设备驱动程序必须获取此地址(将门牌号写在其地址簿中)。这两者都必须完成,可以通过软件自动完成,也可以通过手动将数据输入配置文件来完成。当只有其中一个步骤正确完成时,可能会出现问题。
对于手动 PnP 配置,有些人犯了一个错误,只执行这两个步骤中的一个,然后想知道为什么计算机找不到设备。例如,他们可能会使用“setserial”为串口分配地址,但没有意识到这只是告诉驱动程序一个地址。它不会在串口硬件本身中设置地址。如果您告诉驱动程序错误的信息,那么您就麻烦了。告诉驱动程序的另一种方法是将地址作为内核模块(设备驱动程序)的选项给出。如果您告诉它的内容是错误的,则可能会出现问题。一个智能驱动程序可能会检测到硬件的实际设置方式,并拒绝选项提供的错误信息(或至少发出错误消息)。
一个显而易见的要求是,在设备驱动程序可以使用地址之前,必须首先在物理设备(例如卡)中设置该地址。由于设备驱动程序通常在您启动计算机后不久启动,因此它们有时会尝试访问卡(以查看它是否在那里等),然后在 PnP 配置程序在卡中设置地址之前。然后您会看到一条错误消息,说他们找不到卡,即使它在那里(但尚未设置地址)。
最后几段关于 I/O 地址的内容同样适用于大多数其他总线资源:内存范围、IRQ --概述 和 DMA 通道。这些是什么将在接下来的 3 节中解释。例外情况是 PCI 总线上的中断不是由卡寄存器设置的,而是由主板上的芯片路由(映射)到 IRQ 的。然后,PCI 卡路由到的 IRQ 会写入卡寄存器,仅供参考。
要查看您的 PC 上使用了哪些 IO 地址,请查看 /proc/ioports 文件。
许多设备都分配了主内存中的地址空间。它有时被称为“共享内存”或“内存映射 IO”或“IO 内存”。此内存物理上位于物理设备内部,但计算机访问它的方式与访问内存芯片上的内存的方式相同。在讨论总线资源时,它通常简称为“内存”、“mem”或“iomem”。除了使用这样的“内存”外,这样的设备也可能使用传统的 IO 地址空间。要查看您的计算机上正在使用什么 mem,请查看 /proc/iomem。此“文件”包括您的普通 RAM 内存芯片使用的内存,因此它显示的是一般内存分配,而不仅仅是 iomem 分配。如果您看到一个奇怪的数字而不是名称,则它很可能是 PCI 设备的编号,您可以通过键入“lspci”来验证。
当您插入使用 iomem 的卡时,实际上您也在插入主内存的内存模块。PnP 为它选择了一个高地址,这样它就不会与主内存模块(芯片)冲突。此内存可以是 ROM(只读内存)或共享内存。共享内存是在设备和 CPU(运行设备驱动程序)之间共享的,就像 IO 地址空间在设备和 CPU 之间共享一样。此共享内存充当设备和主内存之间数据“传输”的手段。它是输入-输出 (IO),但它不是在 IO 空间中完成的。卡和设备驱动程序都需要知道内存范围。
卡上的 ROM(只读内存)是一种不同类型的 iomem。它很可能是一个程序(可能是设备驱动程序),将与设备一起使用。它可能是初始化代码,因此仍然需要设备驱动程序。希望它能与 Linux 一起工作,而不仅仅是 MS Windows。它可能需要被阴影化,这意味着它被复制到您的主内存芯片中以便更快地运行。一旦它被阴影化,它就不再是“只读”的。
阅读完本文后,您可能想阅读 中断 --详情 以获取更多详细信息。以下内容有意过于简化:除了地址外,还需要处理中断号(例如 IRQ 5)。它被称为 IRQ(中断请求)编号或简称为“irq”。我们已经在上面提到,设备驱动程序必须知道卡的地址才能与其通信。
但是反方向的通信呢?假设设备需要立即告诉其设备驱动程序某些信息。例如,设备可能正在接收大量目标为主内存的字节,并且其用于存储这些字节的缓冲区几乎已满。因此,设备需要告诉其驱动程序立即获取这些字节,以防止缓冲区因传入的字节流而溢出。另一个示例是向驱动程序发出信号,表明设备已完成发送一批字节,现在正在等待来自驱动程序的更多字节,以便它也可以发送它们。
设备应如何快速向其驱动程序发出信号?它可能无法使用主数据总线,因为它可能已经在使用了。相反,它会在专用中断线(也称为线路或迹线)上施加电压,该中断线通常专为该设备保留。此电压信号称为中断请求 (IRQ) 或简称为“中断”。PC 中有相当于 16 条(或 24 条等)这样的线路,每条线路(间接地)通向特定的设备驱动程序。每条线路都有一个唯一的中断请求 (IRQ) 编号。设备必须将其中断放在正确的线路上,并且设备驱动程序必须监听正确线路上的中断。设备在其上发送此类“帮助请求”的线路由存储在设备中的 IRQ 编号决定。设备驱动程序必须知道相同的 IRQ 编号,以便设备驱动程序知道要监听哪个 IRQ 线路。
一旦设备驱动程序从设备收到中断,它必须找出发出中断的原因,并采取适当的措施来处理中断。在 ISA 总线上,每个设备通常需要自己唯一的 IRQ 号码。对于 PCI 总线和其他特殊情况,允许共享 IRQ(两个或多个 PCI 设备可以具有相同的 IRQ 号码)。此外,对于 PCI,每个 PCI 设备都有一个固定的“PCI 中断”线。但是,可编程路由芯片将 PCI 线映射到 ISA 类型的中断。有关上述所有工作原理的详细信息,请参阅 中断 -- 详细信息。
对于 PCI 总线,DMA 和总线控制意味着相同的事情。在 PCI 总线之前,总线控制很少见,DMA 的工作方式不同且速度较慢。直接内存访问 (DMA) 是指允许设备从 CPU 接管主计算机总线,并将字节直接传输到主存储器或某些其他设备。通常,CPU 会分两步完成从设备到主存储器的传输过程
使用 DMA,这是一个将字节直接从设备发送到内存的一步过程。设备必须在其硬件中内置 DMA 功能,因此并非所有设备都可以进行 DMA。在 DMA 进行时,CPU 不能做太多事情,因为主总线正被 DMA 传输使用。
旧的 ISA 总线可以进行慢速 DMA,而 PCI 总线通过总线控制进行“DMA”。LPC 总线既有旧的 DMA 也有新的 DMA(总线控制)。在 PCI 总线上,更准确地应称为“总线控制”的通常被称为“Ultra DMA”、“BM-DNA”、“udma”或仅称为“DMA”。总线控制允许设备临时成为总线主控器,并像总线主控器是 CPU 一样传输字节。它不使用任何通道号,因为 PCI 总线的组织方式使得 PCI 硬件知道哪个设备当前是总线主控器,以及哪个设备正在请求成为总线主控器。因此,PCI 总线没有 DMA 通道的资源分配,并且此总线不存在 DMA 通道资源。LPC(低引脚数)总线应该由 BIOS 配置,因此用户无需关心其 DMA 通道。
这仅适用于 LPC 总线和旧的 ISA 总线。当设备想要进行 DMA 时,它会使用专用的 DMA 请求线发出 DMA 请求,这很像中断请求。DMA 实际上可以通过使用中断来处理,但这会引入一些延迟,因此通过使用一种称为 DMA 请求的特殊类型的中断来处理更快。与中断类似,DMA 请求也编号,以便识别哪个设备正在发出请求。此号码称为 DMA 通道。由于 DMA 传输都使用主总线(并且一次只能运行一个),因此它们实际上都使用相同的通道进行数据流,但“DMA 通道”号用于识别谁在使用“通道”。主板上存在硬件寄存器,用于存储每个“通道”的当前状态。因此,为了发出 DMA 请求,设备必须知道其 DMA 通道号,该号码必须存储在物理设备上的特殊寄存器中。
因此,设备驱动程序必须以某种方式“附加”到它们控制的硬件。这是通过将总线资源(I/O、内存、IRQ、DMA)分配给物理设备,并让设备驱动程序了解它来完成的。例如,串行端口仅使用 2 个资源:IRQ 和 I/O 地址。这两个值都必须提供给设备驱动程序和物理设备。驱动程序(及其设备)也在 /dev 目录中给出一个名称(例如 ttyS1)。地址和 IRQ 号码由物理设备存储在其卡上的配置寄存器中(或主板上的芯片中)。旧硬件(在 1990 年代中期)使用开关(或跳线)来物理设置硬件中的 IRQ 和地址。此设置保持固定,直到有人取下计算机盖并移动跳线。
但是对于 PnP(无跳线)的情况,配置寄存器数据通常在 PC 断电(关闭)时丢失,因此每次 PC 开机时都必须为每个设备重新提供总线资源数据。
PC 的架构仅提供有限数量的资源:IRQ、DMA 通道、I/O 地址和内存区域。如果只有有限数量的设备,并且它们都使用标准化的总线资源值(例如唯一的 I/O 地址和 IRQ 号码),那么将设备驱动程序附加到设备就不会有问题。每个设备都将具有固定的资源,这些资源不会与计算机上的任何其他设备冲突。没有两个设备会具有相同的地址,ISA 总线上也不会有 IRQ 冲突等。每个驱动程序都将使用唯一的地址、IRQ 等硬编码到程序中。生活将变得简单。
防止地址冲突的另一种方法是将每个卡的插槽号作为地址的一部分包含在内。因此,两个不同的卡之间不会发生地址冲突(因为它们位于不同的插槽中)。卡设计不允许卡的不同功能之间存在地址冲突。事实证明,配置地址空间(用于资源查询和分配)实际上确实如此。但这不适用于 I/O 地址或内存区域。像 PCI 总线上那样共享 IRQ 也可以避免冲突,但可能会导致其他问题。
但是 PC 架构存在冲突问题。设备数量的增加(包括相同类型的多个设备)往往会增加潜在的冲突。与此同时,PCI 总线的引入,其中两个或多个设备可以共享同一个中断,以及更多中断的引入,往往会减少冲突。由于转向 PCI,总体结果是冲突减少了,因为最稀缺的资源是 IRQ。然而,即使在 PCI 总线上,避免 IRQ 共享也更有效。在某些中断快速连续发生且必须快速处理的情况下(例如音频),共享可能会导致性能下降。因此,将所有 PCI 设备分配到同一个 IRQ 并不好,分配需要平衡。然而,有些人发现他们所有的 PCI 设备都在同一个 IRQ 上。
因此,设备需要具有一定的灵活性,以便可以将它们设置为避免任何冲突并实现平衡所需的任何地址、IRQ 等。但是,某些 IRQ 和地址非常标准,例如时钟和键盘的地址和 IRQ。这些不需要这种灵活性。
除了总线资源分配冲突的问题外,还存在告诉设备驱动程序总线资源是什么时出错的问题。对于旧式手动配置的情况,用户将使用的资源键入存储在硬盘驱动器上的配置文件中,这种情况更有可能发生。当资源通过卡上的跳线设置时,这通常可以正常工作(前提是用户知道它们是如何设置的,并且在将此数据键入配置文件时没有出错)。但是,由于资源由 PnP 软件设置,因此它们可能并非始终设置相同,这可能意味着对于用户键入由 PnP 设置的总线资源值的任何手动配置都会出现问题。
如果正确完成总线资源的分配,则可以在物理硬件及其设备驱动程序之间建立非冲突的通信通道。例如,如果将某个 I/O 地址范围(资源)分配给设备驱动程序和一块硬件,那么这就在它们之间建立了一个单向通信通道。驱动程序可以将命令和其他信息发送到设备。实际上,这不仅仅是单向通信,因为驱动程序可以通过读取其寄存器从设备获取信息。但是设备无法以这种方式发起任何通信。要发起通信,设备需要一个 IRQ,以便它可以向其驱动程序发送中断。这创建了一个双向通信通道,驱动程序和物理设备都可以发起通信。
术语即插即用 (PnP) 有多种含义。从广义上讲,它只是自动配置,即只需插入设备,它就会自行配置。在本 HOWTO 中使用的意义上,PnP 是指配置 PnP 总线资源(在物理设备中设置它们)并让设备驱动程序了解它。对于 Linux 的情况,通常只是驱动程序确定 BIOS 如何设置总线资源,并在必要时,驱动程序发出命令来更改(重置)总线资源。“PnP”通常仅指 ISA 总线上的 PnP,因此来自 isapnp 的消息:“未找到即插即用设备”仅表示未找到 ISA PnP 设备。标准 PCI 规范(在“PnP”一词出现之前发明)为 PCI 总线提供了与 PnP 等效的功能。
PnP 将设备与其设备驱动程序匹配,并通过分配总线资源来指定其通信通道。它使用标准化协议与物理设备内部的配置寄存器进行电子通信。在即插即用之前的 ISA 总线上,总线资源以前是通过跳线或开关在硬件设备中设置的。有时,总线资源可以通过驱动程序以电子方式设置到硬件中(通常仅为 MS OS 编写,但在极少数情况下由 Linux 驱动程序支持)。这有点像 PnP,但没有使用标准化的协议,因此它不是真正的 PnP。某些卡具有可以通过此类软件覆盖的跳线设置。对于 PnP 之前的 Linux,大多数软件驱动程序通过配置文件(或类似文件)或通过探测设备预期所在的地址来分配总线资源。但是,这些方法今天仍在使用,以允许 Linux 使用旧的非 PnP 硬件。有时,这些旧方法今天仍然在 PnP 硬件上使用(例如,在 BIOS 通过 PnP 方法为硬件分配资源之后)。
PCI 总线从一开始就类似于 PnP,但通常不称为 PnP 或“即插即用”,因此 PnP 通常意味着 ISA 总线上的 PnP。但是,本文档中的 PnP 通常意味着 ISA 或 PCI 总线上的 PnP。
以下是 PnP 在理论上应该如何工作的。假设的 PnP 配置程序查找所有 PnP 设备,并询问每个设备需要哪些总线资源。然后,它检查它有哪些总线资源(IRQ 等)可以分配。当然,如果它保留了非 PnP(传统)设备使用的总线资源(如果它知道它们),它就不会分配这些资源。然后,它使用一些标准(PnP 规范未指定)来分配总线资源,以便没有冲突,并且所有设备都能获得它们需要的资源(如果可能)。然后,它间接告诉每个物理设备分配给它的总线资源,并且设备自行设置为仅使用分配的总线资源。然后,设备驱动程序以某种方式找出其设备使用的总线资源,从而能够有效地与其控制的设备进行通信。
例如,假设一张卡需要一个中断(IRQ 号码)和 1 MB 的共享内存。PnP 程序从卡上的配置寄存器读取此请求。然后,它为该卡分配 IRQ5 和 1 MB 的内存地址空间,起始地址为 0xe9000000。PnP 程序还从卡中读取识别信息,告知设备类型、ID 号码等。然后,它直接或间接地告诉相应的设备驱动程序它所做的事情。如果是驱动程序本身在执行 PnP,那么就不需要为设备查找驱动程序(因为它的驱动程序已经在运行)。否则,需要找到合适的设备驱动程序,并迟早告知其设备的配置方式。
这并不总是那么简单,因为卡(或 PCI 的路由表)可能会指定它只能使用某些 IRQ 号码,或者 1 MB 的内存必须位于某个地址范围内。PCI 总线和 ISA 总线的细节有所不同,ISA 总线上的复杂性更高。
一种常用的资源分配方式是从一个设备开始,为其分配总线资源。然后对下一个设备执行相同的操作,依此类推。然后,如果最终所有设备都获得分配的资源而没有冲突,那么一切都正常。但是,如果分配所需的资源会造成冲突,则有必要返回并尝试对之前的分配进行一些更改,以便获得所需的总线资源。这称为重新平衡。Linux 不进行重新平衡,但 MS Windows 在某些情况下会进行重新平衡。对于 Linux,所有这些都由 BIOS 和/或内核和/或设备驱动程序完成。在 Linux 中,设备驱动程序直到驱动程序启动后才获得其最终的资源分配,因此避免冲突的一种方法是不启动任何可能引起冲突的设备。但是,BIOS 通常会在 Linux 甚至启动之前就将资源分配给物理设备,并且内核会在启动时检查 PCI 设备是否存在地址冲突。
PnP 软件可能会使用一些快捷方式。一种是跟踪它上次配置时(当计算机上次使用时)如何分配总线资源,并重用它。BIOS 和 MS Windows 都会这样做,但标准 Linux 不会。但在某种程度上,它确实会这样做,因为它经常使用 BIOS 所做的事情。Windows 将此信息存储在其硬盘上的“注册表”中,而 PnP/PCI BIOS 将其存储在 PC 中的非易失性存储器中(称为 ESCD;请参阅 BIOS 的 ESCD 数据库)。有些人说没有注册表(如 Linux)更好,因为使用 Windows,注册表可能会损坏并且难以编辑。但 Linux 中的 PnP 也存在问题。
虽然 MS Windows(Windows 3.x 和 NT4 除外)是 PnP,但 Linux 最初不是 PnP 操作系统,而是逐渐成为 PnP 操作系统。PnP 最初适用于 Linux,因为 PnP BIOS 会配置总线资源,并且设备驱动程序会找出(使用 Linux 内核提供的程序)BIOS 所做的事情。如今,大多数驱动程序都可以发出命令来执行自己的总线资源配置,而无需始终依赖 BIOS。不幸的是,驱动程序可能会抢占另一个设备稍后需要的总线资源。某些设备驱动程序可能会将它们上次使用的配置存储在配置文件中,并在下次计算机开机时使用它。
如果设备硬件记住了其之前的配置,那么在下次启动时就不会有任何硬件需要进行 PnP 配置。但是,硬件似乎在断电时忘记了其配置。某些设备包含默认配置(但不一定是上次使用的配置)。因此,PnP 设备需要在每次 PC 开机时重新配置。此外,如果添加了新设备,则也需要对其进行配置。为这个新设备分配总线资源可能涉及从现有设备中移除一些总线资源,并为现有设备分配它可以使用的替代总线资源。目前,Linux 无法进行如此复杂的分配(MS Windows XP 也可能无法做到)。
当 PC 首次开机时,BIOS 芯片会运行其程序以启动计算机(第一步是检查主板硬件)。如果操作系统存储在硬盘驱动器上(通常情况下是这样),那么 BIOS 必须知道硬盘驱动器。如果硬盘驱动器是 PnP,那么 BIOS 可能会使用 PnP 方法来查找它。此外,为了允许用户手动配置 BIOS 的 CMOS 并在计算机启动时响应错误消息,还需要屏幕(显卡)和键盘。因此,BIOS 必须始终 PnP 配置加载操作系统所需的设备,从硬盘驱动器。
一旦 BIOS 识别出硬盘驱动器、显卡和键盘,它就可以开始启动(从硬盘加载操作系统到内存中)。如果您已告知 BIOS 您拥有 PnP 操作系统 (PnP OS),它应该像上面那样开始启动 PC,并让操作系统完成 PnP 配置。否则,PnP-BIOS 将(在启动之前)可能尝试完成设备的其余 PnP 配置(但不告知设备驱动程序它所做的事情)。但是驱动程序仍然可以通过利用 Linux 内核中可用的功能来找到这一点。
要查看 PCI 总线上有什么,请键入 lspci
或 lspci -vv
。或者键入 scanpci -v
以获得相同的信息,格式为数字代码,其中设备按数字显示(例如:“device 0x122d”而不是按名称等。在极少数情况下,scanpci
会找到 lspci
找不到的设备。
显示器上的启动时消息显示了在各种总线上找到的设备(使用 Shift-PageUp 向后翻阅它们)。请参阅 启动时消息
ISA 是旧 IBM 兼容 PC 的旧总线,而 PCI 是英特尔更新、更快的总线。PCI 总线专为今天所谓的 PnP 而设计。与 ISA 总线相比,这使得更容易找出 PnP 总线资源如何分配给硬件设备。
对于 ISA 总线,实现 PnP 存在一个真正的问题,因为在设计 ISA 总线时没有人考虑到 PnP,并且几乎没有 I/O 地址可供 PnP 用于向物理设备发送配置信息。因此,将 PnP 强行塞进 ISA 总线的方式非常复杂。已经写了整本书来介绍它。请参阅 PnP 书籍。除其他外,它要求 PnP 程序为每个 PnP 设备分配一个临时的“句柄”,以便可以寻址它以进行 PnP 配置。分配这些“句柄”称为“隔离”。有关复杂细节,请参阅 ISA 隔离。
随着 ISA 总线的消亡,PnP 将变得更容易一些。届时,不仅更容易找出 BIOS 如何配置硬件,而且冲突也会减少,因为 PCI 可以共享中断。仍然需要将设备驱动程序与设备匹配,还需要配置在 PC 启动并运行时添加的设备。某些设备不受 Linux 支持的严重问题仍然存在。
Linux 过去在处理 PnP 方面存在严重问题,但大多数问题现在已得到解决(截至 2004 年中期)。Linux 最初是从非 PnP 系统发展而来的,如果编译内核时选择某些选项,则可以成为 PnP 系统。BIOS 可能会分配 IRQ,但 Linux 也可能会分配其中一些 IRQ,甚至重新分配 BIOS 所做的操作。ACPI(高级配置和电源接口)的配置部分旨在使操作系统可以轻松地进行自己的配置。如果编译内核时选择了 ACPI,Linux 可以使用 ACPI。
在 Linux 中,传统上每个设备驱动程序都进行自己的低级配置。这很困难,直到 Linux 在内核中提供了软件,驱动程序可以使用该软件来使其更容易。如今(2005 年),它已经达到了驱动程序只需调用内核函数:pci_enable_device(),设备就会通过启用并分配 irq(如果需要)和地址来配置设备的程度。此分配可能是 BIOS 先前分配的,也可能是内核在内核检测到 pci 或 isapnp 设备时先前为其保留的。甚至有一个 ACPI 选项供 Linux 在启动时为所有设备分配 IRQ。
因此,今天,从某种意义上说,驱动程序仍在进行配置,但他们可以通过告诉 Linux 来完成配置(而 Linux 可能不需要做太多,因为它有时能够使用 BIOS 或 Linux 已经设置的内容)。因此,真正进行大部分配置的是 Linux 内核的非设备驱动程序部分。因此,至少对于常见的计算机架构,将 Linux 称为 PnP 操作系统可能是正确的。
然后,当设备驱动程序找到其设备时,它会询问已分配的地址和 IRQ(由 BIOS 和/或 Linux)并通常只是接受它们。但是,如果驱动程序想要这样做,它可以尝试使用内核提供的函数来更改地址。但是,内核不会接受与其他设备冲突或硬件无法支持的地址。当 PC 启动时,您可能会注意到屏幕上显示的消息,表明某些 Linux 设备驱动程序已找到其硬件设备以及 IRQ 和地址范围。
因此,内核为驱动程序提供了函数(程序代码),驱动程序可以使用这些函数来查找其设备是否存在、配置方式以及在需要时修改配置的函数。内核 2.2 只能对 PCI 总线执行此操作,但内核 2.4 具有 ISA 和 PCI 总线的此功能(前提是在编译内核时选择了适当的 PNP 和 PCI 选项)。内核 2.6 推出了对 ACPI 的更好利用。这绝不保证所有驱动程序都会完全正确地使用这些功能。并且 BIOS 不知道的旧设备可能要等到您(或某些配置实用程序)将其地址、irq 等放入配置文件后才能配置。
此外,内核通过不允许它知道的两个设备同时使用相同的总线资源来帮助避免资源冲突。最初这仅适用于 IRQ 和 DMA,但现在也适用于地址资源。
如果您有旧的 ISA 总线,则程序 isapnp 应在启动时运行,以查找和配置 ISA 总线上的 pnp 设备。查看带有“dmesg”的消息。
要查看内核可能为设备驱动程序提供的帮助,请参阅目录 /usr/.../.../Documentation,其中一个 ... 包含单词“kernel-doc”或类似词语。警告:此处的文档往往已过时,因此要获取最新信息,您需要阅读内核开发人员发送的邮件列表上的消息,以及他们编写的计算机代码,包括注释。在此内核文档目录中,请参阅 pci.txt(“如何编写 Linux PCI 驱动程序”)和文件:/usr/include/linux/pci.h。除非您是驱动程序专家并且了解 C 编程,否则这些文件编写得非常简洁,实际上无法让您编写驱动程序。但这会让您了解驱动程序可以使用哪些 PnP 类型的功能。
对于内核 2.4,请参阅 isapnp.txt。对于内核 2.6,isapnp.txt 被 pnp.txt 取代,pnp.txt 与 isapnp.txt 完全不同,并且还处理 PCI 总线。另请参阅 O'Reilly 书籍:Linux 设备驱动程序,第 3 版,2005 年。完整文本在互联网上。
但是,真正的 PnP 操作系统可以更好地处理许多事情
由于每个驱动程序都为自己着想,因此驱动程序可能会抢占其他设备需要的总线资源(但内核尚未分配给它们)。因此,更复杂的 PnP Linux 内核会更好,其中内核在收到所有请求后进行分配。另一种选择是尝试重新分配已分配的资源,如果设备无法获得其请求的资源。
“总线资源短缺”问题变得越来越不严重,原因有两个:一个原因是 PCI 总线正在取代 ISA 总线。在 PCI 下,IRQ 不会短缺,因为 IRQ 可以共享(即使共享效率稍低)。此外,PCI 不使用 DMA 资源(尽管它执行与 DMA 等效的操作,而无需此类资源)。
第二个原因是设备 I/O 可用的地址空间更多。虽然 ISA 总线的传统 I/O 地址空间限制为 64KB,但 PCI 总线有 4GB 的地址空间。由于越来越多的物理设备使用主内存地址而不是 IO 地址空间,因此即使在 ISA 总线上,也仍然有更多可用空间。在 32 位 PC 上,有 4GB 的主内存地址空间,并且此总线资源的很大一部分可用于设备 IO(除非您安装了 4GB 的主内存)。
至少在早期,有人尝试使 Linux 成为真正的 PnP 操作系统。请参阅 http://www.astarte.free-online.co.uk。虽然在 1998 年左右开发,但它从未放入内核(但可能应该放入)。
当计算机首次开机时,BIOS 程序在操作系统加载之前运行。现代 BIOS 是 PnP,可以配置大多数 PnP 设备。一些旧的 PCI BIOS 将仅配置 PCI 总线。以下是您的 BIOS CMOS 菜单中可能存在的一些选项
无论您如何回答 BIOS 的这个问题,PnP BIOS 都会 PnP 配置硬盘驱动器、软盘、显卡和键盘,以使系统可启动,并配置 LPC 总线(如果您有)。如果您说不是 PnP OS,那么 BIOS 应该配置所有内容。
您应该如何回答 BIOS 的这个问题?如果您至少有 2.4 内核,您可以以任何一种方式回答,Linux 通常都能正常工作。即使您在同一台 PC 上安装了 Windows 2000 或 XP,通常也可以正常工作。这是因为 Windows 和 Linux 据说都是 PnP OS,如果 OS 是 PnP,它也应该能够处理 BIOS 已配置所有内容的情况(如果您说它不是 PnP)。但我仍然建议说它不是 PnP OS,除非有已知的理由说明否则。
目前尚不清楚是应该说是还是否。如果 Linux 使用了 isapnp,那么 Linux 会进行配置,并且声称最好说是 PnP OS。当呈现已经由 BIOS 配置的设备时,isapnp 会遇到麻烦的原因尚不清楚,但是这种麻烦有时会发生,并且通过阻止 BIOS 进行配置(说是,它是 PnP OS)来解决。在少数情况下,说否解决了问题。因此,如果 isapnp 工作正常,您可能应该说是 PnP。如果未使用 isapnp,则通常最好选择否。用于 PCI 设备的 Linux 设备驱动程序应正确配置 PCI 设备。但是对于由非 PCI 驱动程序驱动的 PCI 设备,您可以说它不是 PnP,以使 BIOS 配置它们。
如果您还在同一台 PC 上运行这些 Windows OS,您应该说您没有 PnP OS。这就是 MS 建议您做的。也许 MS 希望 BIOS 在配置方面比 Windows 做得更好。这是有道理的,因为 BIOS 应该针对主板的特殊性而设计,尤其是在当今许多设备都内置在主板中的情况下。PnP OS = 否对于 Linux 内核 2.4 及更高版本也应该没问题。但是对于 2.4 之前的 Linux 内核,尚不清楚哪个是最好的。(请参阅上面的小节)。因此,如果您遇到 Linux 问题,您可以尝试说您拥有 PnP OS 以满足 Linux,但这与 MS 的建议相反(但无论如何可能会正常工作)。
当 BIOS 配置的设备与 Windows 注册表中的设备不同时,Windows 会告诉您它正在查找新硬件。它真正做的是查找已配置不同的旧硬件,因此它认为它是新硬件。无论如何,它都会将其注册表中使用的 BIOS 配置记录下来,并且该设备从现在开始应该可以正常工作。
对于 Windows 9x,MS 建议您告诉 BIOS 您拥有 PnP OS(与 Windows 2000 和 XP 的情况完全相反)。如果您有内核 2.4 或更高版本,这也应该适用于 Linux。但是,如果您使用的 Linux 内核早于 2.4,那么 Linux 最好说它不是 PnP OS。解决此困境的一种方法是为您更频繁使用的操作系统设置它。然后在您启动另一个操作系统时,手动进入 BIOS 并更改设置。这很麻烦,但如果您几乎从不使用其中一个操作系统,那是可行的。否则,还有更好的方法来解决这个难题。
解决此困境的第二种方法是让 Linux 资源配置所有内容。请参阅 2.4 内核之前的 Linux。然后您告诉 BIOS 它是 PnP OS。
解决此困境的第三种方法是告诉 BIOS 它不是 PnP OS。这与 MS 告诉您应该做的事情相反,但是如果您了解该怎么做(以及为什么),则有可能使 MS Windows 9x 正常工作。如果您告诉 BIOS 它不是 PnP OS,那么 MS Windows 不应该检测到 BIOS 如何配置事物并在不喜欢 BIOS 所做的事情时更改它吗?它应该这样做,但不幸的是,它似乎没有以这种方式工作。
Windows 9x 在发现 BIOS 已经配置的硬件时似乎会做什么就是将其搁置一旁,而不重新配置它。现在 Windows 9x 将总线资源配置记录保存在其注册表中。如果 BIOS 配置不同,它应该更正其注册表中的内容以符合 BIOS 设置的内容,或者根据注册表中的内容重新配置所有内容。坏消息。它似乎既不这样做,也不认为实际配置与注册表中的配置相同,而实际上是不同的。
但是,如果注册表恰好包含与 BIOS 配置事物方式完全相同的总线资源配置,那么一切显然都能正常工作。因此,如果 BIOS 以与注册表中记录的方式相同的方式配置设备,则设备将可以正常工作。因此,使 MS Windows 正常工作的方法是使注册表与 BIOS 的配置方式同步。如前所述,BIOS 根据其 ESCD(类似于 BIOS 的注册表)配置事物。请参阅 BIOS 的 ESCD 数据库。因此,我们需要使注册表与 BIOS 的 ESCD 同步,以便注册表和 ESCD 包含相同的配置。在某些情况下,这两者恰好是同步的,您无需执行任何操作。
您可能会想到的一个问题是:BIOS 的 ESCD 和 Windows 注册表最初是如何不同步的?这是一个场景。您在 BIOS 设置为 PnP OS 的情况下安装 Windows。然后 Windows 配置大部分内容并将该配置保存在其注册表中。然后在稍后,您将 BIOS 设置更改为非 PnP OS。然后在启动时,BIOS 配置所有内容,但它并没有完全像 Windows 那样配置。因此,硬件的实际配置和 Windows 在其注册表中拥有的配置现在不同了。
尝试使注册表和 ESCD 相同的一种方法是在 BIOS 设置为“非 PnP OS”的情况下安装(或重新安装)Windows。这应该向 Windows 提供由 BIOS 配置的硬件。如果此配置没有冲突,Windows 希望会将其搁置一旁并将其保存在其注册表中。然后 ESCD 和注册表就同步了。
另一种方法是在Windows设备管理器中点击“删除”来移除导致问题的设备。然后使用“非PnP操作系统”(在启动时在BIOS的CMOS中设置)重启。Windows将会重新安装这些设备,希望能使用BIOS配置的总线资源设置。请注意,Windows可能会要求您插入Windows安装光盘,因为它有时找不到驱动程序文件(以及类似的文件),即使它们仍然存在。一个解决方法是选择“跳过文件”,这将避免从光盘安装文件。如果文件仍然在硬盘上,那么驱动程序应该可以找到它,即使Windows安装程序要求您从光盘安装(但您跳过了这一步)。
作为一个测试,我“移除”了一张使用Novell兼容驱动程序的网卡。重启后,Windows将其重新安装为Microsoft Networking而不是Novell。这意味着需要重新安装Novell客户端——很多不必要的工作。因此,在这种情况下,最好不要欺骗Windows95/98,而是让Linux来配置总线资源。
当使用Windows-Linux双启动电脑时,您可能会注意到BIOS配置方式的变化,这是因为Windows9x(以及其他版本的Windows ??)修改了ESCD。据推测,只有当您“强制”配置或安装旧式设备时才会发生这种情况。请参阅使用Windows设置ESCD。执行配置的设备驱动程序可能会修改BIOS所做的事情,如果您运行 isapnp 或 PCI Utilities 程序,它们也会进行修改。
现代BIOS允许您手动分配资源,主要是IRQ。通常有一个选项可以将分配设置为“自动”,以便BIOS决定如何分配资源。“自动”通常是一个不错的选择,除非您有旧的旧式非PnP ISA卡。
如果您有这样的非PnP卡,那么在BIOS中为它们保留资源(例如IRQ)可能很重要。否则,BIOS可能会将这些资源用于其他设备并产生冲突。一个例外是一些常见的旧式设备(例如并行端口和串行端口、磁盘驱动器),BIOS可能会找到它们(在启动时查看屏幕),因此您无需为它们保留资源。如果您在PC上使用过Windows,那么Windows可能已经通过在Windows下运行ICU实用程序(或类似程序)告知了BIOS关于它们的信息。
对于PCI,BIOS可能允许您将IRQ分配给卡槽1、2、3、4等。如果您这样做,您应该知道哪个卡在哪个插槽中。实际上,每个插槽都有4个PCI IRQ:A、B、C和D。如果BIOS菜单没有说明这些(A、B、C、D)中的哪个被分配给一个IRQ号,那么很可能它只将IRQ号分配给PCI IRQ A。但是许多PCI卡只使用IRQ A,因此这就像将一个IRQ分配给一个插槽。请参阅PCI中断
这样做有点冒险。它将擦除BIOS的ESCD数据库,其中包含有关如何配置PnP设备的信息,以及有关如何配置旧式(非PnP)设备的列表。除非您确信该数据库是错误的并且需要重建,否则永远不要这样做。某处提到只有在您无法启动计算机时才应这样做。如果BIOS丢失了有关旧式ISA设备的数据,那么您需要再次在DOS/Windows下运行ICA来重新建立此数据。
今天,几乎所有新的内部板卡(卡)都是即插即用(PnP)的。因此,在几乎所有情况下,总线资源的配置都应该是完全自动的。如果设备无法工作,请查看是否已检测到它,可能需要重启。如果设备驱动程序无法配置资源,那么希望方法2-6中的一个或多个可以解决问题。
以上任何一种方法都将在硬件中设置总线资源,但只有第一种(可能还有第二种)告诉驱动程序已完成的操作。驱动程序如何被告知取决于驱动程序。您可能需要做一些事情来通知它。请参阅告知驱动程序配置
设备驱动程序(在内核提供的代码的帮助下)可以编写为使用PnP方法在硬件中设置总线资源,但这仅限于它们控制的设备。但是,许多设备驱动程序只是接受BIOS或Linux已配置的内容,并使用内核提供的代码来了解此设备是如何配置的。由于驱动程序已检查配置并可能重新配置了它,因此它显然知道配置,您无需告诉它此信息。这显然是最简单的方法,因为如果驱动程序完成所有操作,您无需执行任何操作。
如果您有旧的pre-PnP ISA硬件,Linux PnP软件可能不知道它及其所需的总线资源。因此,它可能会错误地将此旧硬件所需的资源分配给其他设备。结果是资源冲突,但有一种方法可以尝试避免它。您可以通过在启动时(通常)、isa-pnp 模块或内核(如果 PnP 已构建到内核中)配置 BIOS 来保留旧 ISA 卡所需的资源。例如,要保留 IRQ 5,请将此参数提供给 isa-pnp 模块(或内核):isapnp_reserve_irq=5。请参阅 BootPrompt-HOWTO。除了 ..._irq 之外,还有 _io、_dma 和 _mem。
对于 PCI 设备,大多数驱动程序将配置 PnP。不幸的是,驱动程序可能会抢占其他设备需要的总线资源(但内核尚未将其分配给它们)。因此,更复杂的 PnP Linux 内核会更好,在这种内核中,内核在所有请求都完成后进行分配。请参阅 Linux 如何执行 PnP。
从内核 2.6 开始,据说有一种新方法供用户使用 /sys 目录树进行资源配置。但截至 2004 年 8 月,在大多数情况下它不能用于配置。请参阅 /sys 目录树。
如果您有 PnP BIOS,它可以配置硬件。如果驱动程序无法做到这一点,BIOS 可能可以。这意味着您的 BIOS 读取所有设备的资源需求并配置它们(将总线资源分配给它们)。它是 PnP 操作系统的替代品,只是 BIOS 不会将驱动程序与其设备匹配,也不会告诉驱动程序它是如何进行配置的。它通常应使用存储在其非易失性存储器 (ESCD) 中的配置。如果它找到新设备或存在冲突,BIOS 应更改配置,并且可能不使用与 ESCD 中相同的配置。在这种情况下,它应该更新 ESCD 以反映新的情况。
您的 BIOS 需要支持这种配置,并且在某些情况下它没有正确或完全地执行此操作。可能需要在 CMOS 菜单中告知 BIOS 它不是 PnP 操作系统。虽然许多设备驱动程序将能够自动检测 BIOS 所做的事情,但在某些情况下您可能需要确定它(并非总是容易)。请参阅 我的当前配置是什么? 让 BIOS 执行此操作的一个可能优点是它在 Linux 启动之前完成其工作,因此所有操作都在启动过程的早期完成。
大约 1996 年之后制造的大多数 BIOS ?? 都可以资源配置 PCI 和 ISA 总线。但有人声称,一些较旧的 BIOS 只能配置 PCI。当然,对于只有 PCI 总线的 PC,BIOS 只需要配置 PCI。要尝试了解更多关于您的 BIOS 的信息,请在 Web 上查找。请不要问我,因为我没有关于这方面的数据。您想了解的 BIOS 的详细信息可能很难找到(或不可用)。一些旧的 BIOS 可能具有最小的 PnP 功能,并且似乎期望操作系统正确地执行此操作。如果发生这种情况,您要么必须找到另一种方法,要么尝试设置 ESCD 数据库(如果 BIOS 有一个)。请参阅下一节。
BIOS 维护一个非易失性数据库,其中包含它将尝试使用的 PnP 配置(如果您声明它不是 PnP 操作系统)。它被称为 ESCD(扩展系统配置数据)。再次,ESCD 的提供是可选的,但大多数 PnP-BIOS 都有它。ESCD 不仅存储 PnP 设备的资源配置,还存储非 PnP 设备的配置信息(并将它们标记为这样)以避免冲突。ESCD 数据通常保存在芯片上,并在断电时保持完整,但有时它会保存在硬盘驱动器上??
ESCD 旨在保存最后使用的配置。但是,由于 Linux 可以更改设备的配置方式(包括用户使用 isapnp 或 pci utilities),因此 ESCD 将不知道这一点,也不会将此配置保存在 ESCD 中。一个好的 PnP 操作系统可能会更新 ESCD,以便您以后可以在非 PnP 操作系统(如标准 Linux)中使用它。MS Windows9x 仅在特殊情况下执行此操作。请参阅 使用 Windows 设置 ESCD。从内核 2.6 开始,Linux 能够修改 ESCD,但尚未被使用(截至 2004 年 8 月)。
要使用 ESCD 中设置的内容,请确保您已在 BIOS 的 CMOS 中设置“非 PnP 操作系统”或类似内容。然后每次 BIOS 启动时(在加载 Linux 操作系统之前),它都应以这种方式配置。如果 BIOS 检测到 ESCD 中不存在的新 PnP 卡,则它必须为该卡分配总线资源并更新 ESCD。它甚至可能必须更改分配给现有 PnP 卡的总线资源并相应地修改 ESCD。
有一个程序,您可以使用它来查看 ESCD 的内容。它显示 IRQ 和 IO 地址等,但缺少设备名称(只有 EISA 设备 ID 号)。它位于:Index of /home/gunther.mayer/lsescd
如果每个设备将其上次配置保存在其硬件中,则每次启动 PC 时都不需要硬件配置。但它不是这样工作的。因此,如果您使用 BIOS 进行 PnP,则需要保持所有 ESCD 数据的正确性。有些 BIOS 没有 ESCD,但确实有一些非易失性存储器来存储有关哪些总线资源已保留供非 PnP 卡使用的信息。许多 BIOS 两者都有。
最终 Linux 内核可能会设置 ESCD。从内核 2.6 开始,新代码中的一个函数可以做到这一点,前提是内核已使用 PNPBIOS 编译。但它目前在代码中未使用。
如果 BIOS 没有以您想要的方式(或它应该的方式)设置 ESCD,那么有一个 Linux 实用程序来设置 ESCD 会很好。人们可能会求助于尝试使用 Windows 来执行此操作(如果您在同一台 PC 上安装了 Windows)。
有三种方法可以使用 Windows 来尝试设置/修改 ESCD。一种方法是使用为 DOS 或 Windows 3.x 设计的 ICU 实用程序。它也应该适用于 Windows 9x/2k ?? 另一种方法是在 Windows 9x/2k 下手动(“强制”)设置设备,以便 Windows 在正常关闭 Windows 时将此信息放入 ESCD 中。第三种方法仅适用于非即插即用的旧式设备。如果 Windows 知道它们以及它们使用的总线资源,那么 Windows 应该将此信息放入 ESCD 中。
如果 PnP 设备由 Windows 自动配置,而用户没有“强制”它更改设置,那么这些设置可能不会进入 ESCD。当然,Windows 很可能自行决定配置与 ESCD 中设置的相同,因此它们最终可能会巧合地相同。
Windows 9x 是 PnP 操作系统,并自动 PnP 配置设备。它们在注册表深处维护自己的 PnP 数据库(存储在二进制 Windows 文件中)。注册表中还有许多其他配置内容,除了 PnP 总线资源。内存中有一个当前的 PnP 资源配置,硬盘上还存储了另一个(可能大致相同的)。要在 Windows98 中查看此内容或强制更改它,您可以使用设备管理器。
在 Windows98 中,有 2 种方法可以进入设备管理器:1. 我的电脑 --> 控制面板 --> 系统属性 --> 设备管理器。2. (右键单击)我的电脑 --> 属性 --> 设备管理器。然后在设备管理器中,您选择一个设备(如果同一类设备有多个,有时需要多步操作)。然后单击“属性”,然后单击“资源”。要尝试手动更改资源配置,请取消选中“使用自动设置”,然后单击“更改设置”。现在尝试更改设置,但它可能不允许您更改它。如果它允许您更改,则您已“强制”更改。消息应告知您正在强制执行。如果您想保留 Windows 显示的现有设置,但使其“强制”,那么您必须强制更改为其他设置,然后再强制将其更改回原始设置。
要查看在 Windows98 下“强制”了什么,请查看“强制硬件”列表:开始 --> 程序 --> 附件 --> 系统工具 --> 系统信息 --> 硬件资源 --> 强制硬件。当您在 Windows 中“强制”更改总线资源时,它应该将您的更改放入 ESCD 中(前提是您正常退出 Windows)。从“系统信息”窗口,您还可以检查 IRQ 和 IO 端口在 Windows 下是如何分配的。
即使 Windows 显示没有总线资源冲突,Linux 下也可能存在冲突。这是因为 Windows 分配总线资源的方式可能与 ESCD 不同。在极少数情况下,Windows 下的所有设备要么是旧式设备,要么已被“强制”,那么 Windows 和 ESCD 配置应该是相同的。
如果您添加了一个新的 PnP 设备并将 BIOS 设置为“非 PnP 操作系统”,那么 BIOS 应该自动配置它并将配置存储在 ESCD 中。如果是非 PnP 旧式设备(或通过跳线等方式制成的设备),那么以下是一些处理它的选项
您可以直接(通过 CMOS 设置菜单)告诉 BIOS 它使用的某些总线资源(例如 IRQ)是保留的,并且不能由 PnP 分配。这不会将此信息放入 ESCD 中。但是,可能会有一个 BIOS 菜单选项,用于确定在发生冲突时是否让这些 CMOS 选择覆盖 ESCD 中的内容。另一种方法是在 DOS/Windows 下运行 ICU。还有一种方法是在 Windows 9x/2k 下手动安装它,然后确保其配置是“强制的”(请参阅上一节)。如果它是“强制的”,Windows 应该在您关闭 PC 时更新 ESCD。
PCI 设备本质上是 PnP,因此无法禁用。但是,一些 ISA 设备曾经有通过跳线或运行设备附带的 Windows 程序(无跳线配置)禁用 PnP 的选项。如果设备驱动程序无法配置它,这将避免执行 PnP 配置的可能复杂任务。不要忘记告诉 BIOS 这些总线资源是保留的。但是,由于 Linux 对 PnP 的支持已得到改进,因此您通常不希望禁用 PnP。以下是一些支持 PnP 的更多论据
一旦配置为非 PnP 设备,它们就无法通过 PnP 软件或 PnP-BIOS 进行配置(除非您再次移动跳线和/或使用 Dos/Windows 配置软件)。
isapnp
独立程序仅适用于 ISA 总线(非 PCI)上的 PnP 设备。在 2.4 内核之前,它是非常需要的。在 2.4 内核之后,它提供了允许驱动程序处理 ISA PnP 的功能,isapnp 独立程序的重要性降低了。此外,BIOS 可能会令人满意地配置 ISA PnP。但是,isa-pnp 模块(或内置于内核的等效模块)现在非常重要,因为各种 ISA 设备驱动程序调用它来配置总线资源。在内核 2.6 之前,它产生了一个 /proc/isapnp “文件”,该文件可用于手动配置(请参阅内核文档中的 isapnp.txt)。
在某些情况下,Linux 发行版已设置为在启动时自动运行 isapnp。在 2004 年仍然这样做,但如果设备驱动程序工作良好,则实际上不需要它。如果您需要自己设置它,那么 isapnp 的大部分文档都很难理解,除非您了解 PnP 的基础知识。本 HOWTO 应该可以帮助您理解它以及 isapnp 附带的 FAQ。在启动时运行 Linux 程序“isapnp”会将此类设备配置为 /etc/isapnp.conf 中指定的资源值。可以自动创建此配置文件,但您随后应手动编辑它以在各种选项之间进行选择。然后,为了让驱动程序知道资源,您通常需要将它们指定为相应模块(驱动程序)的参数。这是通过配置文件完成的,通常在 /etc 目录中。在那里查找名为 mod* 等的文件。如果驱动程序已构建到内核中,则有时可以将它们作为参数提供给内核。请参阅 BootPrompt-HOWTO。
对于 isapnp,曾经存在一个问题,即内置于内核的设备驱动程序可能在 isapnp 在硬件中设置地址等之前过早运行。这导致设备驱动程序无法找到设备。驱动程序尝试正确的地址,但该地址尚未在硬件中设置。这仍然是一个问题吗??
如果您的 Linux 发行版自动安装了 isapnptools,则 isapnp 可能已经在启动时运行。在这种情况下,您需要做的就是按照“man isapnp.conf
”编辑 /etc/isapnp.conf。请注意,这就像手动配置 PnP,因为您在编辑配置文件时决定如何配置。
如果配置文件错误或不存在,您可以使用程序“pnpdump”来帮助创建配置文件。它几乎为您创建了一个配置文件,但您必须在使用前巧妙地编辑它一下。它包含一些注释以帮助您编辑它。虽然 BIOS 也可能配置 ISA 设备(如果您已告知它您没有 PnP 操作系统),但 isapnp 会重新执行它。
/etc/isapnp.conf 文件中使用的术语起初可能看起来很奇怪。例如,对于 0x3e8 的 IO 地址,您可能会看到“(IO 0 (BASE 0x3e8))”而不是。 “IO 0”表示这是此设备使用的第一个(第 0 个)IO 地址范围。表达所有这些的另一种方法是:“IO[0] = 0x3e8”,但 isapnp 不是以这种方式执行的。“IO 1”表示这是此设备使用的第二个 IO 地址范围,等等。“INT 0”具有类似的含义,但用于 IRQ(中断)。单张卡可能包含多个物理设备,但以上说明仅适用于其中一个设备。
软件包 PCI Utilities (= pciutils,有时称为“pcitools”),允许人们手动 PnP 配置 PCI 总线(有一定难度)。 “lspci”或“scanpci”列出总线资源,而“setpci”在硬件设备中设置资源分配(IRQ 除外)。似乎 setpci 主要用于脚本,并且需要了解 PCI 配置寄存器的详细信息才能使用它。这是一个此处和 setpci 的手册页中均未解释的主题。
人们使用它来配置驱动程序无法配置的 PCI 设备。在我的 Modem-HOWTO 和 Serial-HOWTO 的子节“PCI:启用禁用的端口”中可以找到一个示例。但是,除非您有适用于设备的工作驱动程序,否则启用设备毫无用处。
此方法使用 MS Windows 进行配置,仅在所有其他方法都失败时才应使用。如果您在同一台 PC 上安装了 Windows9x(或 2k),那么只需启动 Windows 并让它配置 PnP。然后使用例如 loadlin.exe 从 Windows(或 DOS)启动 Linux。但是,PCI 设备的 IRQ 可能存在问题。当 Windows 关闭(没有任何消息)为 Linux 让路时,它可能会擦除(归零)存储在其中一个 PCI 设备配置寄存器中的 IRQ。Linux 会抱怨它找到了一个 IRQ 为零。
据报告,如果您使用快捷方式(PIF 文件)启动 Linux,则会发生上述情况。但据报告,有一种解决方法是您仍然使用快捷方式 PIF。快捷方式有点像 Linux 中的符号链接,但它不仅仅如此,因为它可能是“配置的”。要从 DOS 启动 Linux,您可以创建一个批处理文件(脚本)来启动 Linux。(启动 Linux 的程序在名为“loadlin”的软件包中)。然后创建一个指向该批处理文件的 PIF 快捷方式,并进入该快捷方式的“属性”对话框。选择“高级”,然后选中“MS-DOS 模式”以使其在真正的 MS-DOS 中启动。
现在,这是防止 PCI IRQ 归零的技巧。单击“指定新的 MS-DOS 配置”。然后,要么接受呈现给您的默认配置,要么单击“配置”来更改它。现在,当您通过单击快捷方式启动 Linux 时,将根据您的新配置创建新的配置文件(Config.sys 和 Autoexec.bat)。
旧文件存储为“Config.wos 和 Autoexec.wos”。在使用完 Linux 并关闭 PC 后,您将再次需要这些文件,以便下次启动 PC 时可以运行 DOS。您需要确保名称恢复为 *.sys 和 *.bat。当您离开 Windows/DOS 进入 Linux 时,Windows 期望当您使用完 Linux 后会返回 Windows,以便 Windows 可以自动将这些文件恢复为其原始名称。但这不会发生,因为当您退出 Linux 时,您会关闭 PC 而不会返回 Windows。那么您如何重命名这些文件呢?这很容易,只需将命令放入您的“start-Linux”批处理文件中,将这些文件重命名为它们的 *.bat 和 *.sys 名称。将这些重命名命令放在您的批处理文件中,紧挨着加载 Linux 的行之前。
另据报告,您应该单击快捷方式的“属性”对话框的“常规”选项卡,然后选中“只读”。否则,Windows 可能会将“高级设置”重置为“使用当前 MS-DOS 配置”,并且 PCI IRQ 将归零。因此,当您使用当前的 MS-DOS 配置时,Windows 会擦除 IRQ,但当您使用新的配置时不会擦除(新的配置实际上可能会将事物配置为与旧配置相同)。Windows 似乎不是很一致。
设备的现代驱动程序将找出总线资源配置,而无需您告诉它任何信息。它甚至可以使用 PnP 方法在硬件中设置总线资源。一些驱动程序有多种方法来了解其物理设备的配置方式。在最坏的情况下,您必须将总线资源硬编码到内核(或模块)中并重新编译。
中间的情况是,例如您运行一个程序将总线资源信息提供给驱动程序,或将信息放入配置文件中。在某些情况下,驱动程序可能会在它怀疑设备所在的地址探测设备(但如果 PnP 设备尚未通过 PnP 方法启用,则永远找不到它)。然后它可能会尝试测试各种 IRQ 以查看哪个有效。它可能会或可能不会自动执行此操作。
在现代情况下,驱动程序应使用 PnP 方法来查找设备以及 BIOS 等如何设置总线资源,但实际上不会设置它们。它也可能会查看 /proc 目录中的一些“文件”。
可能需要“手动”告诉驱动程序它应该使用哪些总线资源。您将此类总线资源作为参数提供给内核或可加载模块。如果驱动程序已构建到内核中,则通过“启动提示”将参数传递给内核。请参阅 Boot-Prompt-HOWTO,其中描述了一些总线资源和其他参数。一旦您知道要提供给内核的参数,就可以将它们放入引导加载程序配置文件中。例如,将 append="..." 放入 lilo.conf 文件中,然后使用 lilo 命令将此信息放入 lilo 内核加载程序中。
如果驱动程序是以模块方式加载的,在许多情况下,模块会找到所需的总线资源,然后在设备中设置它们。在其他情况下(主要针对较旧的PC),您可能需要将总线资源作为参数传递给模块。模块的参数(包括自动加载的模块)可以在 /etc/modules.conf 中指定。通常有工具用于修改此文件,这些工具取决于发行版。此文件中的注释应该有助于了解如何修改它。此外,您放入 /etc/modules 中的任何模块都将与其参数一起加载。
虽然关于驱动程序如何查找总线资源存在很多不一致性,但最终目标是相同的。如果您在使用驱动程序时遇到问题,您可能需要查看驱动程序文档(查看内核文档树)。以下章节介绍了一些驱动程序的简要示例
对于 PCI 串口(以及 2.4 内核之后的 ISA PnP 串口),串行驱动程序会检测串口类型,并且 PnP 会对其进行配置。不幸的是,可能有一些 PCI 串口尚不受支持。
对于使用非常旧版本的内核和串行驱动程序的标准 ISA 串口(不适用于多端口卡),驱动程序会探测两个标准地址的串口。它不探测 IRQ,但它只是为前两个串口分配“标准”IRQ。这可能是错误的。
对于任何其他情况,必须手动修改 setserial
程序的配置文件。有关更多详细信息,请参阅 Serial-HOWTO。您使用 setserial 来告知驱动程序的 IO 地址。Setserial 通常从启动文件运行。在较新版本中,有一个 /etc/serial.conf 文件(或 /var/lib/setserial/autoconfig),您只需以正常方式使用 setserial 命令“编辑”它,并且您使用 setserial
设置的内容会保存在 serial.conf
配置文件中。当 setserial
命令从启动文件运行时,应查阅 serial.conf
文件。您的发行版可能会或可能不会为您设置此项。
根据您给出的选项,使用 setserial
有两种不同的方式。一种用途是手动告诉驱动程序配置。另一种用途是在给定地址探测并报告那里是否存在串口。它也可以探测此地址并尝试检测此端口使用了哪个 IRQ。
即使使用现代内核,如果驱动程序未能检测到串口,或者如果您有非常旧的硬件,有时也需要 setserial。
一旦您找到您的硬件,找到它的程序通常会告诉您它是如何配置的。因此,找出它是如何配置的通常与查找硬件是相同的过程。
这里“配置”指的是 PnP 总线资源(地址、IRQ 和 DMA)的分配。对于每个设备,配置问题有两个部分
另一个问题是,当您在屏幕上查看配置消息时,您需要知道报告的配置是设备驱动程序的配置、设备硬件的配置还是两者的配置。如果设备驱动程序已经在硬件中设置了配置,或者以其他方式检查了硬件,那么驱动程序应该具有正确的信息。
但是,有时驱动程序被脚本、配置文件、提供给模块的不正确的资源参数提供了不正确的资源,或者可能只是没有被告知资源是什么,并尝试使用不正确的默认资源。例如,可以使用“setserial”告诉串口驱动程序不正确的资源配置,而驱动程序会毫无疑问地接受它。但是串口无法正常工作(如果还能工作的话)。
一个常见的问题是软件无法检测到您的设备和/或确定适合它的驱动程序。对于 PnP 设备,通过 PnP 软件检测它们很容易,除非在硬件被禁用的不寻常情况下。BIOS 有时可以设置为禁用 PnP 设备,或者物理设备本身的跳线/开关可能会禁用它。在这种情况下,在您重新配置 BIOS 或更改跳线/开关之前,根本无法检测到硬件。
由于 PCI 总线本质上是 PnP 的,因此没有隐藏的设备。即使通过 PnP 方法很容易找到 PnP 设备,但如果驱动程序不使用 PnP 方法,而是使用旧的在可能的地址探测它们的方法,则可能找不到它们。这是因为,在 PnP 设备中的资源被设置(由 BIOS 或 Linux)之前,设备可能根本没有地址,因此在可能的地址探测不会产生任何结果。对于旧的 ISA 总线,某些设备可能不是 PnP 的,因此旧的探测方法可能会找到它们。因此,许多驱动程序除了使用 PnP 方法(= PnP 探测,有时也简称为“探测”)之外,仍然在可能的地址进行探测。
查找硬件设备(及其配置)的方法:(请点击链接查看更多详情)
可以通过阅读计算机首次启动时屏幕上显示的来自 BIOS 和 Linux 的消息来获得有关配置的重要信息。这些消息通常闪烁得太快以至于无法阅读,但是一旦它们停止,请多次按 Shift-PageUp 以向后滚动查看它们。要向前滚动浏览它们,请按 Shift-PageDown。在任何时候在 shell 提示符下键入“dmesg”将仅显示 Linux 内核消息,并且可能会错过一些最重要的消息(包括来自 BIOS 的消息)。来自 Linux 的消息有时可能只显示设备驱动程序认为的配置是什么,可能是通过不正确的配置文件告诉它的。检查 /var/log 中的日志文件也可能很有用。
对于 PCI 总线,符号:00:1a:0 表示 PCI 总线 00(主 PCI 总线),PCI 卡(或芯片)1a,以及卡或芯片上的功能 0(第一个设备)。卡(或芯片)08 上的第二个设备将是:00:08:1。
BIOS 消息首先显示,并将显示当时的实际硬件配置,但是 isapnp、pci 实用程序或设备驱动程序可能会在以后更改它。在某些情况下,它不显示 BIOS 未配置的设备。
如果 BIOS 消息在您使用 Shift-PageUp 备份到 BIOS 消息的开头时没有显示,请尝试在它们闪烁时冻结它们,方法是在屏幕上闪烁第一个单词后立即按下“Pause”键。按任意键恢复。在正确的时间准确按下 Pause 键通常很棘手。在按下“Pause”键之前,请务必按住“Shift”键,因为“Pause”是一个 Shift 键。如果您错过了,请在 Linux 开始启动时按 Ctrl-Alt-Del 重启并重试。一旦来自 Linux 的消息开始出现,就为时已晚使用“Pause”键,因为它不会冻结来自 Linux 的消息。
要在 BIOS 中设置诸如为旧硬件保留的 IRQ、串口地址等,您需要在启动时进入 BIOS (CMOS) 设置菜单。每个 BIOS 品牌都有不同的按键需要按住才能执行此操作。互联网上有列表。有时通过冻结 BIOS 消息或观看屏幕,您需要按下的键将在诸如“Press DEL for setup”的消息中指示。但是它可能会闪烁得太快以至于您错过了它。当然,您不会在 BIOS 中设置您不理解的东西,否则您的 PC 可能会被禁用。
来自启动时 BIOS 的消息告诉您当时的硬件配置。当前配置可能仍然相同,因为 Linux 应该希望接受 BIOS 已完成的操作(如果它没问题)。来自 Linux 的消息可能来自使用内核 PnP 功能来检查和/或设置总线资源的驱动程序。这些应该是正确的,但要注意仅显示驱动程序从配置文件中获知的内容的消息。这可能是错误的。当然,如果设备运行良好,那么它很可能与驱动程序配置相同。
从内核 2.6 开始,除了 /proc 目录树之外,还有一个 /sys 树,请参阅 /sys 树。这些树对于查找资源配置和设备很有用。其中的“文件”代表内核内存中的数据,根本不存在于您的硬盘驱动器上。诸如 lspci 之类的程序从 /proc 树获取其信息,因此此类程序应以比直接检查 /proc 中的“文件”更可读的形式显示结果。以下是 4 个 /proc “文件”,它们显示了设备驱动程序在内核中注册的资源。
由于 Linux 的即插即用通过让设备驱动程序为其设备分配资源来工作,因此如果驱动程序尚未请求保留此类资源,则可能不会列出您的某些硬件使用的资源。对于内核模块(可加载设备驱动程序)的情况,如果模块尚未加载,则内核不知道它需要的任何资源。有时,模块仅在您启动需要它的应用程序时才加载。因此,如果 /proc 中的这些“文件”中缺少某些硬件,则可能意味着该硬件尚未被使用。例如,即使您的软盘驱动器中装有软盘并且可以使用,但除非正在使用,否则其中断不会显示出来。
/pts 显示 I/O 地址。如果存在错误(错误的地址),则意味着麻烦,因为设备将无法接收发送给它的字节。
/proc/iomem 显示注册的 IO 内存地址。
/proc/interrupts 显示当前正在使用的中断。
/proc/dma 显示 dma(直接内存访问)ISA dma 通道分配。
过去,作者观察到列出了不存在的中断。在某些情况下,它表明实际上发送了一些此类中断。这可能是由于硬件缺陷导致发出错误的中断。
/proc/bus/ 具有子目录(子文件夹)input/、pci/ 和 isapnp/。此目录中大多数文件的格式非常神秘,通常只是配置空间中字节的副本。因此,仅在万不得已时才使用它们。input/ 子目录包含有关输入设备(如键盘和鼠标)的信息。它不像 /proc/bus/ 下的其他目录那样神秘,并且可能会产生一些关于 PS2 或 LPC 总线上的输入设备的有用信息(请参阅 LPC 总线)。不幸的是,我所看到的并没有说明它是否在 LPC 总线上,即使它很可能在。在 /pci/00/ 中,每个 pci 设备都有一个二进制文件,其中文件名是 pci 插槽号(也称为 pci 插槽名称)。00 表示 pci 总线 0。
从内核 2.6 开始,有一个新的 /sys 目录用于 PnP 配置。它是一种 sysfs 类型的文件系统,它有点像 /proc 文件系统,因为“文件”代表内核内存中的信息,而不是在您的硬盘驱动器上。但它不如 /proc 文件系统有用。最初(在 2.5 内核中),它被称为“驱动程序文件系统”,类型为“driverfs”。
在 sysfs 中,系统上存在的每个设备都有自己的目录,其中包含显示分配给它的资源的文件。此类设备目录的名称类似于 0000:00:12.0@ 或 00:06@。这些设备是什么?第一个是您 PC “插槽” 12 中的 PCI 卡。插槽实际上可能在您的 PC 内部标记为 PCI2(2 而不是 12)。这是因为低编号的“插槽”用于主板上的内置设备,这些设备不使用任何物理插槽。在此示例中,“插槽” 1-10 将是内置的,而实际插槽 11-14 标记为 1-4。通过键入“lspci”,您将能够将数字(如 0000:00:12.0)与名称(如 IDE 接口)匹配。键入“lspci -v”或“lspci -vv”以查看更多信息。
那么,00:06 是什么?它是一张 ISA 卡(或内置设备),但它不是 ISA 插槽 6(如 PCI 编号)。当搜索 ISA-PNP 设备时,它是找到的第 6 个设备。更准确地说,它是找到的第 7 个设备,因为有一个设备编号为:00:00。那么如何识别它们呢?好吧,您可以键入:“cat */*”并显示所有设备的所有文件,但即使这样您也看不到设备名称(但会看到您可以从中识别它们的信息)。这种不便之处有望在未来得到解决。
这些文件不仅提供有关总线资源配置(格式有些神秘)和驱动程序(在“driver”目录中)的信息,而且在未来,您应该能够使用它们来更改资源配置。目前(2004 年 8 月),您无法使用它配置 PCI 总线。一个严重的限制是,根据当前的“驱动程序模型”,您无法更改已分配给驱动程序的设备的资源,这可能意味着您需要卸载驱动程序模块才能使用它。如果驱动程序是内置的,则没有希望。这些严重的限制有望在未来消除。在内核文档中有一个文件:“pnp.txt”,告诉您如何配置。截至 2004 年 8 月,它已经非常过时了,但作者正在努力更新。使用 /sys 树配置资源被称为“Linux 即插即用用户界面”。
“Linux 即插即用”的另一部分是设备驱动程序使用的内核接口。从内核 2.6 开始,这已经发生了很大变化,但大多数驱动程序仍然在使用旧的接口(截至 2004 年 8 月)。驱动程序(或您)也可以使用“用户界面”,这需要改进。
使用 “lspci” 和/或 “scanpci” 命令很容易找出分配给 PCI 总线上设备的总线资源。选项 -v 或 -vv 将显示更多细节。在某些情况下,“scanpci” 会找到 “lspci” 找不到的设备。这是因为 “scanpci” 直接在 pci 总线上搜索设备(通过配置空间),并且不使用内核获得的数据(由于内核错误,数据可能不正确——我刚刚发现了一个这样的案例)。
以更神秘的格式,此信息可以在 /sys
和 /proc
树中的 “文件” 中找到。在 /sys/bus/pci/devices
中,文件 vendor
将包含供应商 ID 号,例如 0x4B8C 等。以更神秘的格式,它在 /proc/bus/pci
中。在内核 2.6 之前的旧内核中,此类信息在 /proc/pci
中(非神秘但 IRQ 以十六进制表示)或在 /proc/buspci/devices
中(神秘显示)。
在大多数情况下,对于 PCI,您只会看到硬件现在的配置方式,而看不到所需的资源。在某些情况下,您只能看到基地址(范围的起始地址),而看不到结束地址。如果您看到整个范围,那么您可以确定需要多少字节的地址资源。
对于 ISA 总线上的卡,它不像本质上是 PnP 的 PCI 总线那样简单。后来的 ISA 卡是 PnP 的,但较旧的不是。此外,一些 PnP 卡的 PnP 功能被仅在 MS 上运行的特殊软件禁用。非 PnP 卡通过卡上的跳线或 MS 软件进行配置。
如果是 PnP 卡,您可以尝试运行 pnpdump --dumpregs
,但这并不确定。结果可能看起来很神秘,但可以解读。不要将 pnpdump
用于与 PnP 卡通信的读取端口地址与找到设备的 I/O 地址混淆。它们是不相同的。
LPC(低引脚数)是一种总线类接口,通常用于笔记本电脑,并且越来越多地用于台式机。要找出您是否具有 LPC 类型,请键入 “lspci” 并查找 “LPC”。“LPC” 旁边还有其他词,例如 “ISA Bridge ... LPC Interface Controller” 或 “LPC Bridge” 等。LPC 实际上不是 ISA,但它可以替代 ISA 总线。
旧的 ISA 总线速度很慢,需要更高速度的设备被放置在较新的 PCI 总线上。但是,不需要高速的设备通常通过主板上的芯片实现,并且即使没有用于任何 ISA 卡的插槽,也保留在 ISA 总线上。然后出现了 LPC 总线,以取代 ISA 总线的剩余部分。LPC 比 ISA 小得多,速度也一样快,因为它以 ISA 时钟速度的 4 倍运行。其用于数据/地址和控制的多路复用总线只有 4 位宽。要发送一个字节,需要将字节拆分为 2 个半字节,然后再将它们重新组合在一起。因此,很明显为什么它是 “低引脚数” = LPC。总线中还有一些其他线路。
这种小型 LPC 接口用于慢速 “传统” 设备,例如串口、并口和软盘驱动器。因此,使用 LPC 的计算机将在 PCI 总线等上拥有所有快速设备,而在 LPC 总线接口上拥有慢速(传统)设备。所有 LPC 设备都将是板载的;没有 LPC 插槽。
LPC 没有即插即用配置标准,但表示 BIOS 或 ACPI 应该进行配置。此总线上的设备有时使用 isapnp。截至 2004 年末,Linux 对 LPC 的支持非常不完整,但 Linux 对 ACPI 的配置方面有一些支持。有时,BIOS 菜单允许人们手动 PnP 配置 LPC 总线上的设备,但它可能不会告诉您该设备位于 LPC 上。
LPC 总线上的主要芯片是 superio 芯片,其中包含传统 IO 设备:串口和并口、软盘控制器、键盘控制器、鼠标等。BIOS 数据也可能驻留在 LPC 总线上。键盘和鼠标(输入设备)应在 /proc/bus/input/devices 中列出,但似乎显示 “isa0060/serio0 等,而不是看到 “lpc”,即使它在 lpc 总线上而不是 isa 总线上。
在 LPC 总线普及之前,有一种 “X 总线”(本 HOWTO 中未介绍),它的用途与 LPC 总线相同,但不如 LPC 紧凑。有些 PC 同时具有 LPC 和 X 总线。
与 PnP 卡相比,非 PnP 卡始终在硬件中设置其资源。也就是说,它们始终具有地址和 IRQ,除非有跳线设置等来禁用设备。有时,可以通过设备驱动程序完成的探测或通过其他执行探测的软件来找到使用的资源。例如,“scanport”(仅限 Debian ??)探测大多数 IO 端口地址,并可能找到 ISA 设备。但请注意,它可能会使您的 PC 挂起。有时它会找不到实际存在的硬件(因为硬件在其寄存器中具有默认值 0xff)。即使它找到了硬件,它也不会显示 IRQ,也不会积极地识别硬件。
因此,尝试查找此类硬件的一种方法是启动驱动程序,该驱动程序可能会探测此类硬件。通过查看启动时消息,您可能会看到驱动程序启动并找到硬件。否则,您可能需要找到驱动程序并启动它(例如,通过将其作为模块加载)。
找到正确的驱动程序可能很困难。有时根本没有任何驱动程序,因为某些设备(尚未?)不受 Linux 支持。要确定您需要哪个驱动程序,请查看任何可能识别该卡的文档。如果这失败了,请查看卡本身,包括芯片上的重要名称/编号。但是,您需要的驱动程序模块的标识可能不在卡上的任何位置。您可以在卡上找到 FCC ID,然后使用 FCC ID 号搜索 Internet,以尝试找到有关该卡(或其上的芯片)的更多信息。
如果卡具有用于设置资源(配置)的跳线,则可以查看跳线的设置方式。有些卡同时具有 PnP 和跳线。如果 PnP 以某种方式被禁用,它们就像跳线卡一样工作。有时卡上有标签显示如何设置跳线(或至少提供一些线索)。您可能需要卡随附的文档(印刷版或软盘)。也许您可以在 Internet 上找到它。
最困难的情况之一是,在 MS 下运行的软件已被用于配置非 PnP 卡或 PnP 已被相同的 MS 软件禁用的 PnP 卡。因此,您既不能通过 PnP 配置它,也不能通过跳线配置它。在这种情况下,您唯一的希望是按照 非 PnP 卡 中描述的那样探测地址。或者尝试找到配置它的 MS 软件。
在重复努力中,Linux 的各种主要发行版开发了自己的硬件检测和/或配置工具。这种配置通常不仅仅是即插即用的资源类型配置。它是一般的配置,这在很大程度上超出了本 howto 的范围。
然后,其他发行版(例如 Debian)可能会获得该工具的副本,并将其作为选项或作为故障排除工具提供给其用户。这些工具很可能利用标准的 Linux 工具来检测硬件,例如 “lspci”。在以下工具列表中,开发它的发行版的名称在括号中,但该工具也可能在其他发行版中可用。
有各种工具可用于查找和可能配置各种类型的设备。此配置是一般的配置,本 howto 不涵盖。
有些人试图使用 Windows 来查看总线资源是如何设置的。不幸的是,由于 PnP 硬件在断电时会忘记其总线资源配置,因此在 Linux 下配置可能不相同。对于非 PnP 硬件(或有人通过跳线或 Windows 软件禁用了设备内部的 PnP 功能),则使用 Windows 应该可以正常工作。即使对于 PnP,它通常结果相同,因为在许多情况下,Windows 和 Linux 都只是简单地接受 BIOS 设置的内容。但是,在 Windows 和/或 Linux 进行配置的地方,它们可能会以不同的方式进行配置。因此,不要指望 PnP 设备配置相同。
每个需要中断的 PCI 设备都带有一个固定的 PCI 中断,该中断无法更改。它由插槽号和一个字母 A、B、C 或 D 指定。示例 3:B。但是,此 PCI 中断由主板上的芯片映射(路由或重定向)到中断号,例如 21。
此路由由 “可编程中断路由器” = PIR 完成。或者,中断线可能只是直接路由(没有任何 PIR)。如果存在 PIR(路由器),则可以由 BIOS 或 Linux 编程。因此,PCI 设备的中断有时可能会被更改,不是通过在不同的电线上发送中断,而是通过编程 PIR 来更改该电线上脉冲的路由。当路由更改时,此新路由提供的中断将写入位于设备芯片中的配置寄存器中。
在 PCI 总线之前,PC 使用 ISA 总线,然后在过渡到较新的 PCI 总线期间,大多数 PC 计算机同时使用 PCI 和 ISA 总线。ISA 总线的所有中断线都连接到每张卡,因此任何卡都可以通过在不同的线路(在不同的引脚上)上发出其中断信号来更改其中断请求号。所有中断信号都发送到中断控制器,然后中断控制器向 CPU 发出信号,以临时停止它正在执行的操作并运行驱动程序代码来服务中断。
当 PCI 首次出现时,简单的解决方案只是将 PCI 中断映射到未使用的可用 ISA 中断。这需要使用 “可编程中断路由器” = PIR(硬件)来执行此映射。但是,由于只有 15 个此类中断,因此通常将许多 PCI 设备放置在少数可用中断上。解决此问题很简单:提供新的硬件以增加中断数量。结果是 APIC。但是,由于 PCI 总线共享中断的能力缓解了中断短缺问题,因此 APIC 的采用速度很慢。因此,APIC 主要用于需要双处理器的场合。
这可以提供(取决于型号)16、24、32 或 64 个中断等。它还可以处理多个 CPU 情况下的中断从一个 CPU 到另一个 CPU 的路由。请参阅内核文档的 i386 目录中的文件 “IO-APIC” 和 ACPI-HOWTO。不要将 APIC 与 ACPI(高级配置和电源接口)混淆,内核可能会使用 ACPI 来配置 APIC。
连接到中断线的实际 APIC 控制器是 I/O APIC(或 IO-APIC 或 IOAPIC)。通过使用多个 IO-APIC,可以获得更多中断,并且对它们进行编号以使其唯一。例如,第一个控制器可以具有输入引脚 0-23,第二个控制器将其输入引脚称为 24-47,从而产生 48 个编号为 0-47 的中断。但是,有些人发现他们具有很高的中断号。是否可能是第二个 IO-APIC 的起始基数高于它应该有的基数,从而留下很长一段不存在的 irq 空隙?
除了 IO-APIC 之外,还有本地 APIC (LAPIC),它是每个 CPU 的一部分。IO-APIC 通过与 CPU 内部的 LAPIC 通信来完成其工作。
当引入 APIC 时,旧的 ISA PIC 也被保留下来,从而可以选择是否使用 APIC 或 ISA 的 PIC(有时在 /proc/interrupts 中仅称为 PIC 或 XT-PIC;“XT” 来自 IBM 的 XT PC,它是 IBM 在 1983 年的第二款 PC 型号)。可以告诉内核(在内核命令行上)不使用 APIC,在这种情况下,如果 XT-PIC 可用,它将使用旧的 XT-PIC。但是由于 APIC 可以具有比 XT-PIC 提供的 15 个中断更多的中断,因此可能会出现问题 ??
要查看您是否具有 PIC 或 APIC,请查看 /proc/interrupts。如果您仅在 irq 2 中看到 XT-PIC,而在其他 irq 中看到 IO-APIC,则可能意味着您具有旧的 XT-PIC,但当前未使用它。嗯,irq 2 可用于两个旧的 XT-PIC 之间的通信,以防您需要在使用它们时禁用 APIC。有两个 XT-PIC,因为每个仅支持 8 个中断。
另一项发展是消息信号中断 (MSI),其中中断只是通过主计算机总线发送到特殊地址的消息(无需中断线)。但是,发送此类消息的设备必须首先获得对主总线的控制权,以便它可以发送中断消息。此类消息包含比 “我正在发送中断” 更多的信息。它包含需要运行的程序地址的索引,以服务 IRQ。该索引(例如 3)意味着 cpu 找到它必须跳转到的地址,该地址位于 cpu 已知的特殊表的第 3 个元素中。
由于卡必须支持 MSI,但许多卡不支持,因此中断硬件支持的传统方法(称为 INTx)似乎将长期存在。
PCI 中断可以共享,这意味着两个或多个 PCI 设备会产生相同的 IRQ。如果可行,通常最好不要共享。共享对于以下情况无法正常工作:1. 非常旧的 PCI 硬件(1995 年之前 ??);2. 有缺陷的 PCI 硬件,可能存在出厂缺陷(天生如此)。例如,如果 IRQ9 上的一个 PCI 设备错误地声称任何 IRQ9 都是针对它的,那么其他使用 IRQ9 的设备最终可能会使其发出的所有 IRQ 被忽略,因为坏设备错误地声称了它们的 IRQ。在不共享的情况下,可以避免这个问题。
有关在两个 PCI 设备之间共享同一 IRQ 的示例,请参阅 PCI 中断共享。这种共享能力内置于硬件中,所有设备驱动程序都应该支持它。请注意,您通常无法在 PCI 和 ISA 总线之间共享同一中断。
一些信息由启动时消息提供,可以通过键入 dmesg 查看。以下查看表的方法涉及您可能没有(或尚不存在)的软件。要检查 PCI 路由到 16 个 ISA 中断的路由,请使用 pirtool,它显示 $PIR 路由表。如果您有带硬连线路由(无 PIR)的 APIC,请使用 mptable 查看 MP 表。对于可路由的 APIC,可以通过 ACPI _PRT 方法访问表(但是是否有命令行命令来执行此操作?)
有关中断的详细技术信息,请访问 FreeBSD 下 x86 机器的 PCI 中断。微软提供了 在单处理器 PC 上实现基于 APIC 的中断子系统的重要性
以下是 PCI 中断系统的一些细节。每张 PCI 卡(以及安装在主板上的设备)都有 4 个可能的中断:INTA#、INTB#、INTC#、INTD#。从现在开始,我们将它们简称为 A、B、C 和 D。每个中断在 PCI 卡的边缘连接器上都有自己的引脚。因此,对于一个 7 插槽系统(用于 7 张卡),这些卡可能有多达 7 x 4 = 28 条不同的中断线。内置于主板的设备也有额外的中断。但是规范允许更少数量的中断线,因此一些 PCI 总线似乎只制造了 4 条或 8 条中断线。这并不是太受限制,因为中断可以共享。对于 4 条中断线(导线、迹线或链路)LNKA、LNKB、LNKC、LNKD,有一个可编程的“中断路由器”芯片,可以将 LNKA、LNKB、LNKC、LNKD 路由到选定的 IRQ。此路由可以由 BIOS 或 Linux 更改。例如,LNKA 可以路由到 IRQ5。假设我们将插槽 3 的 B 中断指定为中断 3B。然后中断 3B 和 2A 都可以永久连接到 LNKA,而 LNKA 又路由到 IRQ5。这两个中断:3B 和 2A 通过主板上的硬连线永久共享。
可以在命令行上键入“dmesg”来查看中断线(如 LNKA)如何路由(或链接)到 IRQ(*5 表示它链接到 IRQ 5)。查找“PCI Interrupt Link”。请注意,“链接”在这里有两种含义:1. PCI 中断线到 IRQ 的链接(路由)。2. 中断线的标签,例如 LNKB(链接 B)。中断线标签似乎由 BIOS 提供 ??,它们可能有许多不同的名称,例如:LNKC、LNK2、APCF、LUBA、LIDE 等。问题:当大量中断线显示为禁用时,它们是否都物理存在于主板上?或者它们是否只存在于 ACPI BIOS 软件中,以便 BIOS 可以与具有更多中断线的主板一起工作?
将这些线从 PCI 设备(如 3B)连接到中断 LNKA 等的一种简单方法是将所有 A 中断 (INTA#) 连接到线 LNKA,将所有 B 中断连接到 LNKB,等等。这种方法曾经在多年前使用过,但这不是一个好的解决方案。原因如下。如果一张卡只需要一个中断,则必须使用 A。如果它需要两个中断,则必须同时使用 A 和 B,等等。因此,INTA# 的使用频率远高于 INTD#。因此,最终会使过多的中断共享第一条线(LNKA 连接到所有 INTA#)。为了克服这个问题,可以以更随机的方式连接它们,以便 4 条中断线(LNKA、LNKB、LNKC、LNKD)中的每一条都共享大致相同数量的实际 PCI 中断。
执行此操作的一种方法是使导线 LNKA 共享中断 1A、2B、3C、4D、5A、6B、7C。这是通过物理连接导线 W 到导线 1A、2B 等来完成的。同样,导线 LNKB 可以连接到导线 1B、2C、3D、4A、5B、6C、7D 等。然后在启动时,BIOS 将 LNKB、LNKA、LNKC、LNKD 映射到 IRQ。之后,它将每个设备使用的 IRQ 写入每个设备中的硬件配置寄存器。从那时起,任何程序查询此寄存器都可以找出设备使用的 IRQ。请注意,仅仅将 IRQ 写入 PCI 卡上的寄存器并不会以任何方式设置该设备的 IRQ。
此信息的实际用途是,作为最后的手段,可以通过将 PCI 卡插入不同的插槽来更改其 IRQ。在上面的示例中,如果 PCI 卡插入插槽 1(1A 映射到 LNKA),则 PCI 卡的 INTA# 将连接到导线 LNKA,但当 PCI 卡插入插槽 4(4A 映射到 LNKB)时,INTA# 将连接到导线 LNKB。
插槽中的卡上最多可能有 8 个设备,但每个卡只有 4 个 PCI 中断(A、B、C、D)。这是可以的,因为中断可以共享,因此 8 个设备中的每一个(如果存在)都可以拥有一个共享中断。设备的 PCI 中断字母通常是固定的并硬连线到设备中。中断的分配由 BIOS 或 Linux 完成,将 PCI 中断映射到如上所述的类 ISA 中断。
如果只有 4 条线(LNKA、LNKB、LNKC 和 LNKD),如上述示例所示,则 PCI BIOS 的映射选择是有限的。一些主板可能使用更多线,因此有更多选择。例如 LNKA-LNKH(8 条线)。启动时消息(和 dmesg)可能会显示它们以及它们的映射方式。BIOS 知道它们的接线方式。
在 PCI 总线上,BIOS(或 Linux)分配 IRQ(中断)以避免与其知道的 ISA 总线上的 IRQ 冲突。有时,CMOS BIOS 菜单可能允许您为 PCI 卡分配 IRQ,或告诉 BIOS 哪些 IRQ 要为 ISA 设备保留。这些分配被称为“路由表”。在 MS Windows 中,它被称为“IRQ 转向”,但这还涵盖了启动后动态 IRQ 路由的情况。BIOS 可能支持其自己的 IRQ 转向。
如果您的 PC 使用映射到 ISA 中断的 PCI 中断,您可能会认为中断速度很慢,因为 ISA 总线速度很慢。并非如此。ISA 中断控制器芯片有一个直接连接到 CPU 的中断线,因此它可以立即引起注意。虽然旧 ISA 地址和数据总线上的信号到达 CPU 的速度很慢,但 IRQ 中断信号到达 CPU 的速度非常快。
USB(通用串行总线)是一种高速总线,通过外部电缆插入 PC。外部总线电缆有自己的通信协议,不使用任何 IRQ、I/O 地址(或其他总线资源)。通信通过数据包进行,有点像互联网,只是有时间片分配,可以防止任何一个设备在其他设备需要时占用总线。存在空闲时间槽,允许每个设备向总线控制器发送短消息,而无需总线上的 IRQ。
但是,PC 内部的 USB 总线控制器确实在 PCI 总线(或 ISA)上具有 IRQ 和地址,这些 IRQ 和地址用于 CPU 与 USB 上的所有设备之间的通信。因此,USB 上的各个设备不需要资源分配。也可以将此视为 USB 上的所有设备共享一个中断和地址。如果设备在 USB 上,则需要一个了解 USB 的驱动程序。
但是,USB 上的每个设备都有 ID,就像 PCI 总线上的卡一样。因此,Linux 可能会维护这些 ID 的表,以便设备驱动程序可以检查它们以找到其设备。USB 还支持“热插拔”。要找出 USB 总线上有什么,您可以使用通用的硬件检测工具,如“discover”或“hwinfo”。
“热插拔”是指您将某物插入 PC(通常通过电缆连接),它会立即被检测到。如果需要,会使用总线资源对其进行配置。它的驱动程序也已启动,可能是通过为其加载模块。为了使此功能正常工作,使用的硬件必须设计为支持热插拔。可以热插拔某些 PCI 卡 (Cardbus)、USB 设备和 IEEE 1394 设备 (Firewire)。
当检测到新设备时,会读取其寄存器以获取设备的 ID 号。然后,为了找到驱动程序,Linux 必须维护一个将 ID 号映射到驱动程序的表。直到内核 2.4,才存在这样的表,因为 Linux 曾经避开了集中式 PnP。它被命名为:MODULE_DEVICE_TABLE。
“热交换”是指您移除旧设备,然后插入新设备以替换旧设备。您因此“交换”了设备。现在,除了能够检测到已插入新设备之外,还需要检测到旧设备的移除。
通过电缆连接到串行端口的外部设备(如外部调制解调器)也可以称为即插即用。由于只有串行端口本身需要总线资源(IRQ 和 I/O 地址),因此没有总线资源分配给此类插件设备。在这种情况下,PnP 仅用于识别调制解调器(读取其型号代码)。如果调制解调器是软件调制解调器 (linmodem) 并且需要特殊驱动程序,则这可能很重要。对于此类外部串行设备(连接到串行端口的设备),有一个特殊的 PnP 规范。
Linux 尚不支持此功能 ?? 对于硬件调制解调器,普通的串行驱动程序可以正常工作,因此几乎不需要使用特殊的串行 PnP 来查找驱动程序。您仍然需要告诉通信程序调制解调器所在的端口(如 /dev/ttyS1)。使用 PnP,您甚至不需要这样做。随着具有 Linux 驱动程序(linmodem)的软件调制解调器的出现,如果可以通过 PnP 自动安装相应的驱动程序,那就太好了。
这意味着发生了没有驱动程序预期的中断。硬件不太可能错误地发出中断。更可能是软件存在小错误,并且没有意识到某些软件做了某些事情导致了中断。在许多情况下,您可以安全地忽略此错误消息,尤其是当它仅在启动时发生一两次时。对于启动时消息,请查看附近的消息,以了解正在发生的事情的线索。例如,如果正在进行探测,则对物理设备的探测可能会导致该设备发出驱动程序未预期的中断。也许驱动程序没有监听正确的 IRQ 号。
BIOS 无法配置总线资源。可能存在无法避免的中断冲突。戴尔建议您移除一些非必要的卡,看看问题是否消失。在一种情况下,此问题是由于主板缺陷造成的。
如果您使用 isa-pnp,则 IO 地址 0xa79 绝不能被任何设备使用。因此,如果您尝试加载 isa-pnp 模块时,其他硬件正在使用 0xa79,您将在日志中收到此消息,并且 isa-pnp 将退出。尝试解决此问题的一种方法是在其他硬件初始化之前尽早加载 isa-pnp 模块。对于 PCMCIA,这意味着在运行 cb 模块和服务之前加载 isa-pnp。
这里“区域”表示地址范围。需要两个地址的 PCI 设备将具有区域 0 作为第一个地址,区域 1 作为第二个需要的地址。使用命令:lspci -vv 查看各种资源区域(通常简称为区域)以及地址类型是 IO 还是内存。在 PCI 术语中,区域 2 是“基地址 2”(或“基地址寄存器 2”)等。
当两个或多个设备使用同一中断线(和同一 IRQ 号)时,它是“中断共享”或“中断冲突”。PCI 总线允许所有 PCI 设备彼此共享中断,因此这称为“共享”。但是,如果 ISA 设备(或 LPC 设备 ??)与某些其他设备(PCI、ISA 或 LPC ??)使用相同的中断 (IRQ),则通常会发生中断冲突。
上述内容存在例外。一些非常旧的 PCI 设备(1995 年之前 ??)不允许中断共享。相反,一些 ISA 设备被设计为共享中断(在两个 ISA 设备之间 ??),但这两个 ISA 设备都必须以这种方式设计,并且由了解共享中断的软件驱动。主板也必须支持它。以下讨论与具有 ISA 总线的 PC 有关。
冲突意味着当发生中断时,可能不会调用任何设备驱动程序(或错误的驱动程序),并且会发生缓冲区溢出(数据丢失)等不良情况。设备可能几乎将其中断线接地,因为它没有发送中断,从而阻止任何其他设备使用该中断线。如果只有该设备使用该中断,则没问题。但是,如果第二个设备尝试使用同一中断线,则它无法执行此操作。如果第二个设备在不发送中断时也几乎将线路接地,则两个设备都无法使用中断。但是 Linux 和这两个设备都不知道此冲突,并且仍然愉快地发送中断,但这些中断大多无处可去,因此丢失了。
当 IRQ 通过卡上的跳线(ISA 总线)设置时,中断冲突很常见,因为内核通常不知道这些跳线是如何设置的。ISA 即插即用(卡上没有跳线)有所帮助,因为软件可以更改 IRQ。ISA 的消亡而 PCI 的兴起几乎消除了 IRQ 冲突。尽管如此,您的 PC 可能在主板(不在插件卡上)上的 ISA 总线、LPC 总线或 X 总线上有设备。但是 BIOS 和内核应该知道这些是如何设置的,从而避免将它们用于 PCI 设备,从而避免中断冲突。但是,PCI 仍然可能存在中断问题,因为它可能会耗尽可用的中断,尤其是在只有 16 个中断的旧 PC 上。
但是,PCI 总线上的 IRQ 共享虽然消除了冲突问题,但引入了另一个不太严重的问题:IRQ 平衡问题。如果太多高 IRQ 发射设备共享同一 IRQ,则可能会导致 IRQ 服务延迟,甚至可能导致缓冲区溢出和其他错误。这不是由于中断线上的拥塞造成的,而是由于软件确定哪个设备发出中断的方式造成的。PCI 中断共享
中断冲突有两种类型。一种是如上所述的真实冲突。在这种情况下,中断不起作用,设备驱动程序不断尝试控制其设备,但没有意识到中断不起作用。第二种类型的中断冲突是启动设备驱动程序,但发现它需要的中断已被使用,因此它会发出错误消息并退出。该消息可能会说“资源忙”,但没有明确说明是中断问题。
BIOS 和内核都不会有意允许任何中断冲突,那么它们是如何发生的呢?一种方法是有人在配置文件中放置了错误的 IRQ,例如为模块提供参数:irq=9。在此示例中,假设设备的 irq 实际上是 irq5。然后,当另一个设备驱动程序启动时,其设备设置为 irq5,您有两个真实设备使用 irq5,并且发生真实冲突。内核批准让第二个设备使用 irq5,因为它错误地认为第一个设备正在使用 irq9,而 irq5 是空闲的。
还有其他类似的情况,内核未能知道 irq 正在使用中。一种情况是存在通过跳线设置 irq 的旧 ISA 卡,但其驱动程序尚未启动(或者它甚至可能没有驱动程序)。另一种情况是 BIOS 在硬件中设置了 irq,但该硬件的 Linux 驱动程序从未启动,并且 Linux 不知道该 irq。即使对于 PCI 卡,也可能发生这种情况,并且 irq 将显示在 lspci -v 中,但不会显示在 /proc/interrupts 目录中,因此内核不知道。这是内核中的错误吗?
中断冲突的症状是什么?人们可能认为设备根本无法工作,但由于地址是已知的,因此驱动程序确实进行了通信。中断通常用于控制设备之间的数据流,如果没有中断,则无法控制数据流。这可能意味着缓冲区溢出,甚至根本没有数据流,因为中断用于启动数据流。对于串行调制解调器,结果是极慢的数据流,伴有长时间的停顿和频繁的错误。对于声卡,它可能意味着听到一两个字,然后就什么也没有了。
这是指设备驱动程序启动但立即退出的情况,以避免中断冲突。它应该显示或记录类似“资源忙”的错误消息。
一种情况是 ISA 设备被激活,但无法分配中断 (IRQ),因为没有可用的中断。或者中断可能是可用的,但由于需要中断的设备的硬件不支持可用的中断号(或者主板由于“路由”问题而不支持它,请参阅 PCI 中断),因此无法使用中断。如果 ISA 设备用完了所有中断,则一个或多个 PCI 卡可能会发生冲突,因为它们无法获得任何 IRQ。
通常,BIOS 将分配中断,并且不会产生冲突。但是,如果 IRQ 用完,它可能会被迫产生冲突。如果有人已设置 BIOS 以为非 PnP 的旧 ISA 设备保留某些 IRQ,则可能会发生这种情况。这些设置可能不正确,应进行检查,尤其是在您遇到问题时。例如,有人可能为早已从 PC 中移除的 ISA 卡保留了 IRQ。如果您取消保留此 IRQ,则此 IRQ 可用,冲突消失。
有时,BIOS 会通过使用所谓的 IRQ 0 来解决 IRQ 短缺的问题。没有可用的 IRQ 0,因为真正的 IRQ 0 永久分配给计算机的计时器。但是,此处的 IRQ 0 表示驱动程序应使用轮询而不是 IRQ。这意味着驱动程序经常检查设备(轮询设备)以查看设备是否需要中断服务例程的服务。当然,这会浪费计算机时间,并且设备内部缓冲区溢出的可能性更大,因为它可能无法及时得到驱动程序的处理。
这实际上是微软开发的一种网络即插即用技术,但 Linux 可以使用它。您将某物插入网络,该物无需配置,前提是它仅与网络上其他启用 UPnP 的设备通信。这里的“配置”是在广义上使用的,并不意味着仅配置总线资源。一个目标是允许对网络或配置知之甚少的人员安装路由器、网关、网络打印机等。UPnP 的主要用途将是无线网络。
UPnP 使用
本 HOWTO 不涵盖 UPnP。Linux 的 UPnP 由 Intel 支持,Intel 为其开发了软件。还有其他一些程序的功能与 UPnP 大致相同。其中一些程序的比较可以在 http://www.cs.umbc.edu/~dchakr1/papers/mcommerce.html 找到。Linux 的 UPnP 项目位于 SourceForge:Linux 的 UPnP SDK
地址有三种类型:主存储器地址、I/O 地址(端口)和配置地址。在 PCI 总线上,配置地址构成单独的地址空间,就像 I/O 地址一样。除了 ISA 配置地址的复杂情况外,总线上的地址是内存地址、I/O 地址还是配置地址仅取决于总线其他导线(迹线)上的电压。有关 ISA 配置地址,请参阅 ISA 总线配置地址(读取端口等) 了解详细信息
术语“地址”有时在本文档中用于表示连续的地址范围。地址以字节为单位。因此,例如,I/O 地址范围为 3F8-3FF 的串行端口通常仅以其基地址 3F8 指代。3F8 是范围(地址范围)中第一个字节的位置。要查看各种设备的地址范围,请查看 /proc/iomem 和 /proc/ioports。
为了访问 I/O 和(主)存储器地址“空间”,使用了相同的地址总线(用于地址的导线是共享的)。设备如何知道地址总线上出现的地址是内存地址还是 I/O 地址?好吧,对于 ISA(对于 PCI 也请阅读此内容),总线上有 4 条专用导线来传递此类信息。如果这 4 条导线中的某一条被断言,则表示 CPU 想要从 I/O 地址读取数据,并且主存储器忽略总线上的地址。总而言之,主存储器和 I/O 地址都存在读取和写入导线(总共 4 条导线)。
对于 PCI 总线,基本思想相同(也使用 4 条导线),但方式略有不同。不是仅断言四条导线中的一条,而是将二进制数放在导线上(16 种不同的可能性)。因此,这 4 条导线可以传递更多信息。这 16 个数字中的四个像上面段落中那样服务于 I/O 和内存空间。此外,还有配置地址空间,它占用了另外两个数字。这还剩下 10 个数字用于其他目的。
这与 IO 和内存地址空间不同,因为配置地址空间是“地理”的。卡的每个插槽都将插槽号作为地址的一部分。这样,Linux(或 BIOS)就可以寻址某个插槽并找出该插槽中卡的类型。每个设备都有 64 个标准字节大小的寄存器,其中一些寄存器保存可以明确识别设备的数字。由于插槽数量有限,并且内置于主板的 PCI 设备数量也有限,因此 Linux(或 BIOS)只需要检查有限数量的地址即可找到所有 PCI 设备。如果它从设备的第一个寄存器中读取所有 1(十六进制为 0xFF),则表示没有设备存在。由于没有卡或设备来提供所有这些 1 (0xFF) 数字,因此主板上的 PCI“主机桥”会为所有不存在的设备提供(欺骗)此数字。
PCI 插槽号在 PCI 术语中称为“设备号”,并且由于卡上最多可能有 8 个设备,因此功能号 0-7 标识它是 PCI 卡上的哪个设备。这些数字是地理地址的一部分。Linux 程序员称其为“pci-slot-name”。因此,Linux 所谓的“设备”实际上是 PCI 术语中的“功能”。PCI 总线号(通常为 00)也成为地理地址的一部分。例如,0000:00:0d.2 是 PCI 总线 0、插槽 0d、功能 2。对于完整的地理地址,必须包括要访问的设备配置寄存器的双字编号。前导 0000(在 1999 年)保留供将来使用。
CPU 如何指定读取或写入是针对 PCI 配置空间?它不是直接指定的。相反,当需要访问配置空间时,它会对 IO 空间中的 0cf8-0cfb 执行 32 位(双字)写入,并将完整的地理地址写入此处。PCI 主机桥正在此地址监听,并确保任何下一个写入 0cfc-0cff 的数据都放入指定设备的指定配置寄存器中。桥通过向指定的 PCI 卡(或类似物)发送一个特殊信号来完成此操作,该信号通过专用导线仅到达卡插入的插槽。它还在控制总线上放置一些位,说明现在地址总线上的内容是地理配置空间地址。
为什么不简化操作,让 CPU 在控制总线上放置一些位,以说明主总线上的地址是用于 PCI 配置的地理地址?嗯,大多数 CPU 都无法做到这一点,因此 PCI 主机桥改为执行此操作。
在 ISA 总线上,每张 PnP 卡都内置了一种方法,用于检查是否没有其他卡使用相同的 I/O 地址。如果两个或多个卡使用相同的 IO 地址,则两个卡都可能无法正常工作(如果可以工作的话)。良好的 PnP 软件应分配总线资源,以避免此冲突,但即使在这种情况下,也可能在某处潜伏着具有相同地址的旧卡。
该测试的工作原理是卡将其已知的测试编号放入其自身的 IO 寄存器中。然后 PnP 软件读取它,并验证其读取的内容是否与已知的测试编号相同。如果不是,则说明存在问题(例如,另一张卡具有相同的地址)。它使用另一个测试编号重复相同的测试。由于它实际上检查了分配给卡的 IO 地址范围,因此称为“范围检查”。最好称之为地址冲突测试。如果存在地址冲突,您将收到错误消息。
传统上,大多数 I/O 设备仅使用 I/O 内存与 CPU 通信。在 CPU 上运行的设备驱动程序会将数据读写到 I/O 地址空间和主存储器。不幸的是,这需要两个步骤。例如,1. 从设备(在 IO 地址空间中)读取数据并临时存储在 CPU 中;2. 将此数据写入主存储器。更快的方法是让设备本身将数据直接放入主存储器。执行此操作的一种方法是使用 ISA DMA 通道或 PCI 总线主控。另一种方法是让物理设备实际包含一些主存储器(位于高地址,以免与主存储器芯片地址冲突)。这样,设备可以直接读取和写入其自身包含的主存储器,而无需费心处理 DMA 或总线主控。此类设备也可以使用 IO 地址。
这些地址也称为“自动配置端口”。对于 ISA 总线,从技术上讲没有配置地址空间,但是 CPU 可以通过特殊方式访问 PnP 卡上的 PnP 配置寄存器。为此,分配了 3 个 @ I/O 地址,每个地址仅寻址单个字节(没有“范围”)。这不是每张卡 3 个地址,而是所有 ISA-PnP 卡共享的 3 个地址。
这 3 个地址名为读取端口、写入端口和地址端口。每个端口的大小只有一个字节。每张 PnP 卡都有许多配置寄存器,因此仅 3 个地址甚至不足以满足单张卡上的配置寄存器。为了解决这个问题,使用称为“隔离”的技术为每张卡分配一个卡号(句柄)。有关复杂详细信息,请参阅 ISA 隔离。
要配置特定的卡,首先通过写入端口地址发送其卡号(句柄),告知该卡监听其地址端口。所有其他卡注意到这不是它们的卡号,因此不监听。然后,将配置寄存器(针对该卡)的地址发送到地址端口(针对所有卡 -- 但只有一张卡在监听)。接下来,通过在读取端口上执行读取或在写入端口上执行写入,与该卡上的配置寄存器进行数据传输。
写入端口始终位于 A79,地址端口始终位于 279(十六进制)。读取端口不是固定的,而是由配置软件设置在某个地址(范围为 203-3FF),希望不会与其他 ISA 卡冲突。如果存在冲突,它将更改地址。所有 PnP 卡都使用此地址进行“编程”。因此,如果您使用 isapnp 来设置或检查配置数据,则必须确定此读取端口地址。
前面说过,每个中断都有一根线。但是串行化中断(或串行中断)是一个例外。单根导线用于所有在该导线上进行多路复用的中断。每个中断在中断线上都有一个时隙。它用于 LPC 总线,也用于 PCI 总线,但很少用于 PCI ??
在深入探讨中断细节之前,除了发送中断之外,某些设备还有另一种启动通信的方式。这种方法是 DMA(直接内存访问)请求,用于在有限的时间内从 CPU 接管计算机的控制权。在 PCI 总线上,它不使用任何“资源”。并非所有设备都能够进行 DMA。请参阅 DMA 通道。
还有另一种类型的中断,称为“软中断”,本文档未涵盖,也不使用任何“资源”。硬件中断由硬件生成,而软中断由软件启动。 有几种方法可以做到这一点。一种方法是让软件告诉 CPU 发出中断(中断指令)。另一种方法是让软件向其他进程发送消息以中断它们,尽管尚不清楚这是否应该称为中断。您可能会在 Linux PC 上找到运行的 ksoftirq 进程,它是一个程序,用于执行此类中断以处理设备驱动程序。设备驱动程序由于硬件中断而开始运行,但稍后,软件中断用于驱动程序中断服务例程的“下半部分”。因此,ksoftirq 进程也称为“下半部分”。有关更多详细信息,请参阅内核文档。
中断传递大量信息,但只是间接地传递。设备发送的中断请求信号(导线上的电压)只是告诉称为中断控制器的芯片,某个设备需要关注。然后,中断控制器向 CPU 发送信號。然后,CPU 中断它正在执行的任何操作,找到此设备的驱动程序代码,并运行其一部分,称为“中断服务例程”(或“中断处理程序”)。此“例程”尝试找出发生了什么,然后处理问题。例如,可能需要从/向设备传输字节。此程序(例程)可以轻松找出发生了什么,因为设备在驱动程序软件已知的地址处具有寄存器(前提是设备的 IRQ 号和 I/O 地址已正确设置)。这些寄存器包含有关设备的状态信息。软件读取这些寄存器的内容,并通过检查内容,找出发生了什么并采取适当的措施。
因此,每个设备驱动程序都需要知道要监听哪个中断号 (IRQ)。在 PCI 总线上(以及 ISA 总线上的一些特殊情况下),两个(或多个)设备可以共享同一个 IRQ 号。请注意,您不能将 PCI 中断与 ISA 中断共享(是否有任何例外 ??)。当发出共享中断时,CPU 会按顺序为所有使用该中断的设备运行所有中断服务例程。此类服务例程做的第一件事是检查其设备的寄存器,以查看是否真的为该设备发生了中断。如果它发现其设备没有发出中断(误报),那么它可能会立即退出,并且下一个服务例程开始为使用同一中断的第二个设备运行。它像上面描述的那样检查设备。重复此序列,直到找到实际发出中断的设备。一个中断的所有中断例程都被称为构成一个链。因此,遍历链,直到链上的例程通过有效地说:此中断是给我的,来声明中断。处理中断后,链上更远的中断服务例程不会运行。
在 IRQ 线上施加电压只是请求中断 CPU,以便它可以运行设备驱动程序。在几乎所有情况下,CPU 都会按请求中断。但是中断可能会暂时禁用或优先排序,因此在极少数情况下,CPU 的实际中断不会发生(或会延迟)。因此,上面称为“中断”的更准确地说只是一个中断请求,并解释了为什么 IRQ 代表中断请求 (Interrupt ReQuest)。
先前关于设备驱动程序监听其中断的说法过于简单化了。实际上,是主板上的一个芯片(或芯片的一部分),称为“中断控制器”,监听所有中断。当中断控制器捕获到中断时,它会向 CPU 发送信号,以启动相应的设备驱动程序的“中断服务例程”来处理中断。
有多种类型的中断控制器。一种类型是 APIC = 高级可编程中断控制器,它通常具有许多中断的输入引脚,包括 PCI 中断。较旧的控制器只有用于 ISA 中断的引脚,但它们仍然可以处理 PCI 中断,因为有一个“可编程中断路由器”,可以将 PCI 中断转换为 ISA 中断,并将它们路由到 ISA 中断控制器上的某些引脚(= 某些 IRQ)。
这仅适用于旧的 ISA 总线。隔离是一种复杂的方法,用于为 ISA 总线上的每个 PnP 设备分配一个临时句柄(ID 号或卡选择号 = CSN)。由于有更有效(但更复杂)的方法可以做到这一点,因此有些人可能会声称这是一种简单的方法。只有一个写入地址用于对所有 PnP 设备进行 PnP 写入,因此写入此地址会发送到所有正在监听的 PnP 设备。此写入地址用于向每个 PnP 设备发送(分配)唯一的句柄。要分配此句柄,需要仅当一个设备在监听时,才将句柄发送(写入)到此公共地址。所有 PnP 设备都有唯一的序列号,它们在隔离过程中使用该序列号。进行隔离就像一场游戏。它是通过仅使用一根公共总线导线将所有 PnP 设备连接到隔离程序来完成的。
在“游戏”的第一轮中,所有 PnP 设备都监听这根导线,并同时向导线发送一连串的位。允许的位是 1(正电压)或“开路 0”(无电压,开路或三态)。为此,每个 PnP 设备只需开始在这根导线上顺序发送其序列号、电压(开路或三态)。为此,每个 PnP 设备只需开始在这根导线上逐位顺序发送其序列号,从高位开始。如果任何设备发送 1,则所有其他设备都将在导线上听到 1。如果所有设备都发送“开路 0”,则导线上将听不到任何声音。目标是(在本轮结束时)消除除序列号最高的设备以外的所有设备。“消除”意味着退出本轮游戏,从而暂时停止监听导线。(请注意,所有序列号的长度都相同。)当只剩下一个设备仍在监听时,将为其分配一个句柄(卡号)。
首先仅考虑序列号的高位,该高位首先由所有尚未拥有句柄的设备放在导线上。如果任何 PnP 设备发送 0(开路 0)但听到 1,则表示其他一些 PnP 设备具有更高的序列号,因此它暂时退出本轮。现在,游戏中剩余的设备(在本轮中)都具有相同的首位数字 (1),因此我们可以剥离该数字,并且仅考虑生成的“剥离后的序列号”以供将来参与本轮。然后转到本段的开头并重复,直到已检查每个设备的整个序列号(有关全 0 情况,请参见下文)。
因此,很明显,在一轮中只有序列号较低的卡会被淘汰。但是,如果游戏中所有设备都发送 0 作为其高位会发生什么?在这种情况下,在导线上发送“开路 0”,并且所有参与者都留在游戏中。如果它们都以 0 开头,则这是平局,并且就像上面段落中的 1 一样,将 0 剥离掉。然后,当发送序列号的下一位数字时,游戏继续进行。
在本轮结束时(在发送出序列号的低位之后),游戏中仅剩下一个序列号最高的 PnP 设备。然后为其分配一个句柄并永久退出游戏。然后,上一轮的所有退出者(尚未拥有句柄)重新进入游戏,并且以少一个参与者开始新一轮。最终,所有 PnP 设备都分配了句柄。很容易证明此算法有效。实际的算法比上面介绍的算法稍微复杂一些,因为每个步骤都重复两次以确保可靠性,并且重复的执行方式略有不同(但使用相同的基本思想)。
分配所有句柄后,它们用于寻址每个 PnP 设备以发送/读取配置数据。请注意,这些句柄仅用于 PnP 配置,而不用于与 PnP 设备的正常通信。当计算机启动时,PnP BIOS 通常会执行此类隔离,然后执行 PnP 配置。之后,所有句柄都“丢失”了,因此,如果想再次更改(或检查)配置,则必须重新进行隔离。
如果总线具有可用的总线主控,则在该总线上进行 DMA 可能不需要任何资源。例如,PCI 总线不需要 DMA 资源,因为它具有“总线主控”。但是,“总线主控”通常称为 DMA。但由于它不是严格意义上的 DMA,因此不需要 DMA 资源。ISA 和 VESA 局部总线没有总线主控。旧的 MCA 和 EISA 总线确实具有总线主控。
您必须将 IO、IRQ 和 DMA 作为参数提供给模块或将它们编译到内核中。但是某些 PCI 卡将被自动检测到。RedHat 提供了一个程序“sndconfig”,它可以检测 ISA PnP 声卡,并自动设置模块以加载检测到的总线资源。
这将通过 PnP 方法检测卡,然后选择合适的驱动程序并加载它。它还将在 ISA-PnP 卡或 PCI 卡上设置总线资源。OSS(开放声音系统)以前很流行。
Windows NT4 不支持 ISAPNP,但有一个 PNPISA 程序,可以“自行承担风险”使用。对于 NT4 用户,建议在 BIOS 中设置“不是 PnP 操作系统”,以便 BIOS 执行资源配置。因此,MS Windows 和 Linux 在过去都依赖 BIOS 进行配置(现在仍然如此)。
Plug-and-Play-HOWTO 结束