下一页 上一页 目录

5. 高级主题

5.1 PCMCIA 设备的资源分配

理论上,分配给哪个设备哪个中断并不重要,只要两个设备没有配置为使用同一个中断即可。在 /etc/pcmcia/config.opts 中,您可以找到排除非 PCMCIA 设备使用的中断的位置。

同样,没有直接指定卡使用的 I/O 地址的方法。/etc/pcmcia/config.opts 文件允许您指定任何卡可用的端口范围,或排除与其他设备冲突的范围。

修改 /etc/pcmcia/config.opts 后,您可以使用 ``kill -HUP'' 重新初始化 cardmgr

用于监控卡状态更改的中断由底层套接字驱动模块(i82365tcic)在 cardmgr 解析 /etc/pcmcia/config 之前选择,因此它不受对此文件更改的影响。要设置此中断,请在加载套接字驱动程序时使用 cs_irq= 选项,方法是在 /etc/rc.d/rc.pcmcia 中设置 PCIC_OPTS 变量。

所有客户端卡驱动程序都有一个名为 irq_list 的参数,用于指定它们可能尝试分配的中断。这些驱动程序选项应在您的 /etc/pcmcia/config 文件中设置。例如

device "serial_cs"
  module "serial_cs" opts "irq_list=8,12"
  ...

将指定串行驱动程序应仅使用 irq 8 或 irq 12。无论 irq_list 设置如何,Card Services 永远不会分配已被另一个设备使用的中断,或在配置文件中排除的中断。

5.2 PCI 中断配置问题和解决方案

以下大部分讨论适用于 2.2 和更早版本的内核。在 2.4 和更高版本的内核中,PCI 子系统对 PCI 中断管理负有更完整的责任。以下提示可能有助于诊断问题,尽管此处描述的某些解决方法可能不可用。

PCI 中断路由问题概述

每个 PCI 插槽都有四个 PCI 中断引脚,INTA 到 INTD。单功能设备将仅使用 INTA 引脚;多功能设备可以使用多个 INT 引脚。在处理器端,在 x86 单处理器系统上,传入的硬件中断被定向到编号为 0..15 的中断请求 (irq)。PCI 中断路由器(通常是 PCI 到 ISA 主桥的一部分)确定如何将传入的 PCI 中断映射到 CPU irq 编号。大多数现代桥芯片都有多个 PCI 中断输入,称为 PIRQ1、PIRQ2 等,每个输入都可以路由到任何 CPU irq 编号。因此我们可能有类似这样的情况

PCI slot 1 INTA --> router PIRQ1 --> CPU irq 9
PCI slot 1 INTB --> router PIRQ2 --> CPU irq 10

PCI slot 2 INTA --> router PIRQ2 --> CPU irq 10
PCI slot 2 INTB --> router PIRQ1 --> CPU irq 9

多个 INT 引脚通常连接到同一个 PIRQ 引脚。通常,从 INT 引脚到 PIRQ 引脚的连接被安排尽可能分散已安装的设备,以便为操作系统提供最大的灵活性来选择如何共享中断。从桥 PIRQ 引脚到 CPU irq 编号的映射可以通过读取中断路由器中的寄存器获得。然而,从 INT 引脚到路由器 PIRQ 引脚的映射取决于板设计者决定如何连接,并且无法由驱动程序软件直接确定。

对于大多数 PCI 设备,操作系统不需要了解中断路由器的详细信息。每个 PCI 设备都有一个配置寄存器,即 PCI 中断线寄存器,BIOS 使用该设备的适当 CPU irq 编号对其进行初始化。不幸的是,BIOS 通常不会为 CardBus 桥设备配置 PCI 中断。

PCI BIOS 的中断路由表是一个数据结构,其中包含有关从 PCI INT 引脚到 PCI 中断路由器上的 PIRQ 引脚的映射信息。但是,表中的路由信息以某种无用的形式存储。对于每个设备的 INT 引脚,该表指定一个“链接值”。所有具有相同链接值的中断都连接到同一个 PIRQ 引脚;但是,链接值的含义由芯片组供应商定义。

有几个工具可用于检查 PCI 中断路由信息

lspci/proc/pci

这些将显示您所有 PCI 设备的资源信息(包括中断分配,如果已知)。

dump_pirq

这在 PCMCIA 源代码发行版的 debug-tools 目录中。它转储您的 PCI 中断路由表的内容(如果可用)。它还会扫描已知的中断路由器并转储其当前的中断控制设置。

几个 PCMCIA 模块参数会影响 PCI 中断路由

pcmcia_core 模块:cb_pci_irq=n

此选项指定一个中断号,用于为所有尚未分配中断的 CardBus 插槽编程 PCI 中断路由器。它仅对具有 PCI irq 路由表和已知中断路由器的系统有效。

i82365 模块:irq_mode=n

大多数 CardBus 桥提供几种将中断传递到主机的方法。i82365 模块默认假定桥可以传递 PCI 和 ISA 中断,因为这在笔记本电脑上很常见。“irq_mode=0”的设置可用于强制桥仅使用 PCI 中断。有关不同桥类型的其他值的含义的描述,请参阅 i82365 模块的 man 页面。

i82365 模块:irq_list=n,n,...

此参数列出哪些 ISA 中断可用于 PCMCIA。如果没有可用的 ISA 中断,请指定“irq_list=0”。请注意,“irq_mode=0”意味着“irq_list=0”。

i82365 模块:pci_irq_list=n,n,...

此选项指定用于 CardBus 插槽的 PCI 中断号列表。它与 cb_pci_irq 不同,因为它实际上不编程 PCI 中断路由器;当您知道 PCI 中断已经以某种方式设置时,即使您不知道路由器如何工作,也可以使用它。

如果您遇到您认为可能与 PCI 中断配置相关的问题,您应该首先验证您是否有一个相当新的 PCMCIA 驱动程序包。还要仔细查看加载 PCMCIA 内核模块时的启动消息。您应该看到类似这样的内容

Linux PCMCIA Card Services 3.1.18
  kernel build: 2.2.14-5.0 #1 Tue May 9 10:44:24 PDT 2000 
  options:  [pci] [cardbus] [apm] [pnp]
PCI routing table version 1.0 at 0xfdf30
Intel PCIC probe:
  TI 1125 rev 02 PCI-to-CardBus at slot 00:07, mem 0x20000000
    host opts [0]: [ring] [serial pci & irq] [pci irq 11] ...
    host opts [0]: [ring] [serial pci & irq] [pci irq 11] ...
  ISA irqs (scanned) = 3,4,7 PCI status changes

PCI routing table”消息表示找到了有效的路由表。“host opts”行表示中断传递模式以及是否可以为每个插槽确定 PCI 中断。最后一行指示可用中断扫描的结果。

PCI BIOS 未检测到 CardBus 桥

症状

Lucent/SCM PCI-to-CardBus 适配器似乎混淆了一些较旧系统上的 PCI BIOS。Lucent 表示,此卡仅在具有支持 PCI 2.2 规范或符合 PC99 标准的 BIOS 的系统上受支持。一些较旧的系统根本无法检测到 Lucent 卡,如果系统无法检测到它,Linux 驱动程序也无法使用它。唯一可能的解决方案是 BIOS 升级,或使用不同的主板或 CardBus 适配器。

PCI 中断传递问题

症状

CardBus 桥通常支持两种类型的中断,PCI 和 ISA。部分出于历史原因,传统上使用 PCI 中断来表示卡插入和移除事件以及 CardBus 卡中断;以及使用 ISA 中断来表示 16 位卡。自 3.1.9 版本以来,这是 Linux PCMCIA 系统默认使用的方案。大多数 CardBus 桥支持多种将中断传递到主机 CPU 的方法。方法包括“并行”中断,其中每个支持的 irq 在桥上都有一个专用引脚;各种串行中断协议,其中使用一个或两个引脚与中断控制器通信;以及混合型,其中 PCI 中断可以使用专用引脚发出信号,而 ISA 中断通过串行控制器传递。

通常,BIOS 负责为适当的中断传递方法编程桥。但是,有些系统会错误地执行此操作,并且在某些情况下,软件无法安全地检测到正确的传递方法。i82365 模块在启动时报告桥模式,并具有一个参数 irq_mode,可用于重新配置它。并非所有桥都支持此参数,并且 irq_mode 的含义取决于桥类型。有关您的桥支持哪些值的描述,请参阅 i82365 man 页面。在某些情况下,桥可能在多种中断模式下正常工作。

大多数安装在 PCI 总线插槽中的 PCMCIA 读卡器仅提供 PCI 中断路由。Linux 驱动程序假定所有桥都具有 ISA 中断功能,因为这在笔记本电脑上通常是正确的。对于读卡器,通常需要使用 irq_mode 参数来指定“仅 PCI”中断传递模式;参数的值取决于桥类型,因此请查看 i82365 man 页面。少数 PCI 读卡器需要允许 ISA 中断的 irq_mode,但这些中断实际上并未连接;在这种情况下,请使用“irq_list=0”。

检查系统日志并验证 CardBus 桥是否具有 PCI 中断分配。如果它没有,请首先解决该问题,然后如果症状仍然存在,请返回此处。接下来,尝试 irq_mode 参数的不同值。

没有 PCI 中断分配;有效的路由表

症状

当存在路由表时,pcmcia_core 模块将尝试自动配置 PCI 中断路由器,但仅当它对要使用的 PCI 中断有安全且明确的选择时才这样做。如果有多个有效的选择,则您必须使用“cb_pci_irq=...”选项来指定要分配的中断。您最好的选择是选择已分配给另一个 PCI 设备的、使用最少的中断。

将卡移动到另一个插槽有时可以提供快速解决方案。如果该插槽与其中断与已配置的设备共享,则 PCMCIA 驱动程序将毫不费力地找出分配。

没有 PCI 中断分配;未知的中断路由器

症状

添加对新中断路由器的支持很棘手,但不是一项大工作。首先从数据表中确定您的中断路由器如何控制 PCI 中断。然后,看看您是否可以从 dump_pirq 的输出中猜测链接值的含义。通常这非常明显。大多数路由器有四个 PIRQ 引脚,链接值可能类似于 1,2,3,4 或 0x10,0x18,0x20,0x28 或 0x60,0x61,0x62,0x63。通常选择这些值,以便可以轻松地将其转换为适当的中断控制寄存器的位置。最后,将小的函数添加到 modules/pci_fixup.c 以获取/设置此路由器的中断控制信息,使用其他路由器作为示例。

没有 PCI 中断分配;没有路由表

症状

没有中断路由表,我们无法知道来自 CardBus 桥的中断如何定向到 CPU irq 编号。并非所有希望都破灭了:您也许可以猜测 PCI 中断分配,并使用“pci_irq_list=...”选项将此信息传递给 i82365 模块。好的猜测可能包括分配给其他 PCI 设备的中断、Windows 下使用的中断或任何其他未说明的中断。

您可能还想尝试将适配器放入不同的 PCI 插槽,为您尝试的每个 pci_irq_list。您正在尝试找到一个与其中断与已配置的设备共享的插槽,并且可能需要尝试几个插槽才能找到一个。

5.3 如何为家庭和工作设置单独的设备?

使用“方案”支持,这非常容易。使用两个配置方案,分别称为“home”和“work”。以下是带有方案特定设置的 network.opts 脚本示例

case "$ADDRESS" in
work,*,*,*)
    # definitions for network card in work scheme
    ...
    ;;
home,*,*,*|default,*,*,*)
    # definitions for network card in home scheme
    ...
    ;;
esac

设备地址的第一部分始终是配置方案。在此示例中,第二个“case”子句将选择“home”和“default”方案。因此,如果由于任何原因未设置方案,它将默认为“home”设置。

现在,要在两组设置之间进行选择,请运行以下任一项

cardctl scheme home

cardctl scheme work

cardctl 命令执行相当于关闭所有卡并重新启动它们的操作。无论 PCMCIA 系统是否已加载,都可以安全地执行该命令,但是如果您当时正在使用其他 PCMCIA 设备(即使它们的配置未明确依赖于方案设置),则该命令可能会失败。

要找出当前的方案设置,请运行

cardctl scheme

默认情况下,方案设置在启动之间是持久的。如果为错误的环境初始化网络,这可能会产生不良影响。或者,您可以使用 SCHEME 启动选项设置初始方案值(有关详细信息,请参阅 启动选项)。也可以从 lilo 启动提示符设置方案。由于 lilo 将无法识别的选项作为环境变量传递给 init,因此启动提示符下的 SCHEME 值(或任何其他 PCMCIA 启动选项)将传播到 PCMCIA 启动脚本中。

为了节省更多击键次数,可以在 lilo 的配置文件中指定方案。例如,您可以拥有

root = /dev/hda1
read-only
image = /boot/vmlinuz
  label  = home
  append = "SCHEME=home"
image = /boot/vmlinuz
  label  = work
  append = "SCHEME=work"

在启动提示符下键入“home”或“work”将启动到相应的方案。

5.4 从 PCMCIA 设备启动

将根文件系统放在 PCMCIA 设备上很棘手,因为 Linux PCMCIA 系统并非设计为链接到内核中。其核心组件,可加载的内核模块和用户模式 cardmgr 守护程序,依赖于已运行的系统。内核的“initrd”工具通过允许 Linux 使用临时 ram 磁盘作为最小根映像启动,加载驱动程序,然后重新挂载不同的根文件系统来解决此要求。临时根可以配置 PCMCIA 设备,然后重新挂载 PCMCIA 设备作为根。

initrd 映像绝对必须驻留在可启动设备上:这通常不能放在 PCMCIA 设备上。这是 BIOS 限制,而不是内核限制。在此区分“可启动”设备(即,可以启动的设备)和“可作为根”设备(即,可以作为根挂载的设备)很有用。“可启动”设备由 BIOS 确定,通常仅限于内部软盘和硬盘驱动器。“可作为根”设备是内核加载后支持的任何块设备。initrd 工具使更多设备“可作为根”,而不是“可启动”。

一些 Linux 发行版允许安装到连接到 PCMCIA SCSI 适配器的设备,这是因为它们支持从 PCMCIA SCSI CD-ROM 设备安装的意外副作用。但是,目前,没有 Linux 安装工具支持配置适当的“initrd”以使用 PCMCIA 根文件系统启动 Linux。因此,设置具有 PCMCIA 根的系统需要您使用另一个 Linux 系统来创建“initrd”映像。如果另一个 Linux 系统不可用,则另一种选择是在非 PCMCIA 驱动器上临时安装最小的 Linux 设置,创建 initrd 映像,然后重新安装到 PCMCIA 目标。

Linux Bootdisk-HOWTO 有一些关于设置启动盘的一般信息,但没有关于 initrd 的具体信息。主要的 initrd 文档包含在最新的内核源代码发行版中,位于 linux/Documentation/initrd.txt。在开始之前,您应该阅读本文档。熟悉 lilo 也很有帮助。使用 initrd 还要求您编译的内核启用了 CONFIG_BLK_DEV_RAMCONFIG_BLK_DEV_INITRD

这是一种高级配置技术,需要高度熟悉 Linux 和 PCMCIA 系统。在开始之前,请务必阅读所有相关文档。以下食谱说明应该有效,但与示例的偏差将很快使您进入未知的和“不受支持”的领域,您将需要自行解决。

此方法绝对要求您使用 2.9.5 或更高版本的 PCMCIA 驱动程序版本。较旧的 PCMCIA 包或单个组件在 initrd 上下文中不起作用。请勿混合使用来自不同版本的组件。

pcinitrd 辅助脚本

pcinitrd 脚本创建一个基本的 initrd 映像,用于使用 PCMCIA 根分区启动。该映像包括最小的目录层次结构、少量设备文件、一些二进制文件、共享库和一组 PCMCIA 驱动程序模块。在调用 pcinitrd 时,您可以指定要包含在映像中的驱动程序模块。核心 PCMCIA 组件 pcmcia_coreds 会自动包含在内。

例如,假设您的笔记本电脑使用 i82365 兼容的主机控制器,并且您想使用连接到 Adaptec SlimSCSI 适配器的硬盘驱动器上的根文件系统启动 Linux。您可以使用以下命令创建适当的 initrd 映像

pcinitrd -v initrd pcmcia/i82365.o pcmcia/aha152x_cs.o

要自定义 initrd 启动序列,您可以使用“loopback”设备挂载映像,命令如下

mount -o loop -t ext2 initrd /mnt

然后编辑 linuxrc 脚本。配置文件将安装在映像的 /etc 下,也可以自定义。有关更多信息,请参阅 pcinitrd 的 man 页面。

创建 initrd 启动软盘

使用 pcinitrd 创建映像后,您可以通过将内核、压缩的 initrd 映像和一些用于 lilo 的支持文件复制到干净的软盘来创建启动软盘。在以下示例中,我们假设所需的 PCMCIA 根设备是 /dev/sda1

mke2fs /dev/fd0
mount /dev/fd0 /mnt
mkdir /mnt/etc /mnt/boot /mnt/dev
cp -a /dev/fd0 /dev/sda1 /mnt/dev
cp [kernel-image] /mnt/vmlinuz
cp /boot/boot.b /mnt/boot/boot.b
gzip < [initrd-image] > /mnt/initrd

使用以下内容创建 /mnt/etc/lilo.conf

boot=/dev/fd0
compact
image=/vmlinuz
    label=linux
    initrd=/initrd
    read-only
    root=/dev/sda1

最后,使用以下命令调用 lilo

lilo -r /mnt

当使用 -r 调用 lilo 时,它会相对于指定的备用根目录执行所有操作。在 /mnt/dev 下创建设备文件的原因是,当 lilo 在此备用根模式下运行时,将无法使用 /dev 中的文件。

在非 Linux 驱动器上安装 initrd 映像

initrd 工具的一个常见用途是在内部硬盘驱动器专用于另一个操作系统的系统上。Linux 内核和 initrd 映像可以放在非 Linux 分区中,并且可以设置 liloLOADLIN 以从这些映像启动 Linux。

假设您有一个内核已为适当的根设备配置,并且在另一个系统上创建了一个 initrd 映像,那么开始的最简单方法是使用 LOADLIN 启动 Linux,如下所示

LOADLIN <kernel> initrd=<initrd-image>

一旦您可以在目标计算机上启动 Linux,您就可以安装 lilo 以允许直接启动 Linux。例如,假设 /dev/hda1 是非 Linux 目标分区,并且 /mnt 可以用作挂载点。首先,在目标上为 Linux 文件创建一个子目录

mount /dev/hda1 /mnt
mkdir /mnt/linux
cp [kernel-image] /mnt/linux/vmlinuz
cp [initrd-image] /mnt/linux/initrd

在本例中,假设 /dev/sda1 是所需的 Linux 根分区,是通过 PCMCIA SCSI 适配器挂载的 SCSI 硬盘驱动器。要安装 lilo,请创建包含以下内容的 lilo.conf 文件

boot=/dev/hda
map=/mnt/linux/map
compact
image=/mnt/linux/vmlinuz
        label=linux
        root=/dev/sda1
        initrd=/mnt/linux/initrd
        read-only
other=/dev/hda1
        table=/dev/hda
        label=windows

boot= 行表示将引导加载程序安装在指定设备的主引导记录中。root= 行标识在加载 initrd 映像后要使用的所需根文件系统,如果内核映像已经以这种方式配置,则可能是不必要的。other= 部分用于描述安装在 /dev/hda1 上的其他操作系统。

在这种情况下安装 lilo,请使用

lilo -C lilo.conf

请注意,在这种情况下,lilo.conf 文件使用包含 /mnt 的绝对路径。我在示例中这样做是因为目标文件系统可能不支持为 boot=root= 选项创建 Linux 设备文件。


下一页 上一页 目录