i386 Micro Channel Architecture Support ======================================= MCA support is enabled using the CONFIG_MCA define. A machine with a MCA bus will have the kernel variable MCA_bus set, assuming the BIOS feature bits are set properly (see arch/i386/boot/setup.S for information on how this detection is done). Adapter Detection ================= The ideal MCA adapter detection is done through the use of the Programmable Option Select registers. Generic functions for doing this have been added in include/linux/mca.h and arch/i386/kernel/mca.c. Everything needed to detect adapters and read (and write) configuration information is there. A number of MCA-specific drivers already use this. The typical probe code looks like the following: #include unsigned char pos2, pos3, pos4, pos5; struct device* dev; int slot; if( MCA_bus ) { slot = mca_find_adapter( ADAPTER_ID, 0 ); if( slot == MCA_NOTFOUND ) { return ENODEV; } /* optional - see below */ mca_set_adapter_name( slot, "adapter name & description" ); mca_set_adapter_procfn( slot, dev_getinfo, dev ); /* read the POS registers. Most devices only need 2 and 3 */ pos2 = mca_read_stored_pos( slot, 2 ); pos3 = mca_read_stored_pos( slot, 3 ); pos4 = mca_read_stored_pos( slot, 4 ); pos5 = mca_read_stored_pos( slot, 5 ); } else { return ENODEV; } /* extract configuration from pos[2345] and set everything up */ Loadable modules should modify this to test that the specified IRQ and IO ports (plus whatever other stuff) match. See 3c523.c for example code. Keep in mind that devices should never directly access the POS registers (via inb(), outb(), etc). While it's generally safe, there is a small potential for blowing up hardware when it's done at the wrong time. Furthermore, accessing a POS register disables a device temporarily. This is usually okay during startup, but do _you_ want to rely on it? During initial configuration, mca_init() reads all the POS registers into memory. mca_read_stored_pos() accesses that data. mca_read_pos() and mca_write_pos() are also available for (safer) direct POS access, but their use is _highly_ discouraged. mca_write_pos() is particularly dangerous, as it is possible for adapters to be put in inconsistent states (i.e. sharing IO address, etc) and may result in crashes, toasted hardware, and operator injury. User level drivers (such as the AGX X server) can use /proc/mca to find adapters (see below). Some MCA adapters can also be detected via the usual ISA-style device probing (many SCSI adapters, for example). This sort of thing is highly discouraged. Perfectly good information is available telling you what's there, so there's no excuse for messing with random IO ports. However, we MCA people still appreciate any ISA-style driver that will work with our hardware. You take what you can get... Level-Triggered Interrupts ========================== Because MCA uses level-triggered interrupts, a few problems arise with what might best be described as the ISA mindset and its effects on drivers. These sorts of problems are expected to become less common as more people use shared IRQs on PCI machines. In general, an interrupt must be acknowledged not only at the ICU (which is done automagically by the kernel), but at the device level. In particular, IRQ 0 must be reset after a timer interrupt (now done in arch/i386/kernel/time.c) or the first timer interrupt hangs the system. There were also problems with the 1.3.x floppy drivers, but that seems to have been fixed. IRQs are also shareable, and most MCA-specific devices should be coded with shared IRQs in mind. /proc/mca ========= I did a major rewrite of /proc/mca. It is now a directory containing various files for adapters and other stuff. /proc/mca/pos Straight listing of POS registers /proc/mca/slot[1-8] Information on adapter in specific slot /proc/mca/video Same for integrated video /proc/mca/scsi Same for integrated SCSI /proc/mca/machine Machine information Device drivers can easily add their own information function for specific slots (including integrated ones) via the mca_set_adapter_procfn() call. Drivers that support this are ESDI, IBM SCSI, and 3c523. If a device is also a module, make sure that the proc function is removed in the module cleanup. This will require storing the slot information in a private structure somewhere. See the 3c523 driver for details. Your typical proc function will look something like this: static int dev_getinfo( char* buf, int slot, void* d ) { struct device* dev = (struct device*) d; int len = 0; len += sprintf( buf+len, "Device: %s\n", dev->name ); len += sprintf( buf+len, "IRQ: %d\n", dev->irq ); len += sprintf( buf+len, "IO Port: %#lx-%#lx\n", ... ); ... return len; } Some of the standard MCA information will already be printed, so don't bother repeating it. Don't try putting in more that 3K of information. Enable this function with: mca_set_adapter_procfn( slot, dev_getinfo, dev ); Disable it with: mca_set_adapter_procfn( slot, NULL, NULL ); It is also recommended that, even if you don't write a proc function, to set the name of the adapter (i.e. "PS/2 ESDI Controller") via mca_set_adapter_name( int slot, char* name ). Up to 30 characters are used. MCA Device Drivers ================== Currently, there are a number of MCA-specific device drivers. 1) PS/2 ESDI drivers/block/ps2esdi.c include/linux/ps2esdi.h Uses major number 36, and should use /dev files /dev/eda, /dev/edb. Supports two drives, but only one controller. Usually requires the command-line args ed=cyl,head,sec 2) PS/2 SCSI drivers/scsi/ibmmca.c drivers/scsi/ibmmca.h The driver for the IBM SCSI subsystem. Includes both integrated controllers and adapter cards. May require command-line arg ibmmcascsi=pun to force detection of an adapter. 3) 3c523 drivers/net/3c523.c drivers/net/3c523.h 3Com 3c523 Etherlink/MC ethernet driver. 4) SMC Ultra/MCA drivers/net/smc-mca.c drivers/net/smc-mca.h Elite/A (8013EP/A) and Elite10T/A (8013WP/A) ethernet driver As well, drivers/char/psaux.c was modified to support IRQ sharing (it's #ifdef CONFIG_MCA'ed, for your convenience, although PCI users might be able to use it...) The serial drivers were modified to support the extended IO port range of the typical MCA system (also #ifdef CONFIG_MCA). The following devices work with existing drivers: 1) Token-ring 2) Future Domain SCSI (MCS-600, MCS-700, not MCS-350) 3) Adaptec 1640 SCSI (aha1542 driver) 4) Buslogic SCSI (various) Bugs & Other Weirdness ====================== NMIs tend to occur with MCA machines because of various hardware weirdness, bus timeouts, and many other non-critical things. Those of you who have NMI problems should probably set the CONFIG_IGNORE_NMI flag somewhere. NMIs seem to be particularly common on the model 70. Various Pentium machines have serious problems with the FPU test in bugs.h. You may need to comment out the FPU test before you can even boot. This occurs, as far as we know, on the Pentium-equipped 85s, 95s, and some servers. The PCI/MCA PC 750s are fine as far as I can tell. The model 80 has a raft of problems that are just too weird and unique to get into here. Some people have no trouble while others have nothing but problems. I'd suspect the problems are related to the age of the average 80 and accompanying hardware deterioration. Credits ======= A whole pile of people have contributed to the MCA code. I'd include their names here, but I don't have a list handy. Check the MCA Linux home page (URL below) for an out-of-date list. ===================================================================== http://glycerine.cetmm.uni.edu/mca Chris Beauregard chrisb@truespectra.com