Next Previous Contents

11. Appendix

11.1 Universal Plug and Play (UPnP)

This is actually a sort of network plug-and-play developed by Microsoft but usable by Linux. You plug something into a network and that something doesn't need to be configured provided it will only communicate with other UPnP enabled devices on the network. Here "configure" is used in the broad sense and doesn't mean just configuring bus-resources. One objective is to allow people who know little about networks or configuring to install routers, gateways, network printers, etc. A major use for UPnP would be in wireless networking.

UPnP uses:

This HOWTO doesn't cover UPnP. UPnP for Linux is supported by Intel which has developed software for it. There are other programs which do about the same thing as UPnP. A comparison of some of them is at http://www.cs.umbc.edu/~dchakr1/papers/mcommerce.html A UPnP project for Linux is at SourceForge: UPnP SDK for Linux

11.2 Address Details

There are three types of addresses: main memory addresses, I/O addresses (ports) and configuration addresses. On the PCI bus, configuration addresses constitute a separate address space just like I/O addresses do. Except for the complicated case of ISA configuration addresses, whether or not an address on the bus is a memory address, I/O address, or configuration address depends only on the voltage on other wires (traces) of the bus. For the ISA configuration addresses see ISA Bus Configuration Addresses (Read-Port etc.) for details

Address ranges

The term "address" is sometimes used in this document to mean a contiguous range of addresses. Addresses are in units of bytes, So for example, a serial port at I/O address range 3F8-3FF will often just be referred to by its base address, 3F8. The 3F8 is the location of the first byte in the range (address range). To see the address ranges for various devices, look at /proc/iomem and /proc/ioports.

Address space

To access both I/O and (main) memory address "spaces" the same address bus is used (the wires used for the address are shared). How does the device know whether or not an address which appears on the address bus is a memory address or I/O address? Well, for ISA (for PCI read this too), there are 4 dedicated wires on the bus that convey this sort of information. If a certain one of these 4 wires is asserted, it says that the CPU wants to read from an I/O address, and the main memory ignores the address on the bus. In all, read and write wires exist for both main memory and I/O addresses (4 wires in all).

For the PCI bus it's the same basic idea (also using 4 wires) but it's done a little differently. Instead of only one of the four wires being asserted, a binary number is put on the wires (16 different possibilities). Thus, more info may be conveyed by these 4 wires.. Four of these 16 numbers serve the I/O and memory spaces as in the above paragraph. In addition there is also configuration address space which uses up two more numbers. This leaves 10 more numbers left over for other purposes.

PCI Configuration Address Space

This is different from the IO and memory address spaces because configuration address space is "geographic". Each slot for a card has the slot number as part of the address. This way, Linux (or the BIOS) can address a certain slot and find out what type of card is in that slot. Each device has 64 standard byte-size registers and some of these hold numbers which can unambiguously identify the device. Since the number of slots is limited as are the number of PCI devices built into motherboard, Linux (or the BIOS) only needs to check a limited number of addresses to find all the PCI devices. If it reads all ones (0xFF in hexadecimal) from the first register of a device, then that means that no device is present. Since there is no card or device to supply all these ones (0xFF) number, the PCI "host bridge" on the motherboard supplies (spoofs) this number for all non-existent device.

The PCI slot number is called (in PCI lingo) the "Device Number" and since a card may have up to 8 devices on it, a "Function Number" from 0-7 identifies which device it is on a PCI card. These numbers are part of the geographic address. Linux programmers call it "pci-slot-name". Thus what Linux calls a "device" is actually a "function" in PCI lingo. The PCI bus number (often 00) also becomes part of the geographic address. For example, 0000:00:0d.2 is PCI bus 0, slot 0d, function 2. For the full geographic address, one must include the double-word number of the device's configuration registers which one wants to access. The leading 0000 (in 1999) were reserved for future use.

How does the CPU designate that a read or write is to a PCI configuration space? It doesn't, at least not directly. Instead when access to configuration space is desired it does a 32-bit (double-word) write to 0cf8-0cfb in IO space and writes the full geographic address there. The PCI host bridge is listening at this address and insures that any next write of data to 0cfc-0cff is put into the specified configuration registers of the specified device. The bridge does this both by sending a special signal to the specified PCI card (or the like) on a dedicated wire that goes only to the slot where the card is plugged in. It also puts bits on the control bus saying that what's on the address bus now is a geographic configuration space address.

Why not make it simple and just have the CPU put bits on the control bus to say that the address on the main bus is a geographic one for PCI configuration? Well, most CPU's are not capable of doing this so the PCI host bridge gets to do it instead.

Range Check (ISA Testing for IO Address Conflicts)

On the ISA bus, there's a method built into each PnP card for checking that there are no other cards that use the same I/O address. If two or more cards use the same IO address, neither card is likely to work right (if at all). Good PnP software should assign bus-resources so as to avoid this conflict, but even in this case a legacy card might be lurking somewhere with the same address.

The test works by a card putting a known test number in its own IO registers. Then the PnP software reads it and verifies that what it reads is the same as the known test number. If not, something is wrong (such as another card with the same address). It repeats the same test with another test number. Since it actually checks the range of IO addresses assigned to the card, it's called a "range check". It could be better called an address-conflict test. If there is an address conflict you get an error message.

Communicating Directly via Memory

Traditionally, most I/O devices used only I/O memory to communicate with the CPU. The device driver, running on the CPU would read and write data to/from the I/O address space and main memory. Unfortunately, this requires two steps. For example, 1. read data from a device (in IO address space) and temporarily store in in the CPU; 2. write this data to main memory. A faster way would be for the device itself to put the data directly into main memory. One way to do this is by using ISA DMA Channels or PCI bus mastering. Another way is for the physical device to actually contain some main memory (at high addresses so as not to conflict with main memory chip addresses). This way the device reads and writes directly to it's self-contained main memory without having to bother with DMA or bus mastering. Such a device may also use IO addresses.

11.3 ISA Bus Configuration Addresses (Read-Port etc.)

These addresses are also known as the "Auto-configuration Ports". For the ISA bus, there is technically no configuration address space, but there is a special way for the CPU to access PnP configuration registers on the PnP cards. For this purpose 3 @ I/O addresses are allocated and each addresses only a single byte (there is no "range"). This is not 3 addresses for each card but 3 addresses shared by all ISA-PnP cards.

These 3 addresses are named read-port, write-port, and address-port. Each port is just one byte in size. Each PnP card has many configuration registers so that just 3 addresses are not even sufficient for the configuration registers on a single card. To solve this problem, each card is assigned a card number (handle) using a technique called "isolation". See ISA Isolation for the complex details.

Then to configure a certain card, its card number (handle) is sent out via the write-port address to tell that card that it is to listen at its address port. All other cards note that this isn't their card number and thus don't listen. Then the address of a configuration register (for that card) is sent to the address-port (for all cards --but only one is listening). Next, data transfer takes place with that configuration register on that card by either doing a read on the read-port or a write on the write-port.

The write-port is always at A79 and the address-port is always at 279 (hex). The read-port is not fixed but is set by the configuration software at some address (in the range 203-3FF) that will hopefully not conflict with any other ISA card. If there is a conflict, it will change the address. All PnP cards get "programmed" with this address. Thus if you use say isapnp to set or check configuration data it must determine this read-port address.

11.4 Interrupts --Details

Serialized Interrupts

It was previously stated that there was a wire for each interrupt. But the serialized interrupt (or serial interrupt) is an exception. A single wire is used for all interrupt which are multiplexed on that wire. Each interrupt has a time slot on the interrupt line. It's used on the LPC bus and is also for the PCI bus, but it's seldom used for PCI ??

DMA

Before going into interrupt details, there is another way for some devices to initiate communication besides sending out an interrupt. This method is a DMA (Direct Memory Access) request to take control of the computer from the CPU for a limited amount of time. On the PCI bus, it uses no "resources". Not all devices are capable of doing DMA. See DMA Channels.

Soft interrupts

There's also another type of interrupt known as a "soft interrupt" which is not covered in this HOWTO and doesn't use any "resources". While a hardware interrupt is generated by hardware, a soft interrupt is initiated by software. There are a couple of ways to do this. One way is for software to tell the CPU to issue an interrupt (an interrupt instruction). Another way is for the software to send messages to other processes so as to interrupt them although it's not clear that this should be called an interrupt. The ksoftirq process, which you may find running on a Linux PC, is a program which does this kind of interrupt for dealing with device drivers. The device driver starts running due to a hardware interrupt but later on, software interrupts are used for the "bottom half" of the driver's interrupt service routine. Thus, the ksoftirq process is also known as "bottom-half". For more details see the kernel documentation.

Hardware interrupts

Interrupts convey a lot of information but only indirectly. The interrupt request signal (a voltage on a wire) sent by a device just tells a chip called the interrupt controller that a certain device needs attention. The interrupt controller then signals the CPU. The CPU then interrupts whatever it was doing, finds the driver code for this device and runs a part of it known as an "interrupt service routine" (or "interrupt handler"). This "routine" tries to find out what has happened and then deals with the problem. For example, bytes may need to be transferred from/to the device. This program (routine) can easily find out what has happened since the device has registers at addresses known to the driver software (provided the IRQ number and the I/O address of the device has been set correctly). These registers contain status information about the device . The software reads the contents of these registers and by inspecting the contents, finds out what happened and takes appropriate action.

Thus each device driver needs to know what interrupt number (IRQ) to listen for. On the PCI bus (and for some special cases on the ISA bus) it's possible for two (or more) devices to share the same IRQ number. Note that you can't share a PCI interrupt with an ISA interrupt (are there any exceptions ??). When a shared interrupt is issued, the CPU runs all interrupt service routines sequentially for all devices using that interrupt. The first thing such a service routine does is to check its device's registers to see if an interrupt actually happened for its device. If it finds that its device didn't issue an interrupt (a false alarm) then it likely will immediately exit and the next service routine begins for the second device which uses that same interrupt. It checks out the device like described above. This sequence is repeated until the device is found that actually issued the interrupt. All the interrupt routines for an interrupt are said to be constitute a chain. So the chain is traversed until a routine on the chain claims the interrupt by saying in effect: this interrupt was for me. After it handles the interrupt, the interrupt service routines further out on the chain don't run.

The putting of a voltage on the IRQ line is only a request that the CPU be interrupted so it can run a device driver. In almost all cases the CPU is interrupted per the request. But interrupts may be temporarily disabled or prioritized so that in rare cases the actual interrupt of the CPU doesn't happen (or gets delayed). Thus what was above called an "interrupt" is more precisely only an interrupt request and explains why IRQ stands for Interrupt ReQuest.

11.5 How the Device Driver Catches its Interrupt

The previous statement, that device drivers listen for their interrupt, was an oversimplification. Actually it's a chip (or part of a chip) on the motherboard called the "interrupt controller" that listens for all interrupts. When the interrupt controller catches an interrupt, it sends a signal to the CPU to start the appropriate device driver's "interrupt service routine" to handle the interrupt.

There are various types of interrupt controllers. One type is the APIC = Advanced Programmable Interrupt Controller which usually has input pins for many interrupts, including PCI interrupts. Older controllers only have pins for ISA interrupts but they can still handle PCI interrupts since there is a "programmable interrupt router" that converts PCI interrupts to ISA interrupts and routes them to certain pins (= certain IRQs) on the ISA interrupt controller.

11.6 ISA Isolation

This is only for the old ISA bus. Isolation is a complex method of assigning a temporary handle (id number or Card Select Number = CSN) to each PnP device on the ISA bus. Since there are more efficient (but more complex) ways to do this, some might claim that it's a simple method. Only one write address is used for PnP writes to all PnP devices so that writing to this address goes to all PnP device that are listening. This write address is used to send (assign) a unique handle to each PnP device. To assign this handle requires that only one device be listening when the handle is sent (written) to this common address. All PnP devices have a unique serial number which they use for the process of isolation. Doing isolation is something like a game. It's done using the equivalent of just one common bus wire connecting all PnP devices to the isolation program.

For the first round of the "game" all PnP devices listen on this wire and send out simultaneously a sequence of bits to the wire. The allowed bits are either a 1 (positive voltage) or an "open 0" of no voltage (open circuit or tri-state). To do this, each PnP device just starts to sequentially send out its serial number on this wire, voltage (open circuit or tri-state). To do this, each PnP device just starts to sequentially send out its serial number on this wire, bit-by-bit, starting with the high-order bit. If any device sends a 1, a 1 will be heard on the wire by all other devices. If all devices send an "open 0" nothing will be heard on the wire. The object is to eliminate (by the end of this first round) all but highest serial number device. "Eliminate" means to drop out of this round of the game and thus temporarily cease to listen anymore to the wire. (Note that all serial numbers are of the same length.) When there remains only one device still listening, it will be given a handle (card number).

First consider only the high-order bit of the serial number which is put on the wire first by all devices which have no handle yet. If any PnP device sends out a 0 (open 0) but hears a 1, this means that some other PnP device has a higher serial number, so it temporarily drops out of this round. Now the devices remaining in the game (for this round) all have the same leading digit (a 1) so we may strip off this digit and consider only the resulting "stripped serial number" for future participation in this round. Then go to the start of this paragraph and repeat until the entire serial number has been examined for each device (see below for the all-0 case).

Thus it's clear that only cards with the lower serial number get eliminated during a round. But what happens if all devices in the game all send out a 0 as their high-order bit? In this case an "open 0" is sent on the line and all participants stay in the game. If they all have a leading 0 then this is a tie and the 0's are stripped off just like the 1's were in the above paragraph. The game then continues as the next digit (of the serial number) is sent out.

At the end of the round (after the low-order bit of the serial number has been sent out) only one PnP device with the highest serial number remains in the game. It then gets assigned a handle and drops out of the game permanently. Then all the dropouts from the previous round (that don't have a handle yet) reenter the game and a new round begins with one less participant. Eventually, all PnP devices are assigned handles. It's easy to prove that this algorithm works. The actual algorithm is a little more complex than that presented above since each step is repeated twice to ensure reliability and the repeats are done somewhat differently (but use the same basic idea).

Once all handles are assigned, they are used to address each PnP device for sending/reading configuration data. Note that these handles are only used for PnP configuration and are not used for normal communication with the PnP device. When the computer starts up a PnP BIOS will often do such an isolation and then a PnP configuration. After that, all the handles are "lost" so that if one wants to change (or inspect) the configuration again, the isolation must be done over again.

11.7 Bus Mastering and DMA resources

If a bus has bus mastering available, it's unlikely that any resources will be needed for DMA on that bus. For example, the PCI bus doesn't need DMA resources since it has "bus mastering". However, "bus mastering" is often called DMA. But since it's not strictly DMA it needs no DMA resources. The ISA and VESA local bus had no bus mastering. The old MCA and EISA buses did have bus mastering.

11.8 Historical and Obsolete

OSS-Lite Sound Driver

You must give the IO, IRQ, and DMA as parameters to a module or compile them into the kernel. But some PCI cards will get automatically detected. RedHat supplies a program "sndconfig" which detects ISA PnP sound cards and automatically sets up the modules for loading with the detected bus-resources.

ALSA (Advanced Linux Sound Architecture) as of 2000

This will detect the card by PnP methods and then select the appropriate driver and load it. It will also set the bus-resources on an ISA-PnP cards or PCI cards. OSS (Open Sound System) was formerly popular.

MS Windows Notes

Windows NT4 didn't support ISAPNP but had a PNPISA program which one could "use at your own risk". For NT4 users were advised to set "not a PnP OS" in the BIOS so that the BIOS would do the resource configuring. Thus both MS Windows and Linux were in olden days dependent on the BIOS doing the configuring (and still are).

END OF Plug-and-Play-HOWTO


Next Previous Contents