Linux PCMCIA HOWTO

David Hinds, dahinds@users.sourceforge.net

v2.118, 2003年12月06日


本文档描述了如何为 Linux 安装和使用 PCMCIA Card Services,并解答了一些常见问题。本文档的最新版本始终可以在 http://pcmcia-cs.sourceforge.net 找到。

1. 通用信息和硬件需求

2. 编译和安装

3. 解决安装和配置问题

4. 使用和功能

5. 高级主题

6. 处理不受支持的卡

7. 调试技巧和编程信息


1. 通用信息和硬件需求

1.1 简介

Linux 的 Card Services 是一个完整的 PCMCIA 或 “PC Card” 支持包。它包括一组可加载的内核模块,这些模块实现了 Card Services 应用程序编程接口的版本、一组用于特定卡的客户端驱动程序,以及一个卡管理器守护进程,该守护进程可以响应卡插入和移除事件,并按需加载和卸载驱动程序。它支持大多数卡类型的“热插拔”,因此可以随时安全地插入和弹出卡。

此软件正在开发中。它包含错误,应谨慎使用。我会尽力修复报告给我的问题,但如果您不告诉我,我可能永远不会知道。如果您使用此代码,我希望您能将您的经验(无论好坏)发送给我!

如果您对如何改进本文档有任何建议,请告诉我 ( dahinds@users.sourceforge.net)。

1.2 版权声明和免责声明

版权所有 (c) 1998-2002 David A. Hinds

未经我事先许可,可以以任何形式复制或分发本文档。可以自由分发本文档的修改版本,包括翻译成其他语言的版本,前提是这些版本被明确标识为修改版本,并且此版权完整包含在内。

无需我事先同意,即可将本文档包含在商业发行版中。虽然这不是必需的,但我希望被告知此类使用情况。如果您打算将本文档纳入已出版的作品中,请与我联系以确保您拥有最新的可用版本。

本文档按“原样”提供,不提供任何明示或暗示的保证。使用本文档中的信息,风险自负。

1.3 最新版本是什么,以及在哪里可以获取?

Card Services 的当前主要版本是 3.2 版,次要更新或错误修复编号为 3.2.1、3.2.2 等。

最新版本的源代码可在 http://pcmcia-cs.sourceforge.net 的网站上找到,文件名为 pcmcia-cs-3.2.?.tar.gz。您可能会在这里找到多个发布版本号。由您决定哪个版本更合适,但 CHANGES 文件将总结最重要的差异。

预编译的驱动程序包含在当前几乎所有主要的 Linux 发行版中,包括 Slackware、Debian、Red Hat、Caldera 和 SuSE 等。因此,通常不需要从头开始编译驱动程序。

1.4 支持哪些系统?

此软件包应可在几乎所有基于 Intel 的、支持 Linux 的笔记本电脑上运行。它也可以在某些 Alpha、PowerPC、ARM 和 MIPS 平台上运行。支持最常见的插槽控制器。只要桌面系统的卡座使用受支持的控制器,并且直接插入 ISA 或 PCI 总线,而不是 SCSI 到 PCMCIA 或 IDE 到 PCMCIA 适配器,它们就应该可以工作。以下控制器被提供的插槽驱动程序识别:

其他与 Intel i82365sl 寄存器兼容的控制器通常也可以工作。

由于笔记本电脑硬件技术进步迅速,新的控制器频繁出现,因此从新模型上市到驱动程序支持可用之间可能会有延迟。

长期以来,东芝 ToPIC 桥接器的支持受到缺乏足够详细的技术文档的阻碍。虽然已经有一些数据表可用,但 ToPIC 芯片的一些特性没有得到充分解释。东芝就其中一些问题提供了一些直接的技术帮助,我认为主要问题已经解决。但是,随着 2.4.* 和更高版本内核中内核 PCMCIA 支持的引入,新的插槽驱动程序代码中可能出现了一些新的东芝错误。

某些现代笔记本电脑中使用的 Motorola 6AHC05GA 控制器不受支持。HP Omnibook 600 中的自定义主机控制器也不受支持。

1.5 支持哪些卡?

当前版本包括各种以太网卡的驱动程序、调制解调器和串行端口卡的驱动程序、几个 SCSI 适配器驱动程序、ATA/IDE 驱动器卡的驱动程序以及存储卡驱动程序,这些驱动程序应支持大多数 SRAM 卡和一些闪存卡。每个 Card Services 版本附带的 SUPPORTED.CARDS 文件列出了已知在至少一个实际系统中工作的所有卡。

不在支持列表中的卡是否可以工作的可能性取决于卡的类型。基本上所有调制解调器都应该可以使用提供的驱动程序工作。某些网卡可能是受支持卡的 OEM 版本,因此也可以工作。在有人编写相应的驱动程序之前,其他类型的 IO 卡(帧缓冲器、声卡等)将无法工作。

1.6 我最喜欢的(不受支持的)卡何时会得到支持?

不幸的是,他们通常不会付钱给我来编写设备驱动程序,因此如果您希望为自己喜欢的卡提供驱动程序,您可能需要至少做一些工作。理想情况下,我希望朝着类似于 Linux 内核的模式发展,我主要负责“核心”驱动程序代码,而其他作者将贡献和维护特定卡的客户端驱动程序。SUPPORTED.CARDS 文件提到了当前正在进行驱动程序开发的一些卡。我会尽力提供帮助,但请注意,通过电子邮件调试内核设备驱动程序的效果不是特别好。

1.7 邮件列表和其他信息来源

Linux PCMCIA 信息页面位于 http://pcmcia-cs.sourceforge.net,其中包含错误跟踪、支持和功能请求以及各种与 PCMCIA 相关的消息论坛。用户可以请求电子邮件通知以获取对特定问题的新回复,或获取给定类别中所有新消息的通知。我希望这将成为一个有用的信息库,用于解决超出 HOWTO 范围的问题。

Linux 笔记本电脑页面位于 http://www.linux-on-laptops.com,其中包含指向大量站点的链接,这些站点包含有关为 Linux 配置特定类型笔记本电脑的信息。还有一个可搜索的系统配置信息数据库,以及指向各种与笔记本电脑相关的邮件列表的指针。


2. 编译和安装

2.1 先决条件和内核设置

在开始之前,您应该考虑是否真的需要自己编译 PCMCIA 软件包。所有常见的 Linux 发行版都附带预编译的驱动程序包。通常,只有当您需要当前驱动程序的新功能,或者您已更新和/或重新配置内核的方式与 Linux 发行版附带的驱动程序不兼容时,才需要从头开始安装驱动程序。虽然编译软件包在技术上并不困难,但它确实需要一些通用的 Linux 知识。

在开始之前,您的系统上应安装以下内容:

您需要拥有内核的完整 Linux 源代码树,而不仅仅是最新的内核映像。驱动程序模块包含对某些内核源文件的引用。虽然您可能想要构建一个新的内核来删除不必要的驱动程序,但安装 PCMCIA 不需要您这样做。

当前的“稳定”内核源代码和补丁程序可从 ftp://ftp.kernel.org/pub/linux/kernel/v2.4 获取。当前的模块实用程序可以在相同的位置找到。

在 Linux 内核源代码树中,Documentation/Changes 文件描述了该内核版本所需的所有各种其他系统组件的版本。您可能需要检查此文件并验证您的系统是否是最新的,特别是如果您已更新内核。如果您使用的是开发内核,请确保您使用的是共享库和模块工具的正确组合。

在基于 x86 的系统上,如果您计划使用 16 位 PC 卡设备,您还应该为最近的内核启用 CONFIG_ISA。这些卡的行为非常类似于 ISA 设备,PCMCIA 驱动程序使用 CONFIG_ISA 来判断平台是否支持 ISA 总线中断。

配置内核时,如果您计划使用 PCMCIA 以太网卡,则应启用网络支持,但关闭普通的 Linux 网卡驱动程序,包括“袖珍和便携式适配器”。PCMCIA 网卡驱动程序全部实现为可加载模块。任何编译到内核中的驱动程序都只会浪费空间。

如果您想使用 SLIP、PPP 或 PLIP,您需要配置内核以启用这些功能,或者使用这些驱动程序的可加载模块版本。

为了使用 PCMCIA 令牌环适配器,您的内核应配置为启用“令牌环驱动程序支持”(CONFIG_TR),但您应关闭 CONFIG_IBMTR

如果您想使用 PCMCIA IDE 适配器,您的内核应配置为启用 CONFIG_BLK_DEV_IDE_PCMCIA(对于 2.0.* 内核)。较新的内核不需要特殊的配置设置。

如果您将使用 PCMCIA SCSI 适配器,则在配置内核时启用 CONFIG_SCSI。此外,启用您希望使用的任何顶级驱动程序(SCSI 磁盘、磁带、cdrom、通用)。特定主机适配器的所有低级驱动程序都应禁用,因为它们只会占用空间。

此软件包包含一个基于 X 的卡状态实用程序,名为 cardinfo。此实用程序基于一个免费分发的用户界面工具包,名为 XForms 库。此库作为单独的软件包提供,其中包含大多数 Linux 发行版。如果您想构建 cardinfo,则应在配置 PCMCIA 软件包之前安装 XForms 以及所有常规 X 头文件和库。此工具是完全可选的。

2.2 内核 PCMCIA 支持

PCMCIA 驱动程序支持包含在 2.4 和更高版本的 Linux 内核树中。虽然它与独立的 PCMCIA 驱动程序包共享大部分相同的代码,但仍存在一些重要的差异。内核 PCMCIA 支持也仍在不断发展。

内核 PCMCIA 代码具有与 pcmcia-cs 软件包驱动程序端相同的功能。它并没有消除安装 pcmcia-cs 软件包的需要,因为它需要相同的用户工具 (cardmgrcardctl/etc/pcmcia/* 文件)。pcmcia-cs 中的驱动程序仍然可以为 2.4 内核构建,因此您可以选择使用内核内置的 PCMCIA 驱动程序或 pcmcia-cs 中包含的驱动程序。对于 2.5 和更高版本的内核,无法使用独立的驱动程序。

要使用内核 PCMCIA 驱动程序,请使用启用的 CONFIG_HOTPLUGCONFIG_PCMCIA 和通常 CONFIG_CARDBUS 配置内核。在基于 x86 的系统上,也应启用 CONFIG_ISA。驱动程序可以构建到内核中,也可以构建为模块。PCMCIA 客户端驱动程序选项在其常规驱动程序类别中列出;因此,PCMCIA 网络驱动程序位于网络驱动程序的子菜单中,而 PCMCIA 串行驱动程序位于字符驱动程序的子菜单中。

在独立的 pcmcia-cs 驱动程序中,i82365 模块同时支持 ISA 到 PCMCIA、PCI 到 PCMCIA 和 PCI 到 CardBus 桥接器。2.4 树中的 CardBus 插槽驱动程序是 yenta_socket 驱动程序。它由 CONFIG_CARDBUS 选项选择。在您的 PCMCIA 启动选项中,应指定此驱动程序来代替 i82365 驱动程序。内核版本的 i82365 驱动程序(由 CONFIG_I82365 选择)仅支持 ISA 到 PCMCIA 桥接器。内核 PCMCIA 驱动程序根本不支持 PCI 到 PCMCIA 桥接器,如 Cirrus PD6729。

编译独立的 PCMCIA 软件包时,Configure 脚本通过查看内核配置中 CONFIG_PCMCIA 选项的值来决定是否构建任何内核模块。如果 CONFIG_PCMCIA 启用,则默认情况下,不构建任何驱动程序组件。如果 CONFIG_PCMCIA 禁用,则将构建和安装所有模块。在 PCMCIA 软件包中编译用户工具 (cardmgr、cardctl 等) 是安全的,即使其版本号与内核源代码树中的 PCMCIA 版本号不同。如果启用了 CONFIG_PCMCIA,则内核 PCMCIA 头文件优先于 PCMCIA 软件包中包含的头文件。

2.3 安装

以下是安装过程的概要:

如果您计划安装核心 PCMCIA 发行版中未包含的任何贡献的客户端驱动程序,请将每个驱动程序解压缩到 PCMCIA 源代码树的顶层目录中。然后按照正常的构建说明进行操作。额外的驱动程序将自动编译和安装。

运行 “make config” 会提示您输入一些配置选项,并检查您的系统以验证它是否满足安装 PCMCIA 支持的所有先决条件。在大多数情况下,您只需接受所有默认配置选项即可。务必仔细检查此命令的输出,以防出现问题。以下选项可用:

Linux 内核源代码目录?

这是您要与 PCMCIA 一起使用的内核的源代码树的位置。通常这是 /usr/src/linux,但默认位置取决于您使用的 Linux 发行版(或您选择放置内核源代码树的位置)。

构建“信任”版本的卡实用程序?

某些支持实用程序 (cardctlcardinfo) 可以编译为“安全”或“信任”形式。“安全”形式阻止非 root 用户修改卡配置。“信任”形式允许普通用户发出命令来挂起和恢复卡、重置卡以及更改当前配置方案。默认设置为构建安全形式。

包含 32 位 (CardBus) 卡支持?

如果您希望使用 32 位 CardBus 卡,则必须选择此选项。如果您只计划使用 16 位 PC 卡,则不需要此选项来支持 CardBus 桥接器。

包含 PnP BIOS 资源检查?

这会将额外的代码构建到 PCMCIA 核心模块中,以与系统的 PnP BIOS 通信,从而获取内置“主板”设备(串行端口和并行端口、声音等)的资源信息,以帮助避免资源冲突。如果启用,则将在 /proc/bus/pccard 下创建一些额外的资源文件,并且可以使用 lspnpsetpnp 工具来查看和操作 PnP BIOS 设备。但是,此设置在某些笔记本电脑上会导致问题,因此默认情况下未启用。

模块安装目录?

新内核模块将安装到的目录。通常这应该是 /lib/modules 中与您的内核版本匹配的子目录。

如何设置特定于内核的选项?

有一些内核配置选项会影响 PCMCIA 工具。配置脚本可以从正在运行的内核中推断出这些选项(默认和最常见的情况)。或者,如果您要编译以安装在另一台计算机上,则可以从内核源代码树中读取配置,或者可以交互式地设置每个选项。

Configure 脚本也可以非交互方式执行,用于自动构建或在内核更新后快速重新配置。一些其他不太常用的选项只能从命令行设置。运行 “Configure --help” 会列出所有可用选项。

运行 “make all” 后跟 “make install” 将构建并安装内核模块和实用程序。内核模块安装在 /lib/modules/<version>/pcmcia 下。cardmgrcardctl 程序安装在 /sbin 中。如果构建了 cardinfo,则将其安装在 /usr/bin/X11 中。

配置文件将安装在 /etc/pcmcia 目录中。如果您要覆盖旧版本进行安装,则您的旧配置脚本将在被替换之前备份。保存的脚本将获得 *.O 扩展名。

如果您不知道您的系统使用哪种主机控制器,可以使用 cardmgr/ 子目录中的 pcic_probe 实用程序来确定这一点。主要有几种类型:Databook TCIC-2 类型和 Intel i82365SL 兼容类型。对于内核 PCMCIA 子系统,Intel 兼容控制器进一步细分为 ISA 总线 16 位桥接器和基于 PCI 的 CardBus 桥接器。

在少数情况下,pcic_probe 命令将无法自动确定您的控制器类型。如果您有 Halikan NBD 486 系统,它有一个位于异常位置的 TCIC-2 控制器:您需要编辑 rc.pcmcia 以加载 tcic 模块,并将 PCIC_OPTS 参数设置为 “tcic_base=0x02c0”。

在某些使用 Cirrus 控制器的旧的 pre-PCI 系统上,包括 NEC Versa M,BIOS 在系统启动时将控制器置于特殊的挂起状态。在这些系统上,pcic_probe 命令将无法找到任何已知的主机控制器。如果发生这种情况,请编辑 rc.pcmcia 并将 PCIC 设置为 i82365,将 PCIC_OPTS 设置为 “wakeup=1”。

2.4 启动选项

PCMCIA 启动脚本识别几组启动选项,这些选项通过环境变量设置。多个选项应以空格分隔并用引号括起来。启动选项的位置取决于使用的 Linux 发行版。它们可以直接放置在启动脚本中,也可以保存在单独的选项文件中。请参阅 关于特定 Linux 发行版的说明 以了解具体信息。可以设置以下变量:

PCMCIA

此变量指定是否应启动 PCMCIA 支持。如果它设置为 “yes” 以外的任何值,则将禁用启动脚本。

PCIC

这标识了 PC 卡接口控制器驱动程序模块。有几个选项:“tcic”、“i82365” 和(对于内核 PCMCIA 子系统)“yenta_socket”。对于独立驱动程序,几乎所有当前控制器都在 “i82365” 组中,对于内核驱动程序,几乎所有当前控制器都在 “yenta_socket” 组中。这是唯一强制性的选项设置。

PCIC_OPTS

这指定了 PCIC 模块的选项。某些主机控制器具有可选功能,这些功能可能在特定系统中实现,也可能未实现。在某些情况下,插槽驱动程序无法检测到是否实现了这些功能。有关可用选项的完整说明,请参阅相应的手册页。

CORE_OPTS

这指定了 pcmcia_core 模块的选项,该模块实现了核心 PC 卡驱动程序服务。有关更多信息,请参阅 “man pcmcia_core”。

CARDMGR_OPTS

这指定了要传递给 cardmgr 守护进程的选项。有关更多信息,请参阅 “man cardmgr”。

SCHEME

如果设置,则 PC 卡配置方案将在驱动程序启动时初始化为此方案。有关方案的讨论,请参阅 PCMCIA 配置脚本概述

低级插槽驱动程序 tcici82365 具有各种总线时序参数,这些参数可能需要针对某些具有异常总线时钟的系统进行调整。时序问题的症状可能包括卡识别问题、重负载下的死机、高错误率或设备性能不佳。只有某些主机桥接器具有可调整的时序参数:检查相应的手册页以查看您的控制器有哪些可用选项。以下是简要概述:

以下是一些旧系统的时序设置:

桌面系统的读卡器

虽然几乎所有 PCMCIA 读卡器和卡座在 Linux 下都能正常工作,但有些读卡器和卡座需要特殊的启动选项,因为它们的行为与笔记本电脑 PCMCIA 桥接器并不完全相同。特别是 PCI 读卡器,可能以不同的方式处理中断。以下某些参数设置仅适用于独立驱动程序中的 i82365 模块;内核的 yenta_socket 驱动程序是不可配置的。

2.5 系统资源设置

Card Services 应自动避免分配其他标准设备已在使用的 IO 端口和中断。它还会尝试检测与未知设备的冲突,但这并非完全可靠。在某些情况下,您可能需要在 /etc/pcmcia/config.opts 中显式排除设备的资源。

以下是一些特定笔记本电脑类型的资源设置。请以怀疑的态度查看此列表:它可能为解决问题提供有用的提示,但它不可避免地会过时,并且肯定包含错误。欢迎更正和添加。

PowerBook 特定设置

在基于 PowerPC 的 PowerBook 系统上,/etc/pcmcia/config.opts 文件中的默认系统资源完全不好用。将所有 IO 端口和窗口定义替换为类似以下内容:

include port 0x100-0x4ff, port 0x1000-0x17ff
include memory 0x80000000-0x80ffffff

2.6 关于特定 Linux 发行版的说明

本节不完整。欢迎更正和添加。

Debian

Debian 使用 System V 引导脚本排列。PCMCIA 启动脚本安装为 /etc/init.d/pcmcia。新软件包使用 /etc/default/pcmcia 作为启动选项;旧版本使用 /etc/pcmcia.conf 用于此目的。Debian 的 syslog 配置会将内核消息放置在 /var/log/messages 中,并将 cardmgr 消息放置在 /var/log/daemon.log 中。

Debian 在两个软件包中分发 PCMCIA 系统:“pcmcia-cs” 软件包包含 cardmgr 和其他工具、手册页和配置脚本;“pcmcia-modules” 软件包包含内核驱动程序模块。

从 3.1.25 开始,干净的 PCMCIA 安装将识别 Debian 系统并创建一个特殊的 network.opts 文件,该文件在没有其他网络配置设置的情况下,使用 Debian 的 ifupifdown 命令根据 /etc/network/interfaces 中的设置配置网卡。

Red Hat、Caldera、Mandrake

这些发行版使用 System V 引导脚本组织。PCMCIA 启动脚本安装为 /etc/rc.d/init.d/pcmcia,引导选项保存在 /etc/sysconfig/pcmcia 中。请注意,安装 Red Hat 软件包可能会安装一个默认的引导选项文件,该文件已禁用 PCMCIA。要启用 PCMCIA,“PCMCIA” 变量应设置为 “yes”。Red Hat 的默认 syslogd 配置会将所有有趣的消息记录在 /var/log/messages 中。

Red Hat 的 PCMCIA 软件包包含网络设置脚本的替代品 /etc/pcmcia/network,它与 Red Hat linuxconf 配置系统相配合。这对于仅使用一个网卡和一个网络参数集的情况很方便,但不具有常规 PCMCIA 网络脚本的完整灵活性。编译和安装干净的 PCMCIA 源代码发行版将覆盖网络脚本,从而破坏与 Red Hat 工具的链接。如果您更喜欢使用 Red Hat 工具,请仅使用 Red Hat RPM,或将 /etc/pcmcia/network.opts 替换为以下内容:

if [ -f /etc/sysconfig/network-scripts/ifcfg-$2 ] ; then
    start_fn () {
        . /etc/sysconfig/network-scripts/ifcfg-$1
        if [ "$ONBOOT" = "yes" ] ; then /sbin/ifup $1 ; fi
    }
    stop_fn () {
        /sbin/ifdown $1
    }
fi

从 3.1.22 版本开始,PCMCIA 安装脚本将自动将此变体附加到默认的 network.opts 文件中,因此此问题应该不再是问题。

如果您使用 linuxconf(或 netconf)配置网络接口,请将 “内核模块”、“I/O 端口” 和 “irq” 参数留空。设置这些参数可能会干扰 PCMCIA 子系统的正常运行。

在引导时,当 Red Hat 网络子系统启动时,它可能会显示 “Delaying eth0 initialization” 和 “[FAILED]”。这实际上不是失败:这意味着此网络接口将不会初始化,直到 PCMCIA 网络设备配置完成后才会初始化。

Red Hat 将其略作修改的 PCMCIA 源代码发行版与其内核源代码捆绑在一起,而不是作为单独的源代码包。在准备构建一组新的 PCMCIA 驱动程序时,您通常需要安装 Red Hat 的 kernel-source RPM (kernel-source-*.i386.rpm),而不是 kernel SRPM (kernel-*.src.rpm)。SRPM 专为构建其内核 RPM 文件而定制,这与您想要的并不完全相同。对于 Red Hat 7.0,kernel-source RPM 还包含配置错误的 PCMCIA 源代码树;如果您想使用它,请删除其 PCMCIA config.out 文件并重新执行 “make config”。

Slackware

Slackware 使用 BSD 引导脚本排列。PCMCIA 启动脚本安装为 /etc/rc.d/rc.pcmcia,引导选项在 rc.pcmcia 本身中指定。PCMCIA 启动脚本从 /etc/rc.d/rc.S 调用。

SuSE

SuSE 使用 System V init 脚本结构,init 脚本存储在 /etc/init.d 目录下。PCMCIA 启动脚本安装为 /etc/init.d/pcmcia,启动选项保存在 /etc/rc.config 中。在 7.0 版本之前,init 脚本保存在 /sbin/init.d 目录下。在早期的 SuSE 版本(5.3 之前),PCMCIA 启动脚本功能有限,不允许从 lilo 引导提示符覆盖 PCMCIA 启动变量。

SuSE 8.0 既包含独立的 PCMCIA 模块,也包含 2.4 内核 PCMCIA 子系统模块。/etc/sysconfig/pcmcia 中提供了一个新的变量 PCMCIA_SYSTEM,用于在两者之间进行选择。它可以设置为 ``kernel`` 或 ``external``。

要查找 SuSE 支持数据库中当前的 PCMCIA 问题,请访问 http://sdb.suse.de/cgi-bin/sdbsearch_en.cgi?stichwort=PCMCIA


3. 解决安装和配置问题

本节介绍 PCMCIA 子系统一些最常见的故障模式。尝试将您的症状与示例进行匹配。本节仅介绍非特定于特定客户端驱动程序或卡类型的常见故障。

在尝试诊断问题之前,您必须知道系统日志的保存位置(请参阅 关于特定 Linux 发行版的说明)。您还应该熟悉基本的诊断工具,如 dmesglsmod。此外,请注意,大多数驱动程序组件(包括所有内核模块)都有自己的手册页。

在 3.1.15 及更高版本中,PCMCIA 源代码树的 debug-tools 子目录中有一些脚本,可以帮助诊断一些最常见的配置问题。test_setup 脚本检查您的 PCMCIA 安装是否完整。test_networktest_modem 脚本将尝试诊断 PCMCIA 网络卡和调制解调器卡的问题。如果您不熟悉 Linux 并且不确定如何处理问题,这些脚本可能特别有用。

尝试尽可能缩小您的问题范围。如果您有多个卡,请尝试单独测试每个卡,以及不同的组合。尝试冷启动 Linux,以及从 Windows 热启动。比较插入卡启动与启动后插入卡。如果您通常使用笔记本电脑扩展坞,请尝试不使用扩展坞。有时,两个插槽的行为会有所不同。

对于调试设备配置文件中的问题,使用 ``-v`` 选项启动 cardmgr 可能很有用。对于 3.1.23 或更高版本的 PCMCIA 软件包,这将导致大多数重要的脚本操作记录在系统日志中。

尝试通过 PCMCIA 设备安装 Linux 时遇到的驱动程序问题几乎不可能调试。即使您可以根据症状识别问题,安装盘也很难修改,尤其是在无法访问正在运行的 Linux 系统的情况下。安装盘的自定义完全取决于 Linux 发行版的选择,并且超出了本文档的范围。一般来说,最好的做法是使用其他方式安装 Linux,获取最新的驱动程序,然后调试持续存在的问题。

3.1 基础 PCMCIA 内核模块未加载

症状

内核模块包含版本信息,该信息在加载模块时会针对当前内核进行检查。检查类型取决于 CONFIG_MODVERSIONS 内核选项的设置。如果为 false,则内核版本号将编译到每个模块中,并且 insmod 会检查这是否与正在运行的内核匹配。如果 CONFIG_MODVERSIONS 为 true,则内核导出的每个符号都会被赋予一种校验和。这些代码都会与编译到模块中的相应代码进行比较。其目的是使模块对版本的依赖性降低,因为只有在内核接口发生更改时校验和才会更改,并且通常在次要内核更新中保持不变。但在实践中,事实证明校验和的限制性甚至更强,因为许多内核接口都依赖于编译时内核选项设置。此外,事实证明校验和对兼容性的判断过于悲观。

实际结果是,内核模块与内核版本以及许多内核配置选项的设置紧密相关。通常,为某个 2.2.19 内核编译的一组模块将无法加载到另一个 2.2.19 内核上,除非特别注意确保两者使用相似的配置构建。这使得预编译内核模块的发布成为一项棘手的业务。

您有几个选项

3.2 某些客户端驱动程序模块未加载

症状

一些驱动程序模块需要内核服务,这些服务可能存在也可能不存在,具体取决于内核配置。例如,SCSI 卡驱动程序要求内核配置了 SCSI 支持,而网络驱动程序需要网络内核。如果内核缺少必要的功能,insmod 可能会报告未定义的符号并拒绝加载特定模块。请注意,insmod 错误消息不会区分版本不匹配错误和缺少符号错误。

具体来说

有两种方法可以继续

/etc/pcmcia/config 文件可以指定需要为特定客户端加载的附加模块。例如,对于串行驱动程序,可以使用

device "serial_cs"
  class "serial" module "misc/serial", "serial_cs"

模块路径相对于当前内核版本的顶级模块目录指定;如果未给出相对路径,则路径默认为 pcmcia 子目录。

3.3 ISA 中断扫描失败

症状

在识别主机控制器类型后,套接字驱动程序会探测空闲的 ISA 总线中断。探测包括为每个表面上空闲的中断编程控制器,然后生成“软”中断,以查看是否可以正确检测到中断。在某些情况下,探测特定中断可能会干扰另一个系统设备。

探测的原因是识别看似空闲的中断(即,未被任何其他 Linux 设备驱动程序保留),但要么未物理连接到主机控制器,要么连接到另一个没有驱动程序的设备。

在系统日志中,成功的探测可能如下所示

Intel PCIC probe:
  TI 1130 CardBus at mem 0x10211000, 2 sockets
  ...
  ISA irqs (scanned) = 5,7,9,10 status change on irq 10

有两种方法可以继续

在任何一种情况下,都可以使用 PCMCIA 启动脚本中的 PCIC_OPTS 定义来指定探测选项,例如

PCIC_OPTS="irq_list=5,9,10"

应该注意的是,在诊断中断探测问题时,/proc/interrupts 完全无用。探测足够明智,永远不会尝试使用已被另一个 Linux 驱动程序使用的中断。因此,PCMCIA 驱动程序已经使用了 /proc/interrupts 中的所有信息。根据系统设计,如果探测到不活动的设备,它仍然会占用中断并引起问题。

3.4 IO 端口扫描失败

症状

cardmgr 处理 /etc/pcmcia/config.opts 中列出的 IO 端口范围时,内核会探测这些范围以检测占用 IO 空间但未与 Linux 驱动程序关联的潜在设备。探测是只读的,但在极少数情况下,从设备读取可能会干扰重要的系统功能,从而导致锁定。

您的系统用户指南可能包含系统设备映射,显示其 IO 和内存范围。这些可以在 config.opts 中显式排除。

或者,如果探测在您的系统上不可靠,可以通过将 CORE_OPTS 设置为 ``probe_io=0`` 来禁用它。在这种情况下,您应该非常小心,在 config.opts 中仅指定真正可用的端口范围,而不是使用默认设置。

3.5 内存探测失败

症状

或者交替

核心模块在首次插入 16 位卡时执行内存扫描。此扫描可能会干扰其他内存映射设备。此外,3.0.0 之前的驱动程序包执行的扫描比更新的驱动程序更具侵略性。内存窗口在 /etc/pcmcia/config.opts 中定义。默认窗口很大,因此将扫描限制在较窄的范围内可能会有所帮助。要尝试的合理范围包括 0xd0000-0xdffff、0xc0000-0xcffff、0xc8000-0xcffff 或 0xd8000-0xdffff。

如果您有 DOS 或 Windows PCMCIA 驱动程序,您或许可以推断出这些驱动程序使用的内存区域。请注意,DOS 内存地址通常以“段”形式指定,这会省略最后一个十六进制数字(因此 0xd0000 的绝对地址可能给出为 0xd000)。在更改 config.opts 时,请务必添加额外的数字。

更改影响设备映射方式的 BIOS 设置有时可能很有用。尝试更改 BIOS 阴影或“即插即用操作系统支持”的设置。

在不常见的情况下,内存探测失败可能表明主机控制器的时序寄存器设置存在问题。有关处理常见时序问题的信息,请参阅 启动选项 部分。这实际上仅适用于 ISA 到 PCMCIA 总线桥。

CardBus 桥可以在 ISA 总线架构中 640KB-1MB 的“内存空洞”之外分配内存窗口。通常,将 CardBus 桥配置为使用高内存窗口是一个好主意,因为这些窗口不太可能与其他设备冲突。此外,CardBus 卡可能需要较大的内存窗口,这可能难以或不可能放入低内存中。如果 config.opts 中同时定义了低内存窗口和高内存窗口,则 Card Services 将优先为 CardBus 桥分配高内存窗口。默认的 config.opts 包含多个候选高内存窗口,其中一个将在大多数情况下有效。

3.6 未能检测到卡插入和移除

症状

在大多数情况下,套接字驱动程序(i82365tcic)将自动探测并选择适当的中断来指示卡状态更改。自动中断探测在某些 Intel 兼容控制器上不起作用,包括 Cirrus 芯片和某些 IBM ThinkPad 中使用的芯片。如果设备在探测时处于非活动状态,则其中断也可能显示为可用。在这些情况下,套接字驱动程序可能会选择另一个设备使用的中断。

对于 i82365tcic 驱动程序,irq_list 选项可用于限制将要测试的中断。此列表限制了 PCMCIA 卡以及用于监视卡状态更改的中断集。cs_irq 选项也可用于显式设置用于监视卡状态更改的中断。

如果您找不到可用的中断号,还有一种轮询状态模式:i82365tcic 都接受 poll_interval=100 选项,以每秒轮询一次卡状态更改。如果您的系统缺少可供 PCMCIA 卡使用的中断,也应该使用此选项。特别是对于具有多个主机控制器的系统,为监视卡状态更改而专门分配中断意义不大。

所有这些选项都应在 PCIC_OPTS= 行中设置,该行位于 /etc/rc.d/rc.pcmcia/etc/sysconfig/pcmcia 中,具体取决于您的站点设置。

3.7 中断传递问题

症状

最简单的中断传递问题是由于与其他系统设备冲突造成的。这些问题通常可以通过在 /etc/pcmcia/config.opts 中排除问题中断来解决。要测试,只需逐个排除中断,直到问题得到解决或您用完中断为止。如果没有中断工作,则设备冲突可能不是问题所在。

对于 CardBus 桥,可能会出现各种其他中断传递问题。有关完整讨论,请参阅 PCI 中断传递问题

3.8 系统资源匮乏

症状

中断饥饿通常表明中断探测存在问题(请参阅 中断扫描失败)。在某些情况下,探测似乎可以工作,但仅报告一个或两个可用的中断。检查您的系统日志以查看扫描结果是否看起来合理。禁用探测并手动选择中断应该会有所帮助。

如果中断探测无法正常工作,则套接字驱动程序可能会分配一个中断来监视卡插入,即使中断太少而不适合这样做。您可以通过将 PCIC_OPTS 设置为 ``poll_interval=100`` 将控制器切换到轮询模式。或者,如果您有 CardBus 控制器和旧版本的 PCMCIA 驱动程序,请尝试 ``pci_csc=1``,这将选择一个 PCI 中断(如果可用)用于卡状态更改。

在某些情况下,内核配置错误也可能导致明显的中断短缺。在 2.4 及更高版本的内核上,如果未启用 CONFIG_ISA,则 PCMCIA 驱动程序将假定没有可用的 ISA 总线中断。

IO 端口饥饿相当罕见,但有时会发生在需要大片连续、对齐的 IO 端口空间,或者仅识别少数特定 IO 端口位置的卡上。/etc/pcmcia/config.opts 中的默认 IO 端口范围通常足够,但可以扩展。如果这是问题所在,请尝试取消注释 config.opts 中的 ``include port 0x1000-0x17ff`` 行。在极少数情况下,饥饿可能表明 IO 端口探测失败(请参阅 IO 端口扫描失败)。

内存饥饿在 config.opts 中的默认内存窗口设置下也很少见。CardBus 卡可能比典型的 16 位卡需要更大的内存区域。由于 CardBus 内存窗口可以映射到主机 PCI 地址空间的任何位置(而不仅仅是 PC 系统中的 640K-1MB“空洞”中),因此在高内存中指定大的内存窗口很有帮助,例如 0xa0000000-0xa0ffffff。

3.9 仅在插入两张卡时发生资源冲突

症状

这通常表明与 Linux 不知道的系统设备存在资源冲突。PCMCIA 设备是动态配置的,因此,例如,中断是根据需要分配的,而不是专门分配给特定卡或插槽。给定看似可用的资源列表,卡按照配置顺序分配资源。在这种情况下,最后配置的卡被分配的资源实际上不是空闲的。

检查系统日志以查看未工作的卡使用了哪些资源。在 /etc/pcmcia/config.opts 中排除这些资源,然后重新启动 cardmgr 守护程序以重新加载资源数据库。

3.10 设备配置未完成

症状

这表明卡已成功识别,但是,cardmgr 由于某种原因无法完成配置过程。最可能的原因是卡设置脚本中的某个步骤被阻止。一个很好的例子是,如果插入了没有实际网络连接的网络卡,则网络脚本会被阻止。

要查明问题,您可以手动运行设置脚本以查看它在哪里被阻止。脚本位于 /etc/pcmcia 目录中。它们采用两个参数:设备名称和操作。cardmgr 守护程序将配置命令记录在系统日志中。例如,如果系统日志显示命令 ``./network start eth0`` 是 cardmgr 执行的最后一个命令,则以下命令将跟踪脚本

sh -x /etc/pcmcia/network start eth0


4. 用法和功能

4.1 用于配置和监控 PCMCIA 设备的工具

如果所有模块都已正确加载,则在未插入卡时,lsmod 命令的输出应如下所示

Module                  Size  Used by
ds                      5640   2 
i82365                 15452   2 
pcmcia_core            30012   3  [ds i82365]

系统日志还应包含来自套接字驱动程序的输出,描述找到的主机控制器和检测到的插槽数量。

cardmgr 配置守护进程

cardmgr 守护进程负责监视 PCMCIA 插槽,在需要时加载客户端驱动程序,以及响应卡插入和移除运行用户级脚本。它将其操作记录在系统日志中,但也使用提示音来指示卡状态更改。提示音的音调指示特定配置步骤的成功或失败。两声高音提示音表示卡已成功识别和配置。一声高音提示音后跟一声低音提示音表示卡已识别,但由于某种原因无法配置。一声低音提示音表示卡无法识别。

cardmgr 守护进程根据保存在 /etc/pcmcia/config 中的已知卡类型数据库配置卡。此文件描述了各种客户端驱动程序,然后描述了如何识别各种卡,以及哪些驱动程序属于哪些卡。pcmcia(5) 手册页中描述了此文件的格式。

套接字状态文件 stab

Cardmgr 将每个插槽的设备信息记录在 /var/lib/pcmcia/stab 中。以下是 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

对于描述设备的行,第一个字段是插槽,第二个字段是设备类,第三个字段是驱动程序名称,第四个字段用于编号与同一驱动程序关联的多个设备,第五个字段是设备名称,最后两个字段是此设备的主设备号和次设备号(如果适用)。有关更多信息,请参阅 stab 手册页。

在 2.4 及更高版本的内核中,CardBus 卡的热插拔 PCI 驱动程序不由 cardmgr 管理;它们由 hotplug 子系统管理。有关此功能的更多信息,请参阅 http://linux-hotplug.sourceforge.net。当 cardmgr 看到由热插拔 PCI 驱动程序拥有的卡时,它将忽略该卡。当插入或弹出这些卡时,会听到一声提示音,但它们在系统日志和 stab 文件中仅被识别为“CardBus 热插拔设备”。

cardctl 和 cardinfo 实用程序

cardctl 命令可用于检查插槽的状态,或查看其配置方式。它也可用于更改卡的配置状态。以下是 ``cardctl config`` 命令输出的示例

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: 0x02f8 to 0x02ff, 8 bit

或 ``cardctl ident``,以获取卡识别信息

Socket 0:
  no product info available
Socket 1:
  product info: "LINKSYS", "PCMLM336", "A", "0040052D6400"
  manfid: 0x0143, 0xc0ab
  function: 0 (multifunction)

``cardctl suspend`` 和 ``cardctl resume`` 命令可用于关闭卡,而无需卸载其关联的驱动程序。``cardctl reset`` 命令尝试重置和重新配置卡。``cardctl insert`` 和 ``cardctl eject`` 模拟物理插入或弹出卡时执行的操作,包括加载或卸载驱动程序,以及配置或关闭设备。

如果您正在运行 X,则 cardinfo 实用程序会生成一个图形显示,显示所有 PCMCIA 插槽的当前状态,内容类似于 ``cardctl config``。它还为大多数其他 cardctl 功能提供图形界面。

插入和弹出卡

理论上,您可以随时插入和移除 PCMCIA 卡。但是,最好不要弹出应用程序程序当前正在使用的卡。1.1.77 之前的内核在弹出串行/调制解调器卡时经常会锁定,但这现在应该已修复。

某些卡类型无法安全地热弹出。具体来说,ATA/IDE 和 SCSI 接口卡不是热插拔安全的。这不太可能得到修复,因为完整的解决方案需要对 Linux 块设备模型进行重大更改。此外,通常热弹出任何类型的 CardBus 卡都不安全。随着 CardBus 驱动程序中的热插拔错误被发现和修复,这种情况可能会逐渐改善。对于这些卡类型(IDE、SCSI、CardBus),建议您始终在弹出之前使用 ``cardctl eject``。

Card Services 和高级电源管理

如果您已配置内核以支持 APM,则可以使用 APM(高级电源管理)支持编译 Card Services。APM 内核驱动程序由 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au) 维护。apmd 守护程序由 Avery Pennarun (apenwarr@worldvisions.ca) 维护,有关更多信息,请访问 http://www.worldvisions.ca/~apenwarr/apmd/。如果在您的系统上检测到兼容版本,PCMCIA 模块将自动配置为 APM。

无论是否配置了 APM,您都可以在挂起笔记本电脑之前使用 ``cardctl suspend``,并在恢复后使用 ``cardctl resume``,以干净地关闭和重启 PCMCIA 卡。这不适用于正在使用的调制解调器,因为串行驱动程序无法保存和恢复调制解调器操作参数。

APM 在某些系统上似乎不稳定。如果您在系统上遇到 APM 和 PCMCIA 方面的麻烦,请在报告错误之前尝试将问题缩小到其中一个软件包。

某些驱动程序,尤其是 PCMCIA SCSI 驱动程序,无法从挂起/恢复周期中恢复。使用 PCMCIA SCSI 卡时,请始终在挂起系统之前使用 ``cardctl eject``。

关闭 PCMCIA 系统

要卸载整个 PCMCIA 软件包,请使用以下命令调用 rc.pcmcia

/etc/rc.d/rc.pcmcia stop

此脚本将运行几秒钟,以便为所有客户端驱动程序提供足够的时间来正常关闭。如果设备当前正在使用,则关闭将不完整,并且某些内核模块可能无法卸载。为避免这种情况,请在调用 rc.pcmcia 之前使用 ``cardctl eject`` 关闭所有插槽。cardctl 命令的退出状态将指示是否有任何插槽无法关闭。

4.2 PCMCIA 配置文件概述

以下信息适用于由 cardmgr 管理的卡。在 2.4 及更高版本的内核中,如果内核 PCMCIA 子系统处于活动状态,则 CardBus 卡由 hotplug 子系统管理,并且不使用 PCMCIA 脚本。

每个 PCMCIA 设备都有一个关联的“类”,用于描述应如何配置和管理它。类在 /etc/pcmcia/config 中与设备驱动程序关联。当前有五个 IO 设备类(网络、SCSI、cdrom、固定磁盘和串行)和两个内存设备类(内存和 FTL)。对于每个类,/etc/pcmcia 中都有两个脚本:主配置文件(例如,SCSI 设备的 /etc/pcmcia/scsi)和一个选项脚本(例如,/etc/pcmcia/scsi.opts)。当插入卡时,将调用设备的main脚本来配置该设备,并在移除卡时关闭设备。对于具有多个关联设备的卡,将为每个设备调用该脚本。

config 脚本首先从 stab 文件中提取有关设备的一些信息。每个脚本都构造一个“设备地址”,该地址在 ADDRESS shell 变量中唯一地描述了已被要求配置的设备。这会传递给 *.opts 脚本,该脚本应返回有关应如何配置此地址的设备的信息。对于某些设备,设备地址只是插槽号。对于其他设备,它包括可用于决定如何配置设备的额外信息。例如,网络设备将其硬件以太网地址作为设备地址的一部分传递,因此 network.opts 脚本可以使用它从几种不同的配置中进行选择。

所有设备地址的第一部分是当前的 PCMCIA“方案”。此参数用于支持基于单个外部用户指定变量的多组设备配置。方案的一种用途是拥有“家庭”方案和“工作”方案,这将包括不同的网络配置参数集。当前方案使用 ``cardctl scheme`` 命令选择。如果未设置方案,则默认为“default”。

除了 ADDRESS 之外,*.opts 文件中还可以使用一些其他 shell 变量

SOCKETCLASSDRIVERINSTANCEDEVICEMAJORMINOR

这些对应于 stab 文件中一行中的各个字段。有关详细信息,请参阅其手册页。

PRODID_1PRODID_2PRODID_3PRODID_4MANFIDFUNCID

这些等效于 ``cardctl info`` 的输出,并提供更详细的卡识别信息。

由于 *.opts 文件只是 shell 脚本,因此不要求它们遵循示例的形式,示例只是返回基于 ADDRESS 的设置。

作为一般规则,在为笔记本电脑配置 Linux 时,PCMCIA 设备应仅通过 PCMCIA 设备脚本进行配置。请勿尝试以配置永久连接设备的方式配置 PCMCIA 设备。然而,一些 Linux 发行版提供了与这些发行版自身的设备配置工具挂钩的 PCMCIA 软件包。在这种情况下,以下某些章节可能不适用;理想情况下,这将由发行版维护者记录在案。

4.3 PCMCIA 网络适配器

Linux 以太网类型的网络接口通常具有诸如 eth0eth1 等名称。令牌环适配器也以类似方式处理,但它们被命名为 tr0tr1 等。ifconfig 命令用于查看或修改网络接口的状态。Linux 的一个特点是网络接口在 /dev 下没有对应的设备文件,因此当您找不到它们时,请不要感到惊讶。

当检测到以太网卡时,它将被分配第一个可用的接口名称,通常为 eth0Cardmgr 将运行 /etc/pcmcia/network 脚本来配置接口,该脚本通常从 /etc/pcmcia/network.opts 读取网络设置。networknetwork.opts 脚本仅在您的以太网卡实际存在时执行。如果您的系统具有自动网络配置功能,它可能或可能不感知 PCMCIA。请查阅您的 Linux 发行版的文档和 关于特定 Linux 发行版的说明,以确定 PCMCIA 网络设备应使用自动工具配置,还是通过编辑 network.opts 配置。

传递给 network.opts 的设备地址由四个逗号分隔的字段组成:方案、插槽号、设备实例和网卡的硬件以太网地址。设备实例用于为具有多个网络接口的网卡编号设备,因此通常为 0。如果您有多个用于不同用途的网卡,一种选择是根据插槽位置配置网卡,如下所示:

case "$ADDRESS" in
*,0,*,*)
    # definitions for network card in socket 0
    ;;
*,1,*,*)
    # definitions for network card in socket 1
    ;;
esac

或者,可以使用其硬件地址进行配置,如下所示:

case "$ADDRESS" in
*,*,*,00:80:C8:76:00:B1)
    # definitions for a D-Link card
    ;;
*,*,*,08:00:5A:44:80:01)
    # definitions for an IBM card
esac

网络设备参数

以下参数可以在 network.opts 中定义

IF_PORT

指定以太网收发器类型,适用于某些不自动检测的 16 位网卡。有关更多信息,请参阅 ``man ifport'' 和 ``man mii-tool''。

BOOTP

一个布尔值 (y/n):指示是否应使用 BOOTP 协议通过 bootpcpump 获取主机的 IP 地址和路由信息。

DHCP

一个布尔值 (y/n):指示是否应从 DHCP 服务器获取主机的 IP 地址和路由信息。网络脚本首先查找 dhcpcd,然后查找 dhclient,然后查找 pump

DHCP_HOSTNAME

指定要传递给 dhcpcdpump 的主机名,以便包含在 DHCP 消息中。

IPADDR

此接口的 IP 地址。

NETMASK, BROADCAST, NETWORK

基本网络参数:有关更多信息,请参阅 networking HOWTO。

GATEWAY

此主机子网的网关的 IP 地址。目标地址超出此子网的数据包将被路由到此网关。

DOMAIN

此主机的本地网络域名,用于创建 /etc/resolv.conf

SEARCH

用于主机名查找的搜索列表,将添加到 /etc/resolv.confDOMAINSEARCH 是互斥的:有关更多信息,请参阅 ``man resolver''。

DNS_1, DNS_2, DNS_3

此接口的域名服务器的主机名或 IP 地址,将添加到 /etc/resolv.conf

MOUNTS

要为此接口挂载的 NFS 挂载点的空格分隔列表。

IPX_FRAME, IPX_NETNUM

对于 IPX 网络:帧类型和网络号,传递给 ipx_interface 命令。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果设置了 NO_CHECK,则即使存在打开的连接,``cardctl eject'' 也会关闭设备。如果设置了 NO_FUSER,则脚本将不会检查繁忙的 NFS 挂载或终止使用这些挂载的进程。

例如

case "$ADDRESS" in
*,*,*,*)
    IF_PORT="10base2"
    BOOTP="n"
    IPADDR="10.0.0.1"
    NETMASK="255.255.255.0"
    NETWORK="10.0.0.0"
    BROADCAST="10.0.0.255"
    GATEWAY="10.0.0.1"
    DOMAIN="domain.org"
    DNS_1="dns1.domain.org"
    ;;
esac

要自动挂载和卸载 NFS 文件系统,请首先将所有这些文件系统添加到 /etc/fstab,但在挂载选项中包含 noauto。在 network.opts 中,在 MOUNTS 变量中列出文件系统挂载点。当 NFS 挂载处于活动状态时,使用 cardctlcardinfo 关闭网卡尤为重要。如果只是在没有警告的情况下弹出网卡,则无法干净地卸载 NFS 文件系统。

除了通常的网络配置参数外,network.opts 脚本还可以指定在配置接口后或在关闭接口之前要采取的额外操作。如果 network.opts 定义了一个名为 start_fn 的 shell 函数,则网络脚本将在配置接口后调用它,并将接口名称作为其第一个(也是唯一的)参数传递给该函数。同样,如果定义了 stop_fn,则在关闭接口之前将调用它。

某些(主要是旧的)网卡的收发器类型必须使用 IF_PORT 设置手动选择。这可以是数值,也可以是标识收发器类型的关键字。所有网络驱动程序默认情况下都会自动检测接口(如果可能),否则默认为 10baseT。ifport 命令可用于检查或设置当前的收发器类型。例如

# ifport eth0 10base2
# 
# ifport eth0
eth0    2 (10base2)

大多数现代 10/100baseT 网卡都使用“媒体独立接口”(MII) 收发器,该收发器自动选择线路速度和双工设置。mii-tool 命令可用于监视和控制 MII 接口的行为。

关于特定网卡的注释

诊断网络适配器问题

4.4 PCMCIA 串行和调制解调器设备

Linux 串行设备通过 /dev/ttyS*/dev/cua* 特殊设备文件访问。在 2.2 之前的内核中,ttyS* 设备用于传入连接,例如直接连接的终端,而 cua* 设备用于传出连接,例如调制解调器。在当前内核中,不建议使用 cua* 设备,并且 ttyS* 可用于所有应用程序。可以使用 setserial 命令检查和修改串行设备的配置。

当检测到串行卡或调制解调器卡时,它将被分配到第一个可用的串行设备插槽。这通常是 /dev/ttyS1 (cua1) 或 /dev/ttyS2 (cua2),具体取决于内置串行端口的数量。ttyS* 设备是在 stab 中报告的设备。默认的串行设备选项脚本 /etc/pcmcia/serial.opts 会将设备文件链接到 /dev/modem 以方便使用。对于 2.2 之前的内核,链接将链接到 cua* 设备。

请勿尝试使用 /etc/rc.d/rc.serial 配置 PCMCIA 调制解调器。此脚本应仅用于配置不可移动设备。如果您想对设置调制解调器执行任何特殊操作,请修改 /etc/pcmcia/serial.opts。此外,请勿尝试使用 setserial 更改串行设备的 IO 端口和中断设置。这将告诉串行驱动程序在不同的位置查找设备,但不会更改网卡硬件的实际配置方式。串行配置脚本允许您指定其他 setserial 选项,以及是否应为此端口将行添加到 /etc/inittab

传递给 serial.opts 的设备地址具有三个逗号分隔的字段:第一个是方案,第二个是插槽号,第三个是设备实例。设备实例可以为支持多个串行端口的网卡采用多个值,但对于单端口网卡,它始终为 0。如果您通常使用多个调制解调器,您可能希望根据插槽位置指定不同的设置,如下所示:

case "$ADDRESS" in
*,0,*)
    # Options for modem in socket 0
    LINK=/dev/modem0
    ;;
*,1,*)
    # Options for modem in socket 1
    LINK=/dev/modem1
    ;;
esac

如果在 Linux 启动时已配置 PCMCIA 调制解调器,则可能会错误地将其识别为普通的内置串行端口。这是无害的,但是,当 PCMCIA 驱动程序控制调制解调器时,它将被分配不同的设备插槽。最好解析 stab 或使用 /dev/modem,而不是期望 PCMCIA 调制解调器始终具有相同的设备分配。

如果您将内核配置为将基本 Linux 串行端口驱动程序作为模块加载,则必须编辑 /etc/pcmcia/config 以指示必须加载此模块。编辑串行设备条目以读取

device "serial_cs"
  class "serial" module "misc/serial", "serial_cs"

串行设备参数

以下参数可以在 serial.opts 中定义

LINK

指定要为“呼出”设备创建的符号链接的路径(例如,对于 2.2 之前,为 /dev/cua*,或对于 2.2 内核,为 /dev/ttyS*)。

SERIAL_OPTS

指定要传递给 setserial 命令的选项。

INITTAB

如果指定,这将用于为此设备构造 inittab 条目。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果 NO_CHECK 为 true,则即使设备繁忙,``cardctl eject'' 也会关闭设备。如果 NO_FUSER 为 true,则脚本将不会尝试终止使用弹出设备的进程。

例如

case "$ADDRESS" in
*,*,*)
    LINK="/dev/modem"
    SERIAL_OPTS=""
    INITTAB="/sbin/getty"

关于特定网卡的注释

诊断串行设备问题

4.5 PCMCIA 并行端口设备

Linux 并行端口驱动程序是分层的,以便多个高级设备类型可以共享使用同一个低级端口驱动程序。打印机设备通过 /dev/lp* 特殊设备文件访问。可以使用 tunelp 命令检查和修改打印机设备的配置。

parport_cs 模块依赖于 parportparport_pc 驱动程序,这些驱动程序可以编译到内核中,也可以编译为模块。分层驱动程序结构意味着任何顶层并行驱动程序(例如 plip 驱动程序、打印机驱动程序等)都必须编译为模块。这些驱动程序仅在模块启动时识别并行端口设备,因此需要在配置任何 PC Card 并行设备后加载它们。

传递给 parport.opts 的设备地址具有三个逗号分隔的字段:第一个是方案,第二个是插槽号,第三个是设备实例。设备实例可以为支持多个并行端口的网卡采用多个值,但对于单端口网卡,它始终为 0。如果您通常使用多个此类网卡,您可能希望根据插槽位置指定不同的设置,如下所示:

case "$ADDRESS" in
*,0,*)
    # Options for card in socket 0
    LINK=/dev/printer0
    ;;
*,1,*)
    # Options for card in socket 1
    LINK=/dev/printer1
    ;;
esac

并行设备参数

以下参数可以在 parport.opts 中定义

LINK

指定要为打印机端口创建的符号链接的路径。

LP_OPTS

指定要传递给 tunelp 命令的选项。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果 NO_CHECK 为 true,则即使设备繁忙,``cardctl eject'' 也会关闭设备。如果 NO_FUSER 为 true,则脚本将不会尝试终止使用弹出设备的进程。

例如

case "$ADDRESS" in
*,*,*,*)
    LINK="/dev/printer"
    LP_OPTS=""

诊断并行端口设备问题

4.6 PCMCIA SCSI 适配器

当前所有受支持的 PCMCIA SCSI 卡都是以下 ISA 总线卡之一的仿制品:Qlogic、Adaptec AHA-152X 或 Future Domain TMC-16x0。PCMCIA 驱动程序是通过将一些 PCMCIA 特定的代码(在 qlogic_cs.caha152x_cs.cfdomain_cs.c 中)与从 Linux 内核源代码树中提取的普通 Linux SCSI 驱动程序链接而构建的。Adaptec APA1480 CardBus 驱动程序基于内核 aic7xxx PCI 驱动程序。由于 Linux SCSI 驱动程序模型的限制,每个驱动程序仅支持一张可移动卡。

当检测到新的 SCSI 主机适配器时,SCSI 驱动程序将探测设备。检查系统日志,确保您的设备被正确检测到。新的 SCSI 设备将被分配给第一个可用的 SCSI 设备文件。第一个 SCSI 磁盘将是 /dev/sda,第一个 SCSI 磁带将是 /dev/st0,第一个 CD-ROM 将是 /dev/scd0

连接到此主机适配器的 SCSI 设备列表将显示在 stab 中,并且 SCSI 配置脚本 /etc/pcmcia/scsi 将为每个连接的设备调用一次,以配置或关闭该设备。默认脚本不采取任何操作来配置 SCSI 设备,但在移除网卡时会正确卸载 SCSI 设备上的文件系统。

传递给 scsi.opts 的设备地址很复杂,因为可以连接到 SCSI 适配器的东西种类繁多。地址由六个或七个逗号分隔的字段组成:当前方案、设备类型、插槽号、SCSI 通道、ID 和逻辑单元号,以及可选的分区号。设备类型对于磁盘将为“sd”,对于磁带将为“st”,对于 CD-ROM 设备将为“sr”,对于通用 SCSI 设备将为“sg”。对于大多数设置,SCSI 通道和逻辑单元号将为 0。对于具有多个分区的磁盘设备,将首先为整个设备调用 scsi.opts,地址为五个字段。脚本应将 PARTS 变量设置为分区列表。然后,将为每个分区调用 scsi.opts,地址为较长的六个字段。

如果您的内核没有特定 SCSI 设备的顶层驱动程序(磁盘、磁带等),则 PCMCIA 驱动程序将不会配置该设备。作为副作用,设备在 stab 中的名称将类似于 “sd#nnnn”,其中 “nnnn” 是一个四位十六进制数。当 cardmgr 无法将 SCSI 设备 ID 转换为相应的 Linux 设备名称时,就会发生这种情况。

可以模块化顶层 SCSI 驱动程序,以便按需加载它们。为此,您需要编辑 /etc/pcmcia/config 以告诉 cardmgr 在配置适配器时需要加载哪些额外的模块。例如

device "aha152x_cs"
  class "scsi" module "scsi/scsi_mod", "scsi/sd_mod", "aha152x_cs"

将表示在加载常规 PCMCIA 驱动程序模块之前,加载核心 SCSI 模块和顶层磁盘驱动程序模块。

始终在启动笔记本电脑之前或在插入适配器卡之前打开 SCSI 设备,以便在配置适配器时正确终止 SCSI 总线。还要非常小心地弹出 SCSI 适配器。确保在弹出网卡之前卸载并关闭所有关联的 SCSI 设备。确保这一点的最佳方法是使用 cardctlcardinfo 请求移除网卡,然后再物理弹出网卡。目前,所有 SCSI 设备都应在插入 SCSI 适配器之前通电,并应保持连接状态,直到您拔下适配器和/或关闭笔记本电脑电源之后。

使用这些网卡时,存在一个潜在的复杂情况,这在普通的 ISA 总线适配器中不会出现。SCSI 总线带有 “终止电源” 信号,这对于普通被动 SCSI 终端电阻器的正常运行是必需的。PCMCIA SCSI 适配器不提供终止电源,因此如果需要,外部设备必须提供它。某些外部 SCSI 设备可能被配置为提供终止电源。其他设备,例如 Zip Drive 和 Syquest EZ-Drive,使用不依赖于它的有源终端电阻器。在某些情况下,可能需要使用特殊的终端电阻器块,例如 APS SCSI Sentry 2,它具有外部电源。在配置 SCSI 设备链时,请注意您的任何设备是否需要或可以提供终止电源。

SCSI 设备参数

以下参数可以在 scsi.opts 中定义

LINK

指定要为此设备创建的符号链接的路径。

DO_FSTAB

一个布尔值 (y/n) 设置:指定是否应为此设备将条目添加到 /etc/fstab

DO_FSCK

一个布尔值 (y/n) 设置:指定是否应在使用 ``fsck -Ta'' 挂载文件系统之前检查文件系统。

DO_MOUNT

一个布尔值 (y/n) 设置:指定是否应在网卡插入时自动挂载此设备。

FSTYPE, OPTS, MOUNTPT

用于 fstab 条目和/或挂载设备的文件系统类型、挂载选项和挂载点。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果 NO_CHECK 为 true,则即使设备繁忙,``cardctl eject'' 也会关闭设备。如果 NO_FUSER 为 true,则脚本将不会尝试终止使用弹出设备的进程。

例如,这是一个用于配置 SCSI ID 为 3 的磁盘设备(带有两个分区)和 SCSI ID 为 6 的 CD-ROM 的脚本

case "$ADDRESS" in
*,sd,*,0,3,0)
    # This device has two partitions...
    PARTS="1 2"
    ;;
*,sd,*,0,3,0,1)
    # Options for partition 1:
    #  update /etc/fstab, and mount an ext2 fs on /usr1
    DO_FSTAB="y" ; DO_FSCK="y" ; DO_MOUNT="y"
    FSTYPE="ext2"
    OPTS=""
    MOUNTPT="/usr1"
    ;;
*,sd,*,0,3,0,2)
    # Options for partition 2:
    #  update /etc/fstab, and mount an MS-DOS fs on /usr2
    DO_FSTAB="y" ; DO_FSCK="y" ; DO_MOUNT="y"
    FSTYPE="msdos"
    OPTS=""
    MOUNTPT="/usr2"
    ;;
*,sr,*,0,6,0)
    # Options for CD-ROM at SCSI ID 6
    PARTS=""
    DO_FSTAB="y" ; DO_FSCK="n" ; DO_MOUNT="y"
    FSTYPE="iso9660"
    OPTS="ro"
    MOUNTPT="/cdrom"
    ;;
esac

关于特定网卡的注释

诊断 SCSI 适配器问题

4.7 PCMCIA 存储卡

memory_cs 驱动程序处理所有类型的存储卡,并为具有其他功能的网卡提供对 PCMCIA 内存地址空间的直接访问。加载后,它会创建字符设备和块设备的组合。有关设备命名方案的完整描述,请参阅模块的 man 页面。块设备用于类似磁盘的访问(创建和挂载文件系统等)。字符设备用于在任意位置进行“原始”无缓冲的读写操作。

传递给 memory.opts 的设备地址由两个字段组成:方案和插槽号。这些选项应用于相应存储卡上的第一个公共内存分区。

某些闪存卡和大多数简单的静态 RAM 卡缺少 “Card Information Structure”(CIS),这是 PCMCIA 卡用于识别自身的系统。通常,cardmgr 会假定任何缺少 CIS 的卡都是简单的存储卡,并加载 memory_cs 驱动程序。因此,通用网卡识别问题的常见副作用是其他类型的网卡可能会被错误地检测为存储卡。

在处理没有 CIS 信息的存储卡时,还需要考虑另一个问题。在启动时,PCMCIA 软件包尝试使用检测到的第一张网卡来确定哪些内存区域可用于 PCMCIA。如果该网卡是简单的存储卡,则内存扫描可能会被欺骗。如果您计划经常使用存储卡,最好将 /etc/pcmcia/config.opts 中的内存窗口限制为已知的良好区域。

memory_cs 驱动程序使用启发式方法来猜测这些网卡的容量。启发式方法不适用于写保护卡,并且在某些其他情况下也可能会出错。如果网卡被错误检测,则在使用诸如 ddmkfs 之类的命令时,应明确指定其大小。memory_cs 模块还具有一个用于覆盖大小检测的参数。请参阅 man 页面。

存储设备参数

以下参数可以在 memory.opts 中指定

DO_FSTAB

一个布尔值 (y/n) 设置:指定是否应为此设备将条目添加到 /etc/fstab

DO_FSCK

一个布尔值 (y/n) 设置:指定是否应在使用 ``fsck -Ta'' 挂载文件系统之前检查文件系统。

DO_MOUNT

一个布尔值 (y/n) 设置:指定是否应在网卡插入时自动挂载此设备。

FSTYPE, OPTS, MOUNTPT

用于 fstab 条目和/或挂载设备的文件系统类型、挂载选项和挂载点。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果 NO_CHECK 为 true,则即使设备繁忙,``cardctl eject'' 也会关闭设备。如果 NO_FUSER 为 true,则脚本将不会尝试终止使用弹出设备的进程。

这是一个脚本示例,该脚本将根据存储卡插入的插槽自动挂载存储卡

case "$ADDRESS" in
*,0,0)
    # Mount filesystem, but don't update /etc/fstab
    DO_FSTAB="n" ; DO_FSCK="y" ; DO_MOUNT="y"
    FSTYPE="ext2" ; OPTS=""
    MOUNTPT="/mem0"
    ;;
*,1,0)
    # Mount filesystem, but don't update /etc/fstab
    DO_FSTAB="n" ; DO_FSCK="y" ; DO_MOUNT="y"
    FSTYPE="ext2" ; OPTS=""
    MOUNTPT="/mem1"
    ;;
esac

使用线性闪存卡

以下信息仅适用于所谓的 “线性闪存” 存储卡。许多闪存卡,包括所有 SmartMedia 和 CompactFlash 卡,实际上都包含用于模拟 IDE 磁盘设备的电路。因此,这些卡被视为 IDE 设备,而不是存储卡。

闪存卡有两种主要格式:FTL 或 “闪存转换层” 样式,以及 Microsoft Flash File System。FTL 格式通常更灵活,因为它允许在闪存卡上使用任何普通的高级文件系统(ext2、ms-dos 等),就像它是普通的磁盘设备一样。FFS 是一种完全不同的文件系统类型。Linux 目前无法处理使用 FFS 格式化的卡。

要将闪存卡用作普通的类似磁盘的块设备,请首先使用 ftl_format 命令在设备上创建 FTL 分区。此层隐藏了闪存编程的设备特定细节,并使网卡看起来像一个简单的块设备。例如

ftl_format -i /dev/mem0c0c

请注意,此命令通过 “原始” 存储卡接口访问网卡。格式化后,可以通过 ftl_cs 驱动程序将网卡作为普通的块设备访问。例如

mke2fs /dev/ftl0c0
mount -t ext2 /dev/ftl0c0 /mnt

FTL 设备的设备命名很棘手。次设备号有三个部分:卡号、该卡上的区域号,以及可选的分区号。可以将区域视为没有分区表的单个块设备(如软盘),也可以像硬盘设备一样对其进行分区。“ftl0c0” 设备是卡 0,公共内存区域 0,整个区域。“ftl0c0p1” 到 “ftl0c0p4” 设备是区域已分区的主分区 1 到 4。

FTL 分区的配置选项可以在 ftl.opts 中给出,其结构类似于 memory.opts。传递给 ftl.opts 的设备地址由三个或四个字段组成:方案、插槽号、区域号,以及可选的分区号。大多数闪存卡只有一个闪存区域,因此区域号通常始终为零。

Intel Series 100 闪存卡使用第一个 128K 闪存块来存储网卡的配置信息。为了防止意外擦除此信息,ftl_format 将自动检测到这一点,并在创建 FTL 分区时跳过第一个块。

4.8 PCMCIA ATA/IDE 卡驱动器

ATA/IDE 驱动器支持基于常规内核 IDE 驱动程序。这包括 SmartMedia 和 CompactFlash 设备:这些闪存卡设置为模拟 IDE 接口。驱动程序的 PCMCIA 特定部分是 ide_cs。务必使用 cardctlcardinfo 在弹出 ATA/IDE 卡之前将其关闭,因为驱动程序尚未“热插拔”。

传递给 ide.opts 的设备地址由三个或四个字段组成:当前方案、插槽号、驱动器的序列号以及可选的分区号。ide_info 命令可用于获取 IDE 设备的序列号。与 SCSI 设备一样,首先为整个设备调用 ide.opts。如果 ide.optsPARTS 变量中返回分区列表,则脚本将为每个分区调用。

ATA/IDE 固定磁盘设备参数

以下参数可以在 ide.opts 中指定

DO_FSTAB

一个布尔值 (y/n) 设置:指定是否应为此设备将条目添加到 /etc/fstab

DO_FSCK

一个布尔值 (y/n) 设置:指定是否应在使用 ``fsck -Ta'' 挂载文件系统之前检查文件系统。

DO_MOUNT

一个布尔值 (y/n) 设置:指定是否应在网卡插入时自动挂载此设备。

FSTYPE, OPTS, MOUNTPT

用于 fstab 条目和/或挂载设备的文件系统类型、挂载选项和挂载点。

NO_CHECK, NO_FUSER

用于网卡弹出的布尔值 (y/n) 设置。如果 NO_CHECK 为 true,则即使设备繁忙,``cardctl eject'' 也会关闭设备。如果 NO_FUSER 为 true,则脚本将不会尝试终止使用弹出设备的进程。

这是一个示例 ide.opts 文件,用于将任何 ATA/IDE 卡的第一个分区挂载到 /mnt

case "$ADDRESS" in
*,*,*,1)
    DO_FSTAB="y" ; DO_FSCK="y" ; DO_MOUNT="y"
    FSTYPE="msdos"
    OPTS=""
    MOUNTPT="/mnt"
    ;;
*,*,*)
    PARTS="1"
    ;;
esac

诊断 ATA/IDE 适配器问题

4.9 多功能卡

一个中断可以被多个驱动程序共享,例如串行驱动程序和以太网驱动程序:事实上,PCMCIA 规范要求所有卡功能共享同一个中断。通常,所有卡功能都可用,而无需更换驱动程序。所有 Linux 内核都支持这种中断共享。

同时使用两个卡功能是“棘手的”,不同的硬件供应商以他们自己不兼容(有时甚至是专有的)方式实现了中断共享。某些卡(Ositech Jack of Diamonds、3Com 3c562 和相关卡、Linksys 卡)的驱动程序正确地支持同时访问,但其他卡(特别是较旧的 Megahertz 卡)则不支持。如果您在使用同时激活两个功能的卡时遇到问题,请尝试隔离使用每个功能。这可能需要显式地执行 “ifconfig down” 来关闭网络接口,并在同一张卡上使用调制解调器。


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,...

此参数列出了可用于 PCMCIA 的 ISA 中断。如果没有可用的 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 如何为家庭和工作设置单独的设备配置?

使用 “scheme” 支持可以很容易地做到这一点。使用两个配置方案,称为 “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 系统。在开始之前,请务必阅读所有相关文档。以下 cookbook 说明应该有效,但是偏离示例将很快使您进入未知的和 “不受支持” 的领域,您将需要自行解决。

此方法绝对要求您使用 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 设备文件。


6. 处理不支持的卡

6.1 配置无法识别的卡

假设您的卡受到现有驱动程序的支持,那么需要做的就是向 /etc/pcmcia/config 添加一个条目,以告知 cardmgr 如何识别该卡,以及需要将哪些驱动程序链接到该卡。有关配置文件格式的更多信息,请查看 pcmcia 的 man 手册。如果您插入一张未知的卡,cardmgr 通常会在系统日志中记录一些识别信息,这些信息可用于构造配置条目。此信息也可以使用 “cardctl ident” 命令显示。

以下是 cardmgr 将如何在系统日志中报告不支持的卡的示例

cardmgr[460]: unsupported card in socket 1
cardmgr[460]: product info: "MEGAHERTZ", "XJ2288", "V.34 PCMCIA MODEM"
cardmgr[460]: manfid: 0x0101, 0x1234  function: 2 (serial)

/etc/pcmcia/config 中相应的条目将是

card "Megahertz XJ2288 V.34 Fax Modem"
  version "MEGAHERTZ", "XJ2288", "V.34 PCMCIA MODEM"
  bind "serial_cs"

或使用更紧凑的产品 ID 代码

card "Megahertz XJ2288 V.34 Fax Modem"
  manfid 0x0101, 0x1234
  bind "serial_cs"

您可以使用 “*” 来匹配不需要完全匹配的字符串,例如版本号。在制作新的配置条目时,请注意完全复制字符串,保留大小写和空格。还要确保配置条目具有与日志文件中报告的字符串数量相同的字符串。

请注意,您可以为卡指定几乎任何驱动程序,但是如果您只是盲目尝试,则没有太多理由期望这样做会富有成效。您可能会幸运地发现您的卡受到现有驱动程序的支持。然而,最可能的结果是驱动程序无法工作,并且可能会产生不幸的副作用,例如锁定您的系统。与大多数普通的设备驱动程序(它们探测适当的卡)不同,PCMCIA 设备的探测是由 cardmgr 完成的,并且驱动程序本身在尝试与设备通信之前可能不会进行太多验证。

编辑 /etc/pcmcia/config 后,您可以向 cardmgr 发送信号以重新加载文件,使用

kill -HUP `cat /var/run/cardmgr.pid`

如果您确实为新卡设置了一个条目,请给我发送一份副本,以便我可以将其包含在标准配置文件中。

6.2 添加对 NE2000 兼容以太网卡的支持

在您开始之前:此过程仅适用于简单的 16 位以太网卡。多功能卡(即以太网/调制解调器组合卡)在两个功能的集成方式方面具有额外的复杂性,并且通常在没有从卡供应商处获得一些配置信息的情况下无法支持。对多功能卡使用以下过程不会有成效。

首先,查看卡是否已被 cardmgr 识别。SUPPORTED.CARDS 中未列出的某些卡实际上是受支持的卡的 OEM 版本。如果您找到这样的卡,请告诉我,以便我可以将其添加到列表中。

如果您的卡未被识别,请按照 配置无法识别的卡 部分中的说明为您的卡创建配置条目,并将卡绑定到 pcnet_cs 驱动程序。重新启动 cardmgr 以使用更新后的配置文件。

如果 pcnet_cs 驱动程序表示它无法确定您的卡的硬件以太网地址,则编辑您的新配置条目以将卡绑定到存储卡驱动程序 memory_cs。重新启动 cardmgr 以使用新的更新后的配置文件。您将需要知道您的卡的硬件以太网地址。此地址是一系列六个两位十六进制数字,通常印在卡本身上。如果它没有印在卡上,您可以使用 DOS 驱动程序来显示该地址。无论如何,一旦您知道它,请运行

dd if=/dev/mem0a count=20 | od -Ax -t x1

并在输出中搜索您的地址。仅定义了偶数字节,因此请忽略转储中的奇数字节。记录地址的第一个字节的十六进制偏移量。现在,编辑 clients/pcnet_cs.c 并找到 hw_info 结构。您需要为您的卡创建一个新条目。第一个字段是内存偏移量。接下来的三个字段是硬件地址的前三个字节。最后一个字段包含一些特定卡功能的标志;首先,尝试将其设置为 0。

编辑 pcnet_cs.c 后,编译并安装新模块。再次编辑 /etc/pcmcia/config,并将卡绑定从 memory_cs 更改为 pcnet_cs。按照说明重新加载配置文件,您应该一切顺利。请给我发送您的新 hw_info 和配置条目的副本。

如果您在十六进制转储中找不到您的卡的硬件地址,作为最后的手段,可以在初始化 pcnet_cs 模块时 “硬连线” 该地址。编辑 /etc/pcmcia/config.opts 并添加一个 hw_addr= 选项,如下所示

module "pcnet_cs" opts "hw_addr=0x00,0x80,0xc8,0x01,0x02,0x03"

当然,在适当的位置替换您自己的卡的硬件地址。请注意,如果您已经走到这一步,则您的卡不太可能真正与 NE2000 兼容。实际上,我不确定是否有任何卡没有通过前两种方法之一处理。

6.3 PCMCIA 软盘接口卡

Compaq Aero 和少数其他笔记本电脑中使用的 PCMCIA 软盘接口尚不受此软件包支持。支持 Aero 软盘的障碍在于 Aero 似乎使用定制的 PCMCIA 控制器来支持到软盘的 DMA。在不确切知道这是如何完成的情况下,没有任何方法可以在 Linux 下实现支持。

如果在 Aero 启动时软盘适配器卡存在,则 Aero BIOS 将配置该卡,并且 Linux 将其识别为普通软盘驱动器。当加载 Linux PCMCIA 驱动程序时,它们会注意到该卡已配置并连接到 Linux 驱动程序,并且此插槽将被保留。因此,如果驱动器在启动时存在,则可以使用该驱动器,但是该卡不可热插拔。


7. 调试技巧和编程信息

7.1 提交有用的问题报告

提交报告的最佳方法是使用在线 pcmcia-cs 论坛或 SourceForge 上的错误跟踪器。这样,其他人可以看到当前的问题(以及可用的修复程序或解决方法,如果可用)。以下是所有错误报告中应包含的一些内容

所有 PCMCIA 模块和 cardmgr 守护程序都将状态消息发送到系统日志。这些消息通常最终会出现在类似 /var/log/messages/var/log/daemon.log 的位置。在跟踪问题时,这些文件应该是首先查看的地方。提交错误报告时,请务必包含这些文件的相关内容。如果您在查找系统消息时遇到问题,请检查 /etc/syslog.conf 以查看不同类别的消息是如何处理的。

在提交错误报告之前,请检查以确保您使用的是最新版本的驱动程序包。虽然阅读我已经修复的事物的错误报告有点令人欣慰,但这并不是特别有建设性地利用我的时间。

如果您无法访问网络,错误报告可以发送给我,地址为 dahinds@users.sourceforge.net。但是,我更希望将错误报告发布到 pcmcia-cs SourceForge 站点,以便其他人可以看到它们。

7.2 解释内核陷阱报告

如果您的错误涉及内核故障,则只有当您可以将故障地址 EIP 转换为有意义的内容时,来自故障的寄存器转储才有用。最新版本的 klogd 尝试根据当前的内核符号映射转换故障地址,但是如果故障发生在模块中,或者问题严重到 klogd 无法完成将故障信息写入系统日志,则这可能不起作用。

如果故障发生在主内核中,则可以在 System.map 文件中查找故障地址。这可以安装在 /System.map/boot/System.map 中。如果故障发生在模块中,则 nm 命令给出相同的信息,但是,必须根据模块的加载地址调整故障地址。假设您有以下内核故障

Unable to handle kernel NULL pointer dereference
current->tss.cr3 = 014c9000, %cr3 = 014c9000
*pde = 00000000
Oops: 0002
CPU:    0
EIP:    0010:[<c2026081>]
EFLAGS: 00010282

故障地址为 0xc2026081。查看 System.map,我们看到这超出了内核的末尾,即在内核模块中。要确定是哪个模块,请检查 ``ksyms -m | sort'' 的输出

Address   Symbol                            Defined by
c200d000  (35k)                             [pcmcia_core]
c200d10c  register_ss_entry                 [pcmcia_core]
c200d230  unregister_ss_entry               [pcmcia_core]
          ...
c2026000  (9k)                              [3c574_cs]
c202a000  (4k)                              [serial_cs]

因此,0xc2026081 在 3c574_cs 模块中,并且与模块的起始位置偏移 0x0081。我们还无法在 3c574_cs.o 中查找此偏移量:当内核加载模块时,它会在模块加载地址处插入一个标头,因此模块的实际起始位置与 ksyms 中显示的地址偏移。标头的大小随内核版本而异:要找出内核的大小,请检查导出符号的模块(如上面的 pcmcia_core),并将符号地址与该符号的 nm 输出进行比较。在本例中,register_ss_entry 加载在 0xc200d10c - 0xc200d000 = 0x010c 的偏移量处,而 ``nm pcmcia_core.o'' 显示偏移量为 0x00c0,因此标头大小为 0x010c - 0x00c0 = 0x004c 字节。

回到 3c574_cs,我们的错误偏移量是 0x0081,减去 0x004c 的头部,真正的模块偏移量是 0x0035。现在查看 ``nm 3c574_cs.o | sort'',我们看到

0000002c d if_names
0000002c t tc574_attach
00000040 d mii_preamble_required
00000041 d dev_info

所以,错误位于 tc574_attach() 中。

在这个例子中,错误没有导致系统完全死锁,所以错误发生后可以执行 ksyms。在其他情况下,您可能不得不间接推断模块加载地址。相同的事件序列通常会以相同的顺序和相同的地址加载模块。如果插入某个卡时发生错误,请在插入卡之前或插入不同的卡时获取 ksyms 输出。您也可以使用 insmod 手动加载卡的驱动模块,并在插入卡之前运行 ksyms

有关更多背景信息,请参阅 ``man insmod''、``man ksyms'' 和 ``man klogd''。在内核源代码树中,Documentation/oops-tracing.txt 也相关。以下是一些更多的内核调试提示

7.3 低级 PCMCIA 调试辅助工具

PCMCIA 模块包含大量有条件编译的调试代码。大多数代码都在 PCMCIA_DEBUG 预处理器定义的控制之下。如果未定义此项,则不会编译调试代码。如果设置为 0,则代码已编译但处于非活动状态。较大的数字指定更高的详细程度。每个使用 PCMCIA_DEBUG 定义构建的模块都将具有一个整数参数 pc_debug,该参数控制其输出的详细程度。这可以在模块加载时进行调整,因此可以在每个模块的基础上控制输出,而无需重新编译。

您的 syslogd 默认配置可能会丢弃内核调试消息。为了确保记录它们,请编辑 /etc/syslog.conf 以确保 ``kern.debug'' 消息记录在某处。有关详细信息,请参阅 ``man syslog.conf''。

PCMCIA 发行版的 debug_tools/ 子目录中有一些寄存器级调试工具。dump_tcicdump_i365 实用程序为 ISA 到 PCMCIA 控制器生成寄存器转储。在 3.1.15 及更高版本中,dump_i365dump_exca 取代,后者类似,但也适用于 PCI 到 CardBus 桥接器。在 3.1.15 中针对 CardBus 桥接器新增的还有 dump_cardbus 工具,它解释了 CardBus 特有的寄存器。如果您可以访问相应控制器芯片的数据手册,这些工具都非常有用。dump_cis 实用程序(在 3.0.2 之前的发行版中为 dump_tuples)列出了卡的 CIS(卡信息结构)的内容,并解码了大多数重要位。dump_cisreg 实用程序显示卡的本地配置寄存器。

memory_cs 存储卡驱动程序有时也用于调试 16 位 PC 卡的问题。它可以绑定到任何卡,并且不会干扰其他驱动程序。它可用于直接访问任何卡的属性内存或公共内存。同样,对于 CardBus 卡,memory_cb 驱动程序可以绑定到任何 32 位卡,以直接访问该卡的地址空间。有关更多信息,请参阅手册页。

7.4 /proc/bus/pccard

在 2.2 及更高版本的内核上,PCMCIA 包将在 /proc/bus/pccard 下创建一个状态信息树。许多信息只能使用 PCMCIA 主机控制器的数据表来解释。其内容可能取决于驱动程序的配置方式,但可能包括以下全部或部分内容

/proc/bus/pccard/{irq,ioport,memory}

如果存在,这些文件包含资源分配信息,以补充正常的内核资源表。如果配置为这样做,最新版本的 PCMCIA 系统可能会从即插即用 BIOS 获取额外的资源信息。

/proc/bus/pccard/drivers

在最近的版本中,这列出了所有当前加载的 PCMCIA 客户端驱动程序。与 /proc/modules 不同,它还列出了可能静态链接到内核中的驱动程序。

/proc/bus/pccard/*/info

对于每个插槽,描述该插槽的主机控制器及其功能。

/proc/bus/pccard/*/exca

这包含控制器 ``ExCA'' Intel i82365sl 兼容寄存器组的转储。

/proc/bus/pccard/*/{pci,cardbus}

对于 CardBus 桥接器,桥接器的 PCI 配置空间的转储,以及桥接器的 CardBus 配置寄存器的转储。

7.5 为新卡编写 Card Services 驱动程序

《Linux PCMCIA 程序员指南》是客户端驱动程序接口的最佳文档。最新版本始终可以从 projects.sourceforge.net/pub/pcmcia-cs/doc 中获得,或在 Web 上访问 http://pcmcia-cs.sourceforge.net

对于与普通 ISA 设备密切相关的设备,您可能可以使用现有 Linux 驱动程序的部分代码。在某些情况下,最大的障碍将是修改现有驱动程序,使其能够处理在启动时间后添加和删除设备。在当前的驱动程序中,存储卡驱动程序是唯一“自包含”的驱动程序,它不依赖于 Linux 内核的其他部分来完成大部分繁重的工作。

在许多情况下,支持新型卡的最大障碍是从制造商处获取技术信息。可能很难弄清楚要问谁,或者准确解释需要什么信息。但是,除了一些例外,如果没有制造商提供的技术信息,为卡实现驱动程序是非常困难的,如果不是不可能的话。

我编写了一个带有大量注释的虚拟驱动程序,解释了驱动程序如何与卡服务通信;您可以在 PCMCIA 源代码发行版的 clients/dummy_cs.c 中找到它。

7.6 PCMCIA 客户端驱动程序作者指南

我已经决定,将所有 PCMCIA 客户端驱动程序作为 PCMCIA 包的一部分分发实际上是不可行的。每个新驱动程序都使主包的维护难度逐渐增加,并且包含驱动程序不可避免地将一些维护工作从驱动程序作者转移到我身上。相反,我将根据用户需求以及可维护性,在个案基础上决定是否包含贡献的驱动程序。对于未包含在核心包中的驱动程序,我建议驱动程序作者采用以下方案来打包他们的驱动程序以进行分发。

驱动程序文件应以与 PCMCIA 源代码发行版中使用的目录方案相同的目录方案排列,以便可以将驱动程序解压缩到完整的 PCMCIA 源代码树之上。驱动程序应包括源文件(在 ./modules/ 中)、手册页(在 ./man/ 中)和配置文件(在 ./etc/ 中)。顶层目录还应包括一个 README 文件。

顶层目录应包含一个 makefile,设置为使 ``make -f ... all'' 和 ``make -f ... install'' 编译驱动程序并安装所有适当的文件。如果此 makefile 被赋予 .mk 的扩展名,那么它将自动被顶层 Makefileallinstall 目标调用。这是一个如何构建此类 makefile 的示例

# Sample Makefile for contributed client driver
FILES = sample_cs.mk README.sample_cs \
        modules/sample_cs.c modules/sample_cs.h \
        etc/sample.conf etc/sample etc/sample.opts \
        man/sample_cs.4
all:
        $(MAKE) -C modules MODULES=sample_cs.o
install:
        $(MAKE) -C modules install-modules MODULES=sample_cs.o
        $(MAKE) -C etc install-clients CLIENTS=sample
        $(MAKE) -C man install-man4 MAN4=sample_cs.4
dist:
        tar czvf sample_cs.tar.gz $(FILES)

此 makefile 使用 2.9.10 及更高版本的 PCMCIA 包中定义的安装目标。此 makefile 还包括一个 “dist” 目标,以方便驱动程序作者。您可能需要在最终软件包文件名中添加版本号(例如,sample_cs-1.5.tar.gz)。完整的发行版可能如下所示

sample_cs.mk
README.sample_cs
modules/sample_cs.c
modules/sample_cs.h
etc/sample.conf
etc/sample
etc/sample.opts
man/sample_cs.4

通过这种安排,当解压缩贡献的驱动程序时,它实际上成为 PCMCIA 源代码树的一部分。它可以像“普通”客户端驱动程序一样,利用 PCMCIA 头文件,以及用于检查用户系统配置的机制和自动依赖性检查。

在此示例中,etc/sampleetc/sample.opts 将是新驱动程序的配置脚本(如果需要),etc/sample.conf 将包含对 PCMCIA 卡配置文件的任何添加。从 3.1.6 版本开始,cardmgr 将自动处理安装在 /etc/pcmcia 中的任何 *.conf 文件,因此贡献驱动程序的安装应该不再需要手动编辑配置文件。

我将接受根据此规范准备的客户端驱动程序,并将它们放在 projects.sourceforge.net 上的 /pub/pcmcia-cs/contrib 目录中。此目录中的 README 将描述如何解压缩贡献的驱动程序。

客户端驱动程序接口随着时间的推移变化不大,并且几乎始终保持向后兼容性。客户端驱动程序通常不需要为主包中的次要修订进行更新。我将尝试通知贡献驱动程序的作者需要更新其驱动程序的更改。

7.7 Linux 发行版维护者指南

如果您的发行版具有您希望 PCMCIA 感知的系统配置工具,请在 /etc/pcmcia 中为您的 “hooks” 使用 *.opts 文件。如果用户编译并安装新版本的 PCMCIA 包,这些文件将不会被修改。如果您修改主配置文件,那么全新安装将静默覆盖您的自定义脚本并断开与您的配置工具的连接。如果您不确定如何编写适当的选项脚本,或者您需要其他功能,请联系我。

如果您可以记录您的发行版如何偏离本文档中描述的 PCMCIA 包,这对用户(以及对我)很有帮助。特别是,请记录对启动脚本和配置脚本的更改。如果您将适当的信息发送给我,我将将其包含在 关于特定 Linux 发行版的说明 中。

在构建 PCMCIA 以进行分发时,请考虑包含不属于主 PCMCIA 包的贡献驱动程序。出于可维护性的原因,我试图限制核心包的大小,仅在我认为新驱动程序具有特别广泛的兴趣时才添加新驱动程序。其他驱动程序将单独分发,如上一节所述。整体驱动程序和单独驱动程序之间的划分在某种程度上是任意的和部分历史的,不应暗示质量上的差异。