In theory, it should not really matter which interrupt is allocated to which device, as long as two devices are not configured to use the same interrupt. In /etc/pcmcia/config.opts
you'll find a place for excluding interrupts that are used by non-PCMCIA devices.
Similarly, there is no way to directly specify the I/O addresses for a card to use. The /etc/pcmcia/config.opts
file allows you to specify ranges of ports available for use by any card, or to exclude ranges that conflict with other devices.
After modifying /etc/pcmcia/config.opts
, you can reinitialize cardmgr
with ``kill -HUP
''.
The interrupt used to monitor card status changes is chosen by the low-level socket driver module (i82365
or tcic
) before cardmgr
parses /etc/pcmcia/config
, so it is not affected by changes to this file. To set this interrupt, use the cs_irq=
option when the socket driver is loaded, by setting the PCIC_OPTS
variable in /etc/rc.d/rc.pcmcia
.
All the client card drivers have a parameter called irq_list
for specifying which interrupts they may try to allocate. These driver options should be set in your /etc/pcmcia/config
file. For example:
device "serial_cs" module "serial_cs" opts "irq_list=8,12" ...
would specify that the serial driver should only use irq 8 or irq 12. Regardless of irq_list
settings, Card Services will never allocate an interrupt that is already in use by another device, or an interrupt that is excluded in the config file.
Each PCI slot has four PCI interrupt pins, INTA through INTD. Single function devices will only use the INTA pin; multifunction devices may use multiple INT pins. On the processor side, on x86 single processor systems, incoming hardware interrupts are directed to interrupt requests (irq's) numbered 0..15. The PCI interrupt router, usually part of the PCI-to-ISA host bridge, determines how incoming PCI interrupts are mapped to CPU irq numbers. Most modern bridge chips have several PCI interrupt inputs, known as PIRQ1, PIRQ2, etc, each of which can be routed to any CPU irq number. So we might have something like:
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
Multiple INT pins are often connected to the same PIRQ pin. Usually, the connections from INT pins to PIRQ pins are arranged to spread installed devices out as much as possible, to give the OS the most flexibility for choosing how interrupts are shared. The mapping from bridge PIRQ pins to CPU irq numbers can be obtained by reading registers in the interrupt router. The mapping from INT pins to the router's PIRQ pins, however, depends on how the board designer decided to connect things up, and cannot be directly determined by driver software.
For most PCI devices, the OS does not need to understand the interrupt router details. Each PCI device has a configuration register, the PCI Interrupt Line Register, that the BIOS initializes with the appropriate CPU irq number for that device. Unfortunately, the BIOS generally will not configure PCI interrupts for CardBus bridge devices.
The PCI BIOS's Interrupt Routing Table is a data structure that contains information about the mapping from PCI INT pins to the PIRQ pins on the PCI interrupt router. The routing information in the table is stored in a somewhat unhelpful form, however. For each device's INT pins, the table specifies a ``link value''. All interrupts with the same link value are wired to the same PIRQ pin; however, the meaning of the link values is defined by the chipset vendor.
Several tools are available for examining PCI interrupt routing information:
lspci
, /proc/pci
These will show you resource information (including interrupt assignments, where they are known) for all your PCI devices.
dump_pirq
This is in the debug-tools
directory of the PCMCIA source distribution. It dumps the contents of your PCI interrupt routing table, if available. It also scans for known interrupt routers and dumps their current interrupt steering settings.
Several PCMCIA module parameters affect PCI interrupt routing:
pcmcia_core
module: cb_pci_irq=n
This option specifies one interrupt number to be used to program the PCI interrupt router for all CardBus sockets that do not already have an interrupt assignment. It only has any effect on systems that have a PCI irq routing table, and a known interrupt router.
i82365
module: irq_mode=n
Most CardBus bridges offer several methods for delivering interrupts to the host. The i82365 module by default assumes that a bridge can deliver both PCI and ISA interrupts, since this is normal for laptops. A setting of ``irq_mode=0
'' can be used to force a bridge to use only PCI interrupts. See the man page for the i82365
module for a description of what other values mean for different bridge types.
i82365
module: irq_list=n,n,...
This parameter lists which ISA interrupt(s) can be used for PCMCIA. If no ISA interrupts are available, specify ``irq_list=0
''. Note that ``irq_mode=0
'' implies ``irq_list=0
''.
i82365
module: pci_irq_list=n,n,...
This option specifies a list of PCI interrupt numbers to use for CardBus sockets. It differs from cb_pci_irq
, because it does not actually program the PCI interrupt router; it can be used when you know the PCI interrupts are already set up a certain way, even if you do not know how the router works.
If you are having problems that you think may be related to PCI interrupt configuration, you should first verify that you have a reasonably current PCMCIA driver package. Also carefully look at the startup messages when the PCMCIA kernel modules are loaded. You should see something like:
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
The ``PCI routing table
'' message indicates that a valid routing table was found. The ``host opts
'' lines indicate the interrupt delivery mode and whether or not a PCI interrupt could be determined for each socket. And the final line indicates the results of the scan for available interrupts.
Symptoms:
lspci
or in /proc/pci
.The Lucent/SCM PCI-to-CardBus adapters seem to confuse the PCI BIOS on some older systems. Lucent says that this card is only supported on systems that have a BIOS that supports the PCI 2.2 specification, or are PC99 compliant. Some older systems will not detect the Lucent card at all, and if the system can't detect it, the Linux drivers cannot use it. The only possible resolutions are a BIOS upgrade, or using a different motherboard or CardBus adapter.
Symptoms:
/proc/interrupts
shows a count of 0 for interrupts assigned to PCMCIA drivers.CardBus bridges usually support two types of interrupts, PCI and ISA. Partly for historical reasons, it has become conventional to use PCI interrupts for signaling card insertion and removal events, and for CardBus card interrupts; and ISA interrupts for 16-bit cards. Since version 3.1.9, this is the scheme that the Linux PCMCIA system will use by default. Most CardBus bridges support multiple methods for delivering interrupts to the host CPU. Methods include ``parallel'' interrupts, where each supported irq has a dedicated pin on the bridge; various serial interrupt protocols, where one or two pins are used to communicate with an interrupt controller; and hybrids, where PCI interrupts might be signalled using dedicated pins, while ISA interrupts are delivered via a serial controller.
In general, it is the responsibility of the BIOS to program a bridge for the appropriate interrupt delivery method. However, there are systems that do this incorrectly, and in some cases, there is no way for software to safely detect the correct delivery method. The i82365
module reports the bridge mode at startup time, and has a parameter, irq_mode
, that can be used to reconfigure it. Not all bridges support this parameter, and the meaning of irq_mode
depends on the bridge type. See the i82365
man page for a description of what values are supported by your bridge. In some cases, a bridge may function correctly in more than one interrupt mode.
Most PCMCIA card readers that fit in a PCI bus slot only provide PCI interrupt routing. The Linux drivers assume that all bridges have ISA interrupt capability, since that is generally correct on laptops. With a card reader, it will generally be necessary to use the irq_mode
parameter to specify a ``PCI only'' interrupt delivery mode; the value of the parameter depends on the bridge type, so check the i82365
man page. A few PCI card readers require an irq_mode
that permits ISA interrupts, but those interrupts are not actually connected; in that case, use ``irq_list=0
''.
Check the system log and verify that the CardBus bridge has a PCI interrupt assignment. If it does not, then resolve that problem first, then return here if the symptoms persist. Next, experiment with different values for the irq_mode
parameter.
Symptoms:
When a routing table is present, the pcmcia_core
module will try to automatically configure the PCI interrupt router, but only does so when it has a safe and unambiguous choice for what PCI interrupt to use. If there are several valid choices, then you must use the ``cb_pci_irq=...
'' option to specify which interrupt to assign. Your best bet is to pick the most lightly used interrupt that is already assigned to another PCI device.
Moving the card to another slot sometimes offers a quick solution. If that slot shares its interrupt with an already-configured device, then the PCMCIA drivers will have no trouble figuring out the assignment.
Symptoms:
Adding support for a new interrupt router is tricky but not a big job. First determine, from a datasheet, how your interrupt router steers PCI interrupts. Then, see if you can guess the meaning of the link values from the output of dump_pirq
. Usually this is reasonably obvious. Most routers have four PIRQ pins, and the link values might be something like 1,2,3,4, or 0x10,0x18,0x20,0x28, or 0x60,0x61,0x62,0x63. The values are usually chosen so that they can be easily converted to the location of the appropriate interrupt steering register. Finally, add small functions to modules/pci_fixup.c
to get/set the interrupt steering information for this router, using the other routers as examples.
Symptoms:
Without an interrupt routing table, we cannot tell how interrupts from the CardBus bridge are directed to CPU irq numbers. All hope is not lost: you may be able to guess the PCI interrupt assignment and use the ``pci_irq_list=...
'' option to pass this information to the i82365
module. Good guesses might include the interrupt(s) assigned to other PCI devices, the interrupt(s) used under Windows, or any other interrupts that are unaccounted for.
You may also want to experiment with putting the adapter in different PCI slots, for each pci_irq_list
you try. You are trying to find a slot that shares its interrupt with an already-configured device, and might need to try several slots to find one.
This is fairly easy using ``scheme'' support. Use two configuration schemes, called ``home'' and ``work''. Here is an example of a network.opts
script with scheme-specific settings:
case "$ADDRESS" in work,*,*,*) # definitions for network card in work scheme ... ;; home,*,*,*|default,*,*,*) # definitions for network card in home scheme ... ;; esac
The first part of a device address is always the configuration scheme. In this example, the second ``case'' clause will select for both the ``home'' and ``default'' schemes. So, if the scheme is unset for any reason, it will default to the ``home'' setup.
Now, to select between the two sets of settings, run either:
cardctl scheme home
or
cardctl scheme work
The cardctl
command does the equivalent of shutting down all your cards and restarting them. The command can be safely executed whether or not the PCMCIA system is loaded, but the command may fail if you are using other PCMCIA devices at the time (even if their configurations are not explicitly dependant on the scheme setting).
To find out the current scheme setting, run:
cardctl scheme
By default, the scheme setting is persistent across boots. This can have undesirable effects if networking is initialized for the wrong environment. Optionally, you can set the initial scheme value with the SCHEME
startup option (see Startup options for details). It is also possible to set the scheme from the lilo
boot prompt. Since lilo
passes unrecognized options to init
as environment variables, a value for SCHEME
(or any other PCMCIA startup option) at the boot prompt will be propagated into the PCMCIA startup script.
To save even more keystrokes, schemes can be specified in lilo
's configuration file. For instance, you could have:
root = /dev/hda1 read-only image = /boot/vmlinuz label = home append = "SCHEME=home" image = /boot/vmlinuz label = work append = "SCHEME=work"
Typing ``home'' or ``work'' at the boot prompt would then boot into the appropriate scheme.
Having the root filesystem on a PCMCIA device is tricky because the Linux PCMCIA system is not designed to be linked into the kernel. Its core components, the loadable kernel modules and the user mode cardmgr daemon, depend on an already running system. The kernel's ``initrd'' facility works around this requirement by allowing Linux to boot using a temporary ram disk as a minimal root image, load drivers, and then re-mount a different root filesystem. The temporary root can configure PCMCIA devices and then re-mount a PCMCIA device as root.
The initrd image absolutely must reside on a bootable device: this generally cannot be put on a PCMCIA device. This is a BIOS limitation, not a kernel limitation. It is useful here to distinguish between ``boot-able'' devices (i.e., devices that can be booted), and ``root-able'' devices (i.e., devices that can be mounted as root). ``Boot-able'' devices are determined by the BIOS, and are generally limited to internal floppy and hard disk drives. ``Root-able'' devices are any block devices that the kernel supports once it has been loaded. The initrd facility makes more devices ``root-able'', not ``boot-able''.
Some Linux distributions will allow installation to a device connected to a PCMCIA SCSI adapter, as an unintended side-effect of their support for installs from PCMCIA SCSI CD-ROM devices. However, at present, no Linux installation tools support configuring an appropriate ``initrd'' to boot Linux with a PCMCIA root filesystem. Setting up a system with a PCMCIA root thus requires that you use another Linux system to create the ``initrd'' image. If another Linux system is not available, another option would be to temporarily install a minimal Linux setup on a non-PCMCIA drive, create an initrd image, and then reinstall to the PCMCIA target.
The Linux Bootdisk-HOWTO has some general information about setting up boot disks but nothing specific to initrd. The main initrd document is included with recent kernel source code distributions, in linux/Documentation/initrd.txt
. Before beginning, you should read this document. A familiarity with lilo
is also helpful. Using initrd also requires that you have a kernel compiled with CONFIG_BLK_DEV_RAM
and CONFIG_BLK_DEV_INITRD
enabled.
This is an advanced configuration technique, and requires a high level of familiarity with Linux and the PCMCIA system. Be sure to read all the relevant documentation before starting. The following cookbook instructions should work, but deviations from the examples will quickly put you in uncharted and ``unsupported'' territory, and you will be on your own.
This method absolutely requires that you use a PCMCIA driver release of 2.9.5 or later. Older PCMCIA packages or individual components will not work in the initrd context. Do not mix components from different releases.
The pcinitrd
script creates a basic initrd image for booting with a PCMCIA root partition. The image includes a minimal directory heirarchy, a handful of device files, a few binaries, shared libraries, and a set of PCMCIA driver modules. When invoking pcinitrd
, you specify the driver modules that you want to be included in the image. The core PCMCIA components, pcmcia_core
and ds
, are automatically included.
As an example, say that your laptop uses an i82365-compatible host controller, and you want to boot Linux with the root filesystem on a hard drive attached to an Adaptec SlimSCSI adapter. You could create an appropriate initrd image with:
pcinitrd -v initrd pcmcia/i82365.o pcmcia/aha152x_cs.o
To customize the initrd startup sequence, you could mount the image using the ``loopback'' device with a command like:
mount -o loop -t ext2 initrd /mnt
and then edit the linuxrc
script. The configuration files will be installed under /etc
in the image, and can also be customized. See the man page for pcinitrd
for more information.
After creating an image with pcinitrd
, you can create a boot floppy by copying the kernel, the compressed initrd image, and a few support files for lilo
to a clean floppy. In the following example, we assume that the desired PCMCIA root device is /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
Create /mnt/etc/lilo.conf
with the contents:
boot=/dev/fd0 compact image=/vmlinuz label=linux initrd=/initrd read-only root=/dev/sda1
Finally, invoke lilo with:
lilo -r /mnt
When lilo
is invoked with -r
, it performs all actions relative to the specified alternate root directory. The reason for creating the device files under /mnt/dev
was that lilo
will not be able to use the files in /dev
when it is running in this alternate-root mode.
One common use of the initrd facility would be on systems where the internal hard drive is dedicated to another operating system. The Linux kernel and initrd image can be placed in a non-Linux partition, and lilo
or LOADLIN
can be set up to boot Linux from these images.
Assuming that you have a kernel has been configured for the appropriate root device, and an initrd image created on another system, the easiest way to get started is to boot Linux using LOADLIN
, as:
LOADLIN <kernel> initrd=<initrd-image>
Once you can boot Linux on your target machine, you could then install lilo
to allow booting Linux directly. For example, say that /dev/hda1
is the non-Linux target partition and /mnt
can be used as a mount point. First, create a subdirectory on the target for the Linux files:
mount /dev/hda1 /mnt mkdir /mnt/linux cp [kernel-image] /mnt/linux/vmlinuz cp [initrd-image] /mnt/linux/initrd
In this example, say that /dev/sda1
is the desired Linux root partition, a SCSI hard drive mounted via a PCMCIA SCSI adapter. To install lilo
, create a lilo.conf
file with the contents:
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
The boot=
line says to install the boot loader in the master boot record of the specified device. The root=
line identifies the desired root filesystem to be used after loading the initrd image, and may be unnecessary if the kernel image is already configured this way. The other=
section is used to describe the other operating system installed on /dev/hda1
.
To install lilo
in this case, use:
lilo -C lilo.conf
Note that in this case, the lilo.conf
file uses absolute paths that include /mnt
. I did this in the example because the target filesystem may not support the creation of Linux device files for the boot=
and root=
options.