Commit bb8187d3 authored by Paul Gortmaker's avatar Paul Gortmaker

MCA: delete all remaining traces of microchannel bus support.

Hardware with MCA bus is limited to 386 and 486 class machines
that are now 20+ years old and typically with less than 32MB
of memory.  A quick search on the internet, and you see that
even the MCA hobbyist/enthusiast community has lost interest
in the early 2000 era and never really even moved ahead from
the 2.4 kernels to the 2.6 series.

This deletes anything remaining related to CONFIG_MCA from core
kernel code and from the x86 architecture.  There is no point in
carrying this any further into the future.

One complication to watch for is inadvertently scooping up
stuff relating to machine check, since there is overlap in
the TLA name space (e.g. arch/x86/boot/mca.c).

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: James Bottomley <JBottomley@Parallels.com>
Cc: x86@kernel.org
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Acked-by: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent a88dc06c
...@@ -218,8 +218,6 @@ m68k/ ...@@ -218,8 +218,6 @@ m68k/
- directory with info about Linux on Motorola 68k architecture. - directory with info about Linux on Motorola 68k architecture.
magic-number.txt magic-number.txt
- list of magic numbers used to mark/protect kernel data structures. - list of magic numbers used to mark/protect kernel data structures.
mca.txt
- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
md.txt md.txt
- info on boot arguments for the multiple devices driver. - info on boot arguments for the multiple devices driver.
memory-barriers.txt memory-barriers.txt
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# To add a new book the only step required is to add the book to the # To add a new book the only step required is to add the book to the
# list of DOCBOOKS. # list of DOCBOOKS.
DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ DOCBOOKS := z8530book.xml device-drivers.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
writing_usb_driver.xml networking.xml \ writing_usb_driver.xml networking.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
......
...@@ -212,19 +212,6 @@ X!Edrivers/pci/hotplug.c ...@@ -212,19 +212,6 @@ X!Edrivers/pci/hotplug.c
<sect1><title>PCI Hotplug Support Library</title> <sect1><title>PCI Hotplug Support Library</title>
!Edrivers/pci/hotplug/pci_hotplug_core.c !Edrivers/pci/hotplug/pci_hotplug_core.c
</sect1> </sect1>
<sect1><title>MCA Architecture</title>
<sect2><title>MCA Device Functions</title>
<para>
Refer to the file arch/x86/kernel/mca_32.c for more information.
</para>
<!-- FIXME: Removed for now since no structured comments in source
X!Earch/x86/kernel/mca_32.c
-->
</sect2>
<sect2><title>MCA Bus DMA</title>
!Iarch/x86/include/asm/mca_dma.h
</sect2>
</sect1>
</chapter> </chapter>
<chapter id="firmware"> <chapter id="firmware">
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="MCAGuide">
<bookinfo>
<title>MCA Driver Programming Interface</title>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@lxorguk.ukuu.org.uk</email>
</address>
</affiliation>
</author>
<author>
<firstname>David</firstname>
<surname>Weinehall</surname>
</author>
<author>
<firstname>Chris</firstname>
<surname>Beauregard</surname>
</author>
</authorgroup>
<copyright>
<year>2000</year>
<holder>Alan Cox</holder>
<holder>David Weinehall</holder>
<holder>Chris Beauregard</holder>
</copyright>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
The MCA bus functions provide a generalised interface to find MCA
bus cards, to claim them for a driver, and to read and manipulate POS
registers without being aware of the motherboard internals or
certain deep magic specific to onboard devices.
</para>
<para>
The basic interface to the MCA bus devices is the slot. Each slot
is numbered and virtual slot numbers are assigned to the internal
devices. Using a pci_dev as other busses do does not really make
sense in the MCA context as the MCA bus resources require card
specific interpretation.
</para>
<para>
Finally the MCA bus functions provide a parallel set of DMA
functions mimicing the ISA bus DMA functions as closely as possible,
although also supporting the additional DMA functionality on the
MCA bus controllers.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
None.
</para>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Edrivers/mca/mca-legacy.c
</chapter>
<chapter id="dmafunctions">
<title>DMA Functions Provided</title>
!Iarch/x86/include/asm/mca_dma.h
</chapter>
</book>
...@@ -846,13 +846,7 @@ Your cooperation is appreciated. ...@@ -846,13 +846,7 @@ Your cooperation is appreciated.
... ...
31 = /dev/tap15 16th Ethertap device 31 = /dev/tap15 16th Ethertap device
36 block MCA ESDI hard disk 36 block OBSOLETE (was MCA ESDI hard disk)
0 = /dev/eda First ESDI disk whole disk
64 = /dev/edb Second ESDI disk whole disk
...
Partitions are handled in the same way as IDE disks
(see major number 3).
37 char IDE tape 37 char IDE tape
0 = /dev/ht0 First IDE tape 0 = /dev/ht0 First IDE tape
......
...@@ -179,7 +179,7 @@ CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set. ...@@ -179,7 +179,7 @@ CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set.
Converting an EISA driver to the new API mostly involves *deleting* Converting an EISA driver to the new API mostly involves *deleting*
code (since probing is now in the core EISA code). Unfortunately, most code (since probing is now in the core EISA code). Unfortunately, most
drivers share their probing routine between ISA, MCA and EISA. Special drivers share their probing routine between ISA, and EISA. Special
care must be taken when ripping out the EISA code, so other busses care must be taken when ripping out the EISA code, so other busses
won't suffer from these surgical strikes... won't suffer from these surgical strikes...
......
...@@ -70,7 +70,6 @@ parameter is applicable: ...@@ -70,7 +70,6 @@ parameter is applicable:
M68k M68k architecture is enabled. M68k M68k architecture is enabled.
These options have more detailed description inside of These options have more detailed description inside of
Documentation/m68k/kernel-options.txt. Documentation/m68k/kernel-options.txt.
MCA MCA bus support is enabled.
MDA MDA console support is enabled. MDA MDA console support is enabled.
MIPS MIPS architecture is enabled. MIPS MIPS architecture is enabled.
MOUSE Appropriate mouse support is enabled. MOUSE Appropriate mouse support is enabled.
......
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/x86/kernel/mca_32.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 <linux/mca.h>
unsigned char pos2, pos3, pos4, pos5;
struct net_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 use 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 (actually, smc-mca.c has a slightly more complex example that can
handle a list of adapter ids).
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 blindness.
User level drivers (such as the AGX X server) can use /proc/mca/pos 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/x86/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
=========
/proc/mca is 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
See Appendix A for a sample.
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 net_device* dev = (struct net_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 than 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 ).
MCA Device Drivers
==================
Currently, there are a number of MCA-specific device drivers.
1) 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=io_port" to force detection of an adapter. If you have a
machine with a front-panel display (i.e. model 95), you can use
"ibmmcascsi=display" to enable a drive activity indicator.
2) 3c523
drivers/net/3c523.c
drivers/net/3c523.h
3Com 3c523 Etherlink/MC ethernet driver.
3) SMC Ultra/MCA and IBM Adapter/A
drivers/net/smc-mca.c
drivers/net/smc-mca.h
Driver for the MCA version of the SMC Ultra and various other
OEM'ed and work-alike cards (Elite, Adapter/A, etc).
4) NE/2
driver/net/ne2.c
driver/net/ne2.h
The NE/2 is the MCA version of the NE2000. This may not work
with clones that have a different adapter id than the original
NE/2.
5) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and
Reply Sound Blaster/SCSI (SCSI part)
Better support for these cards than the driver for ISA.
Supports multiple cards with IRQ sharing.
Also added boot time option of scsi-probe, which can do reordering of
SCSI host adapters. This will direct the kernel on the order which
SCSI adapter should be detected. Example:
scsi-probe=ibmmca,fd_mcs,adaptec1542,buslogic
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, OEM'ed IBM SCSI)
3) Adaptec 1640 SCSI (using the aha1542 driver)
4) Bustek/Buslogic SCSI (various)
5) Probably all Arcnet cards.
6) Some, possibly all, MCA IDE controllers.
7) 3Com 3c529 (MCA version of 3c509) (patched)
8) Intel EtherExpressMC (patched version)
You need to have CONFIG_MCA defined to have EtherExpressMC support.
9) Reply Sound Blaster/SCSI (SB part) (patched version)
Bugs & Other Weirdness
======================
NMIs tend to occur with MCA machines because of various hardware
weirdness, bus timeouts, and many other non-critical things. Some basic
code to handle them (inspired by the NetBSD MCA code) has been added to
detect the guilty device, but it's pretty incomplete. If NMIs are a
persistent problem (on some model 70 or 80s, they occur every couple
shell commands), the CONFIG_IGNORE_NMI flag will take care of that.
Various Pentium machines have had serious problems with the FPU test in
bugs.h. Basically, the machine hangs after the HLT test. This occurs,
as far as we know, on the Pentium-equipped 85s, 95s, and some PC Servers.
The PCI/MCA PC 750s are fine as far as I can tell. The ``mca-pentium''
boot-prompt flag will disable the FPU bug check if this is a problem
with your machine.
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 some problems are related to the age of the
average 80 and accompanying hardware deterioration, although others
are definitely design problems with the hardware. Among the problems
include SCSI controller problems, ESDI controller problems, and serious
screw-ups in the floppy controller. Oh, and the parallel port is also
pretty flaky. There were about 5 or 6 different model 80 motherboards
produced to fix various obscure problems. As far as I know, it's pretty
much impossible to tell which bugs a particular model 80 has (other than
triggering them, that is).
Drivers are required for some MCA memory adapters. If you're suddenly
short a few megs of RAM, this might be the reason. The (I think) Enhanced
Memory Adapter commonly found on the model 70 is one. There's a very
alpha driver floating around, but it's pretty ugly (disassembled from
the DOS driver, actually). See the MCA Linux web page (URL below)
for more current memory info.
The Thinkpad 700 and 720 will work, but various components are either
non-functional, flaky, or we don't know anything about them. The
graphics controller is supposed to be some WD, but we can't get things
working properly. The PCMCIA slots don't seem to work. Ditto for APM.
The serial ports work, but detection seems to be flaky.
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 a perpetually out-of-date list.
=====================================================================
MCA Linux Home Page: http://www.dgmicro.com/mca/
Christophe Beauregard
chrisb@truespectra.com
cpbeaure@calum.csclub.uwaterloo.ca
=====================================================================
Appendix A: Sample /proc/mca
This is from my model 8595. Slot 1 contains the standard IBM SCSI
adapter, slot 3 is an Adaptec AHA-1640, slot 5 is a XGA-1 video adapter,
and slot 7 is the 3c523 Etherlink/MC.
/proc/mca/machine:
Model Id: 0xf8
Submodel Id: 0x14
BIOS Revision: 0x5
/proc/mca/pos:
Slot 1: ff 8e f1 fc a0 ff ff ff IBM SCSI Adapter w/Cache
Slot 2: ff ff ff ff ff ff ff ff
Slot 3: 1f 0f 81 3b bf b6 ff ff
Slot 4: ff ff ff ff ff ff ff ff
Slot 5: db 8f 1d 5e fd c0 00 00
Slot 6: ff ff ff ff ff ff ff ff
Slot 7: 42 60 ff 08 ff ff ff ff 3Com 3c523 Etherlink/MC
Slot 8: ff ff ff ff ff ff ff ff
Video : ff ff ff ff ff ff ff ff
SCSI : ff ff ff ff ff ff ff ff
/proc/mca/slot1:
Slot: 1
Adapter Name: IBM SCSI Adapter w/Cache
Id: 8eff
Enabled: Yes
POS: ff 8e f1 fc a0 ff ff ff
Subsystem PUN: 7
Detected at boot: Yes
/proc/mca/slot3:
Slot: 3
Adapter Name: Unknown
Id: 0f1f
Enabled: Yes
POS: 1f 0f 81 3b bf b6 ff ff
/proc/mca/slot5:
Slot: 5
Adapter Name: Unknown
Id: 8fdb
Enabled: Yes
POS: db 8f 1d 5e fd c0 00 00
/proc/mca/slot7:
Slot: 7
Adapter Name: 3Com 3c523 Etherlink/MC
Id: 6042
Enabled: Yes
POS: 42 60 ff 08 ff ff ff ff
Revision: 0xe
IRQ: 9
IO Address: 0x3300-0x3308
Memory: 0xd8000-0xdbfff
Transceiver: External
Device: eth0
Hardware Address: 02 60 8c 45 c4 2a
...@@ -3316,12 +3316,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git ...@@ -3316,12 +3316,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
S: Maintained S: Maintained
F: arch/ia64/ F: arch/ia64/
IBM MCA SCSI SUBSYSTEM DRIVER
M: Michael Lang <langa2@kph.uni-mainz.de>
W: http://www.uni-mainz.de/~langm000/linux.html
S: Maintained
F: drivers/scsi/ibmmca.c
IBM Power Linux RAID adapter IBM Power Linux RAID adapter
M: Brian King <brking@us.ibm.com> M: Brian King <brking@us.ibm.com>
S: Supported S: Supported
...@@ -4418,13 +4412,6 @@ T: git git://git.monstr.eu/linux-2.6-microblaze.git ...@@ -4418,13 +4412,6 @@ T: git git://git.monstr.eu/linux-2.6-microblaze.git
S: Supported S: Supported
F: arch/microblaze/ F: arch/microblaze/
MICROCHANNEL ARCHITECTURE (MCA)
M: James Bottomley <James.Bottomley@HansenPartnership.com>
S: Maintained
F: Documentation/mca.txt
F: drivers/mca/
F: include/linux/mca*
MICROTEK X6 SCANNER MICROTEK X6 SCANNER
M: Oliver Neukum <oliver@neukum.name> M: Oliver Neukum <oliver@neukum.name>
S: Maintained S: Maintained
......
...@@ -54,7 +54,6 @@ extern struct cpuinfo_frv __nongprelbss boot_cpu_data; ...@@ -54,7 +54,6 @@ extern struct cpuinfo_frv __nongprelbss boot_cpu_data;
* Bus types * Bus types
*/ */
#define EISA_bus 0 #define EISA_bus 0
#define MCA_bus 0
struct thread_struct { struct thread_struct {
struct pt_regs *frame; /* [GR28] exception frame ptr for this thread */ struct pt_regs *frame; /* [GR28] exception frame ptr for this thread */
......
...@@ -2023,16 +2023,6 @@ config EISA ...@@ -2023,16 +2023,6 @@ config EISA
source "drivers/eisa/Kconfig" source "drivers/eisa/Kconfig"
config MCA
bool "MCA support"
---help---
MicroChannel Architecture is found in some IBM PS/2 machines and
laptops. It is a bus system similar to PCI or ISA. See
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
source "drivers/mca/Kconfig"
config SCx200 config SCx200
tristate "NatSemi SCx200 support" tristate "NatSemi SCx200 support"
---help--- ---help---
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* Platform specific MCA defines */
#ifndef _ASM_X86_MCA_H
#define _ASM_X86_MCA_H
/* Maximal number of MCA slots - actually, some machines have less, but
* they all have sufficient number of POS registers to cover 8.
*/
#define MCA_MAX_SLOT_NR 8
/* Most machines have only one MCA bus. The only multiple bus machines
* I know have at most two */
#define MAX_MCA_BUSSES 2
#define MCA_PRIMARY_BUS 0
#define MCA_SECONDARY_BUS 1
/* Dummy slot numbers on primary MCA for integrated functions */
#define MCA_INTEGSCSI (MCA_MAX_SLOT_NR)
#define MCA_INTEGVIDEO (MCA_MAX_SLOT_NR+1)
#define MCA_MOTHERBOARD (MCA_MAX_SLOT_NR+2)
/* Dummy POS values for integrated functions */
#define MCA_DUMMY_POS_START 0x10000
#define MCA_INTEGSCSI_POS (MCA_DUMMY_POS_START+1)
#define MCA_INTEGVIDEO_POS (MCA_DUMMY_POS_START+2)
#define MCA_MOTHERBOARD_POS (MCA_DUMMY_POS_START+3)
/* MCA registers */
#define MCA_MOTHERBOARD_SETUP_REG 0x94
#define MCA_ADAPTER_SETUP_REG 0x96
#define MCA_POS_REG(n) (0x100+(n))
#define MCA_ENABLED 0x01 /* POS 2, set if adapter enabled */
/* Max number of adapters, including both slots and various integrated
* things.
*/
#define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3)
#endif /* _ASM_X86_MCA_H */
#ifndef _ASM_X86_MCA_DMA_H
#define _ASM_X86_MCA_DMA_H
#include <asm/io.h>
#include <linux/ioport.h>
/*
* Microchannel specific DMA stuff. DMA on an MCA machine is fairly similar to
* standard PC dma, but it certainly has its quirks. DMA register addresses
* are in a different place and there are some added functions. Most of this
* should be pretty obvious on inspection. Note that the user must divide
* count by 2 when using 16-bit dma; that is not handled by these functions.
*
* Ramen Noodles are yummy.
*
* 1998 Tymm Twillman <tymm@computer.org>
*/
/*
* Registers that are used by the DMA controller; FN is the function register
* (tell the controller what to do) and EXE is the execution register (how
* to do it)
*/
#define MCA_DMA_REG_FN 0x18
#define MCA_DMA_REG_EXE 0x1A
/*
* Functions that the DMA controller can do
*/
#define MCA_DMA_FN_SET_IO 0x00
#define MCA_DMA_FN_SET_ADDR 0x20
#define MCA_DMA_FN_GET_ADDR 0x30
#define MCA_DMA_FN_SET_COUNT 0x40
#define MCA_DMA_FN_GET_COUNT 0x50
#define MCA_DMA_FN_GET_STATUS 0x60
#define MCA_DMA_FN_SET_MODE 0x70
#define MCA_DMA_FN_SET_ARBUS 0x80
#define MCA_DMA_FN_MASK 0x90
#define MCA_DMA_FN_RESET_MASK 0xA0
#define MCA_DMA_FN_MASTER_CLEAR 0xD0
/*
* Modes (used by setting MCA_DMA_FN_MODE in the function register)
*
* Note that the MODE_READ is read from memory (write to device), and
* MODE_WRITE is vice-versa.
*/
#define MCA_DMA_MODE_XFER 0x04 /* read by default */
#define MCA_DMA_MODE_READ 0x04 /* same as XFER */
#define MCA_DMA_MODE_WRITE 0x08 /* OR with MODE_XFER to use */
#define MCA_DMA_MODE_IO 0x01 /* DMA from IO register */
#define MCA_DMA_MODE_16 0x40 /* 16 bit xfers */
/**
* mca_enable_dma - channel to enable DMA on
* @dmanr: DMA channel
*
* Enable the MCA bus DMA on a channel. This can be called from
* IRQ context.
*/
static inline void mca_enable_dma(unsigned int dmanr)
{
outb(MCA_DMA_FN_RESET_MASK | dmanr, MCA_DMA_REG_FN);
}
/**
* mca_disble_dma - channel to disable DMA on
* @dmanr: DMA channel
*
* Enable the MCA bus DMA on a channel. This can be called from
* IRQ context.
*/
static inline void mca_disable_dma(unsigned int dmanr)
{
outb(MCA_DMA_FN_MASK | dmanr, MCA_DMA_REG_FN);
}
/**
* mca_set_dma_addr - load a 24bit DMA address
* @dmanr: DMA channel
* @a: 24bit bus address
*
* Load the address register in the DMA controller. This has a 24bit
* limitation (16Mb).
*/
static inline void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
{
outb(MCA_DMA_FN_SET_ADDR | dmanr, MCA_DMA_REG_FN);
outb(a & 0xff, MCA_DMA_REG_EXE);
outb((a >> 8) & 0xff, MCA_DMA_REG_EXE);
outb((a >> 16) & 0xff, MCA_DMA_REG_EXE);
}
/**
* mca_get_dma_addr - load a 24bit DMA address
* @dmanr: DMA channel
*
* Read the address register in the DMA controller. This has a 24bit
* limitation (16Mb). The return is a bus address.
*/
static inline unsigned int mca_get_dma_addr(unsigned int dmanr)
{
unsigned int addr;
outb(MCA_DMA_FN_GET_ADDR | dmanr, MCA_DMA_REG_FN);
addr = inb(MCA_DMA_REG_EXE);
addr |= inb(MCA_DMA_REG_EXE) << 8;
addr |= inb(MCA_DMA_REG_EXE) << 16;
return addr;
}
/**
* mca_set_dma_count - load a 16bit transfer count
* @dmanr: DMA channel
* @count: count
*
* Set the DMA count for this channel. This can be up to 64Kbytes.
* Setting a count of zero will not do what you expect.
*/
static inline void mca_set_dma_count(unsigned int dmanr, unsigned int count)
{
count--; /* transfers one more than count -- correct for this */
outb(MCA_DMA_FN_SET_COUNT | dmanr, MCA_DMA_REG_FN);
outb(count & 0xff, MCA_DMA_REG_EXE);
outb((count >> 8) & 0xff, MCA_DMA_REG_EXE);
}
/**
* mca_get_dma_residue - get the remaining bytes to transfer
* @dmanr: DMA channel
*
* This function returns the number of bytes left to transfer
* on this DMA channel.
*/
static inline unsigned int mca_get_dma_residue(unsigned int dmanr)
{
unsigned short count;
outb(MCA_DMA_FN_GET_COUNT | dmanr, MCA_DMA_REG_FN);
count = 1 + inb(MCA_DMA_REG_EXE);
count += inb(MCA_DMA_REG_EXE) << 8;
return count;
}
/**
* mca_set_dma_io - set the port for an I/O transfer
* @dmanr: DMA channel
* @io_addr: an I/O port number
*
* Unlike the ISA bus DMA controllers the DMA on MCA bus can transfer
* with an I/O port target.
*/
static inline void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
{
/*
* DMA from a port address -- set the io address
*/
outb(MCA_DMA_FN_SET_IO | dmanr, MCA_DMA_REG_FN);
outb(io_addr & 0xff, MCA_DMA_REG_EXE);
outb((io_addr >> 8) & 0xff, MCA_DMA_REG_EXE);
}
/**
* mca_set_dma_mode - set the DMA mode
* @dmanr: DMA channel
* @mode: mode to set
*
* The DMA controller supports several modes. The mode values you can
* set are-
*
* %MCA_DMA_MODE_READ when reading from the DMA device.
*
* %MCA_DMA_MODE_WRITE to writing to the DMA device.
*
* %MCA_DMA_MODE_IO to do DMA to or from an I/O port.
*
* %MCA_DMA_MODE_16 to do 16bit transfers.
*/
static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
{
outb(MCA_DMA_FN_SET_MODE | dmanr, MCA_DMA_REG_FN);
outb(mode, MCA_DMA_REG_EXE);
}
#endif /* _ASM_X86_MCA_DMA_H */
...@@ -40,7 +40,7 @@ extern int quad_local_to_mp_bus_id [NR_CPUS/4][4]; ...@@ -40,7 +40,7 @@ extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
#if defined(CONFIG_MCA) || defined(CONFIG_EISA) #ifdef CONFIG_EISA
extern int mp_bus_id_to_type[MAX_MP_BUSSES]; extern int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif #endif
......
...@@ -84,7 +84,7 @@ struct mpc_bus { ...@@ -84,7 +84,7 @@ struct mpc_bus {
#define BUSTYPE_EISA "EISA" #define BUSTYPE_EISA "EISA"
#define BUSTYPE_ISA "ISA" #define BUSTYPE_ISA "ISA"
#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ #define BUSTYPE_INTERN "INTERN" /* Internal BUS */
#define BUSTYPE_MCA "MCA" #define BUSTYPE_MCA "MCA" /* Obsolete */
#define BUSTYPE_VL "VL" /* Local bus */ #define BUSTYPE_VL "VL" /* Local bus */
#define BUSTYPE_PCI "PCI" #define BUSTYPE_PCI "PCI"
#define BUSTYPE_PCMCIA "PCMCIA" #define BUSTYPE_PCMCIA "PCMCIA"
...@@ -169,6 +169,5 @@ enum mp_bustype { ...@@ -169,6 +169,5 @@ enum mp_bustype {
MP_BUS_ISA = 1, MP_BUS_ISA = 1,
MP_BUS_EISA, MP_BUS_EISA,
MP_BUS_PCI, MP_BUS_PCI,
MP_BUS_MCA,
}; };
#endif /* _ASM_X86_MPSPEC_DEF_H */ #endif /* _ASM_X86_MPSPEC_DEF_H */
...@@ -49,7 +49,6 @@ obj-y += cpu/ ...@@ -49,7 +49,6 @@ obj-y += cpu/
obj-y += acpi/ obj-y += acpi/
obj-y += reboot.o obj-y += reboot.o
obj-$(CONFIG_X86_32) += reboot_32.o obj-$(CONFIG_X86_32) += reboot_32.o
obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_PCI) += early-quirks.o obj-$(CONFIG_PCI) += early-quirks.o
......
...@@ -990,7 +990,7 @@ void __init mp_config_acpi_legacy_irqs(void) ...@@ -990,7 +990,7 @@ void __init mp_config_acpi_legacy_irqs(void)
int i; int i;
struct mpc_intsrc mp_irq; struct mpc_intsrc mp_irq;
#if defined (CONFIG_MCA) || defined (CONFIG_EISA) #ifdef CONFIG_EISA
/* /*
* Fabricate the legacy ISA bus (bus #31). * Fabricate the legacy ISA bus (bus #31).
*/ */
......
...@@ -142,7 +142,7 @@ int mp_irq_entries; ...@@ -142,7 +142,7 @@ int mp_irq_entries;
/* GSI interrupts */ /* GSI interrupts */
static int nr_irqs_gsi = NR_IRQS_LEGACY; static int nr_irqs_gsi = NR_IRQS_LEGACY;
#if defined (CONFIG_MCA) || defined (CONFIG_EISA) #ifdef CONFIG_EISA
int mp_bus_id_to_type[MAX_MP_BUSSES]; int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif #endif
...@@ -875,7 +875,7 @@ static int __init find_isa_irq_apic(int irq, int type) ...@@ -875,7 +875,7 @@ static int __init find_isa_irq_apic(int irq, int type)
return -1; return -1;
} }
#if defined(CONFIG_EISA) || defined(CONFIG_MCA) #ifdef CONFIG_EISA
/* /*
* EISA Edge/Level control register, ELCR * EISA Edge/Level control register, ELCR
*/ */
...@@ -912,12 +912,6 @@ static int EISA_ELCR(unsigned int irq) ...@@ -912,12 +912,6 @@ static int EISA_ELCR(unsigned int irq)
#define default_PCI_trigger(idx) (1) #define default_PCI_trigger(idx) (1)
#define default_PCI_polarity(idx) (1) #define default_PCI_polarity(idx) (1)
/* MCA interrupts are always polarity zero level triggered,
* when listed as conforming in the MP table. */
#define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) default_ISA_polarity(idx)
static int irq_polarity(int idx) static int irq_polarity(int idx)
{ {
int bus = mp_irqs[idx].srcbus; int bus = mp_irqs[idx].srcbus;
...@@ -975,7 +969,7 @@ static int irq_trigger(int idx) ...@@ -975,7 +969,7 @@ static int irq_trigger(int idx)
trigger = default_ISA_trigger(idx); trigger = default_ISA_trigger(idx);
else else
trigger = default_PCI_trigger(idx); trigger = default_PCI_trigger(idx);
#if defined(CONFIG_EISA) || defined(CONFIG_MCA) #ifdef CONFIG_EISA
switch (mp_bus_id_to_type[bus]) { switch (mp_bus_id_to_type[bus]) {
case MP_BUS_ISA: /* ISA pin */ case MP_BUS_ISA: /* ISA pin */
{ {
...@@ -992,11 +986,6 @@ static int irq_trigger(int idx) ...@@ -992,11 +986,6 @@ static int irq_trigger(int idx)
/* set before the switch */ /* set before the switch */
break; break;
} }
case MP_BUS_MCA: /* MCA pin */
{
trigger = default_MCA_trigger(idx);
break;
}
default: default:
{ {
printk(KERN_WARNING "broken BIOS!!\n"); printk(KERN_WARNING "broken BIOS!!\n");
......
/*
* Written by Martin Kolinek, February 1996
*
* Changes:
*
* Chris Beauregard July 28th, 1996
* - Fixed up integrated SCSI detection
*
* Chris Beauregard August 3rd, 1996
* - Made mca_info local
* - Made integrated registers accessible through standard function calls
* - Added name field
* - More sanity checking
*
* Chris Beauregard August 9th, 1996
* - Rewrote /proc/mca
*
* Chris Beauregard January 7th, 1997
* - Added basic NMI-processing
* - Added more information to mca_info structure
*
* David Weinehall October 12th, 1998
* - Made a lot of cleaning up in the source
* - Added use of save_flags / restore_flags
* - Added the 'driver_loaded' flag in MCA_adapter
* - Added an alternative implemention of ZP Gu's mca_find_unused_adapter
*
* David Weinehall March 24th, 1999
* - Fixed the output of 'Driver Installed' in /proc/mca/pos
* - Made the Integrated Video & SCSI show up even if they have id 0000
*
* Alexander Viro November 9th, 1999
* - Switched to regular procfs methods
*
* Alfred Arnold & David Weinehall August 23rd, 2000
* - Added support for Planar POS-registers
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mca.h>
#include <linux/kprobes.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/proc_fs.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <linux/init.h>
static unsigned char which_scsi;
int MCA_bus;
EXPORT_SYMBOL(MCA_bus);
/*
* Motherboard register spinlock. Untested on SMP at the moment, but
* are there any MCA SMP boxes?
*
* Yes - Alan
*/
static DEFINE_SPINLOCK(mca_lock);
/* Build the status info for the adapter */
static void mca_configure_adapter_status(struct mca_device *mca_dev)
{
mca_dev->status = MCA_ADAPTER_NONE;
mca_dev->pos_id = mca_dev->pos[0]
+ (mca_dev->pos[1] << 8);
if (!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
/*
* id = 0x0000 usually indicates hardware failure,
* however, ZP Gu (zpg@castle.net> reports that his 9556
* has 0x0000 as id and everything still works. There
* also seem to be an adapter with id = 0x0000; the
* NCR Parallel Bus Memory Card. Until this is confirmed,
* however, this code will stay.
*/
mca_dev->status = MCA_ADAPTER_ERROR;
return;
} else if (mca_dev->pos_id != 0xffff) {
/*
* 0xffff usually indicates that there's no adapter,
* however, some integrated adapters may have 0xffff as
* their id and still be valid. Examples are on-board
* VGA of the 55sx, the integrated SCSI of the 56 & 57,
* and possibly also the 95 ULTIMEDIA.
*/
mca_dev->status = MCA_ADAPTER_NORMAL;
}
if ((mca_dev->pos_id == 0xffff ||
mca_dev->pos_id == 0x0000) && mca_dev->slot >= MCA_MAX_SLOT_NR) {
int j;
for (j = 2; j < 8; j++) {
if (mca_dev->pos[j] != 0xff) {
mca_dev->status = MCA_ADAPTER_NORMAL;
break;
}
}
}
if (!(mca_dev->pos[2] & MCA_ENABLED)) {
/* enabled bit is in POS 2 */
mca_dev->status = MCA_ADAPTER_DISABLED;
}
} /* mca_configure_adapter_status */
/*--------------------------------------------------------------------*/
static struct resource mca_standard_resources[] = {
{ .start = 0x60, .end = 0x60, .name = "system control port B (MCA)" },
{ .start = 0x90, .end = 0x90, .name = "arbitration (MCA)" },
{ .start = 0x91, .end = 0x91, .name = "card Select Feedback (MCA)" },
{ .start = 0x92, .end = 0x92, .name = "system Control port A (MCA)" },
{ .start = 0x94, .end = 0x94, .name = "system board setup (MCA)" },
{ .start = 0x96, .end = 0x97, .name = "POS (MCA)" },
{ .start = 0x100, .end = 0x107, .name = "POS (MCA)" }
};
#define MCA_STANDARD_RESOURCES ARRAY_SIZE(mca_standard_resources)
/*
* mca_read_and_store_pos - read the POS registers into a memory buffer
* @pos: a char pointer to 8 bytes, contains the POS register value on
* successful return
*
* Returns 1 if a card actually exists (i.e. the pos isn't
* all 0xff) or 0 otherwise
*/
static int mca_read_and_store_pos(unsigned char *pos)
{
int j;
int found = 0;
for (j = 0; j < 8; j++) {
pos[j] = inb_p(MCA_POS_REG(j));
if (pos[j] != 0xff) {
/* 0xff all across means no device. 0x00 means
* something's broken, but a device is
* probably there. However, if you get 0x00
* from a motherboard register it won't matter
* what we find. For the record, on the
* 57SLC, the integrated SCSI adapter has
* 0xffff for the adapter ID, but nonzero for
* other registers. */
found = 1;
}
}
return found;
}
static unsigned char mca_pc_read_pos(struct mca_device *mca_dev, int reg)
{
unsigned char byte;
unsigned long flags;
if (reg < 0 || reg >= 8)
return 0;
spin_lock_irqsave(&mca_lock, flags);
if (mca_dev->pos_register) {
/* Disable adapter setup, enable motherboard setup */
outb_p(0, MCA_ADAPTER_SETUP_REG);
outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
byte = inb_p(MCA_POS_REG(reg));
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
} else {
/* Make sure motherboard setup is off */
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
/* Read the appropriate register */
outb_p(0x8|(mca_dev->slot & 0xf), MCA_ADAPTER_SETUP_REG);
byte = inb_p(MCA_POS_REG(reg));
outb_p(0, MCA_ADAPTER_SETUP_REG);
}
spin_unlock_irqrestore(&mca_lock, flags);
mca_dev->pos[reg] = byte;
return byte;
}
static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
unsigned char byte)
{
unsigned long flags;
if (reg < 0 || reg >= 8)
return;
spin_lock_irqsave(&mca_lock, flags);
/* Make sure motherboard setup is off */
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
/* Read in the appropriate register */
outb_p(0x8|(mca_dev->slot&0xf), MCA_ADAPTER_SETUP_REG);
outb_p(byte, MCA_POS_REG(reg));
outb_p(0, MCA_ADAPTER_SETUP_REG);
spin_unlock_irqrestore(&mca_lock, flags);
/* Update the global register list, while we have the byte */
mca_dev->pos[reg] = byte;
}
/* for the primary MCA bus, we have identity transforms */
static int mca_dummy_transform_irq(struct mca_device *mca_dev, int irq)
{
return irq;
}
static int mca_dummy_transform_ioport(struct mca_device *mca_dev, int port)
{
return port;
}
static void *mca_dummy_transform_memory(struct mca_device *mca_dev, void *mem)
{
return mem;
}
static int __init mca_init(void)
{
unsigned int i, j;
struct mca_device *mca_dev;
unsigned char pos[8];
short mca_builtin_scsi_ports[] = {0xf7, 0xfd, 0x00};
struct mca_bus *bus;
/*
* WARNING: Be careful when making changes here. Putting an adapter
* and the motherboard simultaneously into setup mode may result in
* damage to chips (according to The Indispensable PC Hardware Book
* by Hans-Peter Messmer). Also, we disable system interrupts (so
* that we are not disturbed in the middle of this).
*/
/* Make sure the MCA bus is present */
if (mca_system_init()) {
printk(KERN_ERR "MCA bus system initialisation failed\n");
return -ENODEV;
}
if (!MCA_bus)
return -ENODEV;
printk(KERN_INFO "Micro Channel bus detected.\n");
/* All MCA systems have at least a primary bus */
bus = mca_attach_bus(MCA_PRIMARY_BUS);
if (!bus)
goto out_nomem;
bus->default_dma_mask = 0xffffffffLL;
bus->f.mca_write_pos = mca_pc_write_pos;
bus->f.mca_read_pos = mca_pc_read_pos;
bus->f.mca_transform_irq = mca_dummy_transform_irq;
bus->f.mca_transform_ioport = mca_dummy_transform_ioport;
bus->f.mca_transform_memory = mca_dummy_transform_memory;
/* get the motherboard device */
mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
if (unlikely(!mca_dev))
goto out_nomem;
/*
* We do not expect many MCA interrupts during initialization,
* but let us be safe:
*/
spin_lock_irq(&mca_lock);
/* Make sure adapter setup is off */
outb_p(0, MCA_ADAPTER_SETUP_REG);
/* Read motherboard POS registers */
mca_dev->pos_register = 0x7f;
outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
mca_dev->name[0] = 0;
mca_read_and_store_pos(mca_dev->pos);
mca_configure_adapter_status(mca_dev);
/* fake POS and slot for a motherboard */
mca_dev->pos_id = MCA_MOTHERBOARD_POS;
mca_dev->slot = MCA_MOTHERBOARD;
mca_register_device(MCA_PRIMARY_BUS, mca_dev);
mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if (unlikely(!mca_dev))
goto out_unlock_nomem;
/* Put motherboard into video setup mode, read integrated video
* POS registers, and turn motherboard setup off.
*/
mca_dev->pos_register = 0xdf;
outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
mca_dev->name[0] = 0;
mca_read_and_store_pos(mca_dev->pos);
mca_configure_adapter_status(mca_dev);
/* fake POS and slot for the integrated video */
mca_dev->pos_id = MCA_INTEGVIDEO_POS;
mca_dev->slot = MCA_INTEGVIDEO;
mca_register_device(MCA_PRIMARY_BUS, mca_dev);
/*
* Put motherboard into scsi setup mode, read integrated scsi
* POS registers, and turn motherboard setup off.
*
* It seems there are two possible SCSI registers. Martin says that
* for the 56,57, 0xf7 is the one, but fails on the 76.
* Alfredo (apena@vnet.ibm.com) says
* 0xfd works on his machine. We'll try both of them. I figure it's
* a good bet that only one could be valid at a time. This could
* screw up though if one is used for something else on the other
* machine.
*/
for (i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
outb_p(which_scsi, MCA_MOTHERBOARD_SETUP_REG);
if (mca_read_and_store_pos(pos))
break;
}
if (which_scsi) {
/* found a scsi card */
mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if (unlikely(!mca_dev))
goto out_unlock_nomem;
for (j = 0; j < 8; j++)
mca_dev->pos[j] = pos[j];
mca_configure_adapter_status(mca_dev);
/* fake POS and slot for integrated SCSI controller */
mca_dev->pos_id = MCA_INTEGSCSI_POS;
mca_dev->slot = MCA_INTEGSCSI;
mca_dev->pos_register = which_scsi;
mca_register_device(MCA_PRIMARY_BUS, mca_dev);
}
/* Turn off motherboard setup */
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
/*
* Now loop over MCA slots: put each adapter into setup mode, and
* read its POS registers. Then put adapter setup off.
*/
for (i = 0; i < MCA_MAX_SLOT_NR; i++) {
outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
if (!mca_read_and_store_pos(pos))
continue;
mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if (unlikely(!mca_dev))
goto out_unlock_nomem;
for (j = 0; j < 8; j++)
mca_dev->pos[j] = pos[j];
mca_dev->driver_loaded = 0;
mca_dev->slot = i;
mca_dev->pos_register = 0;
mca_configure_adapter_status(mca_dev);
mca_register_device(MCA_PRIMARY_BUS, mca_dev);
}
outb_p(0, MCA_ADAPTER_SETUP_REG);
/* Enable interrupts and return memory start */
spin_unlock_irq(&mca_lock);
for (i = 0; i < MCA_STANDARD_RESOURCES; i++)
request_resource(&ioport_resource, mca_standard_resources + i);
mca_do_proc_init();
return 0;
out_unlock_nomem:
spin_unlock_irq(&mca_lock);
out_nomem:
printk(KERN_EMERG "Failed memory allocation in MCA setup!\n");
return -ENOMEM;
}
subsys_initcall(mca_init);
/*--------------------------------------------------------------------*/
static __kprobes void
mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
{
int slot = mca_dev->slot;
if (slot == MCA_INTEGSCSI) {
printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n",
mca_dev->name);
} else if (slot == MCA_INTEGVIDEO) {
printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n",
mca_dev->name);
} else if (slot == MCA_MOTHERBOARD) {
printk(KERN_CRIT "NMI: caused by motherboard (%s)\n",
mca_dev->name);
}
/* More info available in POS 6 and 7? */
if (check_flag) {
unsigned char pos6, pos7;
pos6 = mca_device_read_pos(mca_dev, 6);
pos7 = mca_device_read_pos(mca_dev, 7);
printk(KERN_CRIT "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);
}
} /* mca_handle_nmi_slot */
/*--------------------------------------------------------------------*/
static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
{
struct mca_device *mca_dev = to_mca_device(dev);
unsigned char pos5;
pos5 = mca_device_read_pos(mca_dev, 5);
if (!(pos5 & 0x80)) {
/*
* Bit 7 of POS 5 is reset when this adapter has a hardware
* error. Bit 7 it reset if there's error information
* available in POS 6 and 7.
*/
mca_handle_nmi_device(mca_dev, !(pos5 & 0x40));
return 1;
}
return 0;
}
void __kprobes mca_handle_nmi(void)
{
/*
* First try - scan the various adapters and see if a specific
* adapter was responsible for the error.
*/
bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback);
}
...@@ -97,7 +97,7 @@ static void __init MP_bus_info(struct mpc_bus *m) ...@@ -97,7 +97,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
set_bit(m->busid, mp_bus_not_pci); set_bit(m->busid, mp_bus_not_pci);
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) { if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
#if defined(CONFIG_EISA) || defined(CONFIG_MCA) #ifdef CONFIG_EISA
mp_bus_id_to_type[m->busid] = MP_BUS_ISA; mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
#endif #endif
} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
...@@ -105,12 +105,10 @@ static void __init MP_bus_info(struct mpc_bus *m) ...@@ -105,12 +105,10 @@ static void __init MP_bus_info(struct mpc_bus *m)
x86_init.mpparse.mpc_oem_pci_bus(m); x86_init.mpparse.mpc_oem_pci_bus(m);
clear_bit(m->busid, mp_bus_not_pci); clear_bit(m->busid, mp_bus_not_pci);
#if defined(CONFIG_EISA) || defined(CONFIG_MCA) #ifdef CONFIG_EISA
mp_bus_id_to_type[m->busid] = MP_BUS_PCI; mp_bus_id_to_type[m->busid] = MP_BUS_PCI;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) { } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
mp_bus_id_to_type[m->busid] = MP_BUS_EISA; mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
mp_bus_id_to_type[m->busid] = MP_BUS_MCA;
#endif #endif
} else } else
printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
...@@ -368,9 +366,6 @@ static void __init construct_ioapic_table(int mpc_default_type) ...@@ -368,9 +366,6 @@ static void __init construct_ioapic_table(int mpc_default_type)
case 3: case 3:
memcpy(bus.bustype, "EISA ", 6); memcpy(bus.bustype, "EISA ", 6);
break; break;
case 4:
case 7:
memcpy(bus.bustype, "MCA ", 6);
} }
MP_bus_info(&bus); MP_bus_info(&bus);
if (mpc_default_type > 4) { if (mpc_default_type > 4) {
...@@ -623,7 +618,7 @@ void __init default_find_smp_config(void) ...@@ -623,7 +618,7 @@ void __init default_find_smp_config(void)
return; return;
/* /*
* If it is an SMP machine we should know now, unless the * If it is an SMP machine we should know now, unless the
* configuration is in an EISA/MCA bus machine with an * configuration is in an EISA bus machine with an
* extended bios data area. * extended bios data area.
* *
* there is a real-mode segmented pointer pointing to the * there is a real-mode segmented pointer pointing to the
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/mca.h>
#if defined(CONFIG_EDAC) #if defined(CONFIG_EDAC)
#include <linux/edac.h> #include <linux/edac.h>
#endif #endif
...@@ -282,16 +280,6 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) ...@@ -282,16 +280,6 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
__this_cpu_add(nmi_stats.unknown, 1); __this_cpu_add(nmi_stats.unknown, 1);
#ifdef CONFIG_MCA
/*
* Might actually be able to figure out what the guilty party
* is:
*/
if (MCA_bus) {
mca_handle_nmi();
return;
}
#endif
pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
reason, smp_processor_id()); reason, smp_processor_id());
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/mca.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -179,12 +178,6 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1}; ...@@ -179,12 +178,6 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};
/* common cpu data for all cpus */ /* common cpu data for all cpus */
struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1}; struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1};
EXPORT_SYMBOL(boot_cpu_data); EXPORT_SYMBOL(boot_cpu_data);
static void set_mca_bus(int x)
{
#ifdef CONFIG_MCA
MCA_bus = x;
#endif
}
unsigned int def_to_bigsmp; unsigned int def_to_bigsmp;
...@@ -717,7 +710,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -717,7 +710,6 @@ void __init setup_arch(char **cmdline_p)
apm_info.bios = boot_params.apm_bios_info; apm_info.bios = boot_params.apm_bios_info;
ist_info = boot_params.ist_info; ist_info = boot_params.ist_info;
if (boot_params.sys_desc_table.length != 0) { if (boot_params.sys_desc_table.length != 0) {
set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
machine_id = boot_params.sys_desc_table.table[0]; machine_id = boot_params.sys_desc_table.table[0];
machine_submodel_id = boot_params.sys_desc_table.table[1]; machine_submodel_id = boot_params.sys_desc_table.table[1];
BIOS_revision = boot_params.sys_desc_table.table[2]; BIOS_revision = boot_params.sys_desc_table.table[2];
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/i8253.h> #include <linux/i8253.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/mca.h>
#include <asm/vsyscall.h> #include <asm/vsyscall.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
...@@ -58,11 +57,6 @@ EXPORT_SYMBOL(profile_pc); ...@@ -58,11 +57,6 @@ EXPORT_SYMBOL(profile_pc);
static irqreturn_t timer_interrupt(int irq, void *dev_id) static irqreturn_t timer_interrupt(int irq, void *dev_id)
{ {
global_clock_event->event_handler(global_clock_event); global_clock_event->event_handler(global_clock_event);
/* MCA bus quirk: Acknowledge irq0 by setting bit 7 in port 0x61 */
if (MCA_bus)
outb_p(inb_p(0x61)| 0x80, 0x61);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -37,10 +37,6 @@ ...@@ -37,10 +37,6 @@
#include <linux/eisa.h> #include <linux/eisa.h>
#endif #endif
#ifdef CONFIG_MCA
#include <linux/mca.h>
#endif
#if defined(CONFIG_EDAC) #if defined(CONFIG_EDAC)
#include <linux/edac.h> #include <linux/edac.h>
#endif #endif
......
...@@ -92,7 +92,6 @@ obj-$(CONFIG_BT) += bluetooth/ ...@@ -92,7 +92,6 @@ obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_ACCESSIBILITY) += accessibility/ obj-$(CONFIG_ACCESSIBILITY) += accessibility/
obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_ISDN) += isdn/
obj-$(CONFIG_EDAC) += edac/ obj-$(CONFIG_EDAC) += edac/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/ obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_CPU_FREQ) += cpufreq/
......
config MCA_LEGACY
bool "Legacy MCA API Support"
depends on MCA
help
This compiles in support for the old slot based MCA API. If you
have an unconverted MCA driver, you will need to say Y here. It
is safe to say Y anyway.
config MCA_PROC_FS
bool "Support for the mca entry in /proc"
depends on MCA_LEGACY && PROC_FS
help
If you want the old style /proc/mca directory in addition to the
new style sysfs say Y here.
# Makefile for the Linux MCA bus support
obj-y := mca-bus.o mca-device.o mca-driver.o
obj-$(CONFIG_MCA_PROC_FS) += mca-proc.o
obj-$(CONFIG_MCA_LEGACY) += mca-legacy.o
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA bus support functions for sysfs.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mca.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
/* Very few machines have more than one MCA bus. However, there are
* those that do (Voyager 35xx/5xxx), so we do it this way for future
* expansion. None that I know have more than 2 */
static struct mca_bus *mca_root_busses[MAX_MCA_BUSSES];
#define MCA_DEVINFO(i,s) { .pos = i, .name = s }
struct mca_device_info {
short pos_id; /* the 2 byte pos id for this card */
char name[50];
};
static int mca_bus_match (struct device *dev, struct device_driver *drv)
{
struct mca_device *mca_dev = to_mca_device (dev);
struct mca_driver *mca_drv = to_mca_driver (drv);
const unsigned short *mca_ids = mca_drv->id_table;
int i = 0;
if (mca_ids) {
for(i = 0; mca_ids[i]; i++) {
if (mca_ids[i] == mca_dev->pos_id) {
mca_dev->index = i;
return 1;
}
}
}
/* If the integrated id is present, treat it as though it were an
* additional id in the id_table (it can't be because by definition,
* integrated id's overflow a short */
if (mca_drv->integrated_id && mca_dev->pos_id ==
mca_drv->integrated_id) {
mca_dev->index = i;
return 1;
}
return 0;
}
struct bus_type mca_bus_type = {
.name = "MCA",
.match = mca_bus_match,
};
EXPORT_SYMBOL (mca_bus_type);
static ssize_t mca_show_pos_id(struct device *dev, struct device_attribute *attr, char *buf)
{
/* four digits, \n and trailing \0 */
struct mca_device *mca_dev = to_mca_device(dev);
int len;
if(mca_dev->pos_id < MCA_DUMMY_POS_START)
len = sprintf(buf, "%04x\n", mca_dev->pos_id);
else
len = sprintf(buf, "none\n");
return len;
}
static ssize_t mca_show_pos(struct device *dev, struct device_attribute *attr, char *buf)
{
/* enough for 8 two byte hex chars plus space and new line */
int j, len=0;
struct mca_device *mca_dev = to_mca_device(dev);
for(j=0; j<8; j++)
len += sprintf(buf+len, "%02x ", mca_dev->pos[j]);
/* change last trailing space to new line */
buf[len-1] = '\n';
return len;
}
static DEVICE_ATTR(id, S_IRUGO, mca_show_pos_id, NULL);
static DEVICE_ATTR(pos, S_IRUGO, mca_show_pos, NULL);
int __init mca_register_device(int bus, struct mca_device *mca_dev)
{
struct mca_bus *mca_bus = mca_root_busses[bus];
int rc;
mca_dev->dev.parent = &mca_bus->dev;
mca_dev->dev.bus = &mca_bus_type;
dev_set_name(&mca_dev->dev, "%02d:%02X", bus, mca_dev->slot);
mca_dev->dma_mask = mca_bus->default_dma_mask;
mca_dev->dev.dma_mask = &mca_dev->dma_mask;
mca_dev->dev.coherent_dma_mask = mca_dev->dma_mask;
rc = device_register(&mca_dev->dev);
if (rc)
goto err_out;
rc = device_create_file(&mca_dev->dev, &dev_attr_id);
if (rc) goto err_out_devreg;
rc = device_create_file(&mca_dev->dev, &dev_attr_pos);
if (rc) goto err_out_id;
return 1;
err_out_id:
device_remove_file(&mca_dev->dev, &dev_attr_id);
err_out_devreg:
device_unregister(&mca_dev->dev);
err_out:
return 0;
}
/* */
struct mca_bus * __devinit mca_attach_bus(int bus)
{
struct mca_bus *mca_bus;
if (unlikely(mca_root_busses[bus] != NULL)) {
/* This should never happen, but just in case */
printk(KERN_EMERG "MCA tried to add already existing bus %d\n",
bus);
dump_stack();
return NULL;
}
mca_bus = kzalloc(sizeof(struct mca_bus), GFP_KERNEL);
if (!mca_bus)
return NULL;
dev_set_name(&mca_bus->dev, "mca%d", bus);
sprintf(mca_bus->name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary");
if (device_register(&mca_bus->dev)) {
kfree(mca_bus);
return NULL;
}
mca_root_busses[bus] = mca_bus;
return mca_bus;
}
int __init mca_system_init (void)
{
return bus_register(&mca_bus_type);
}
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA device support functions
*
* These functions support the ongoing device access API.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mca.h>
#include <linux/string.h>
/**
* mca_device_read_stored_pos - read POS register from stored data
* @mca_dev: device to read from
* @reg: register to read from
*
* Fetch a POS value that was stored at boot time by the kernel
* when it scanned the MCA space. The register value is returned.
* Missing or invalid registers report 0.
*/
unsigned char mca_device_read_stored_pos(struct mca_device *mca_dev, int reg)
{
if(reg < 0 || reg >= 8)
return 0;
return mca_dev->pos[reg];
}
EXPORT_SYMBOL(mca_device_read_stored_pos);
/**
* mca_device_read_pos - read POS register from card
* @mca_dev: device to read from
* @reg: register to read from
*
* Fetch a POS value directly from the hardware to obtain the
* current value. This is much slower than
* mca_device_read_stored_pos and may not be invoked from
* interrupt context. It handles the deep magic required for
* onboard devices transparently.
*/
unsigned char mca_device_read_pos(struct mca_device *mca_dev, int reg)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_read_pos(mca_dev, reg);
return mca_dev->pos[reg];
}
EXPORT_SYMBOL(mca_device_read_pos);
/**
* mca_device_write_pos - read POS register from card
* @mca_dev: device to write pos register to
* @reg: register to write to
* @byte: byte to write to the POS registers
*
* Store a POS value directly to the hardware. You should not
* normally need to use this function and should have a very good
* knowledge of MCA bus before you do so. Doing this wrongly can
* damage the hardware.
*
* This function may not be used from interrupt context.
*
*/
void mca_device_write_pos(struct mca_device *mca_dev, int reg,
unsigned char byte)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
mca_bus->f.mca_write_pos(mca_dev, reg, byte);
}
EXPORT_SYMBOL(mca_device_write_pos);
/**
* mca_device_transform_irq - transform the ADF obtained IRQ
* @mca_device: device whose irq needs transforming
* @irq: input irq from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the interrupt number and returns the
* transformed system global interrupt
*/
int mca_device_transform_irq(struct mca_device *mca_dev, int irq)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_irq(mca_dev, irq);
}
EXPORT_SYMBOL(mca_device_transform_irq);
/**
* mca_device_transform_ioport - transform the ADF obtained I/O port
* @mca_device: device whose port needs transforming
* @ioport: input I/O port from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the I/O port number and returns the
* transformed system global port number.
*
* This transformation can be assumed to be linear for port ranges.
*/
int mca_device_transform_ioport(struct mca_device *mca_dev, int port)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_ioport(mca_dev, port);
}
EXPORT_SYMBOL(mca_device_transform_ioport);
/**
* mca_device_transform_memory - transform the ADF obtained memory
* @mca_device: device whose memory region needs transforming
* @mem: memory region start from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the memory region start and returns the
* transformed system global memory region (physical).
*
* This transformation can be assumed to be linear for region ranges.
*/
void *mca_device_transform_memory(struct mca_device *mca_dev, void *mem)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_memory(mca_dev, mem);
}
EXPORT_SYMBOL(mca_device_transform_memory);
/**
* mca_device_claimed - check if claimed by driver
* @mca_dev: device to check
*
* Returns 1 if the slot has been claimed by a driver
*/
int mca_device_claimed(struct mca_device *mca_dev)
{
return mca_dev->driver_loaded;
}
EXPORT_SYMBOL(mca_device_claimed);
/**
* mca_device_set_claim - set the claim value of the driver
* @mca_dev: device to set value for
* @val: claim value to set (1 claimed, 0 unclaimed)
*/
void mca_device_set_claim(struct mca_device *mca_dev, int val)
{
mca_dev->driver_loaded = val;
}
EXPORT_SYMBOL(mca_device_set_claim);
/**
* mca_device_status - get the status of the device
* @mca_device: device to get
*
* returns an enumeration of the device status:
*
* MCA_ADAPTER_NORMAL adapter is OK.
* MCA_ADAPTER_NONE no adapter at device (should never happen).
* MCA_ADAPTER_DISABLED adapter is disabled.
* MCA_ADAPTER_ERROR adapter cannot be initialised.
*/
enum MCA_AdapterStatus mca_device_status(struct mca_device *mca_dev)
{
return mca_dev->status;
}
EXPORT_SYMBOL(mca_device_status);
/**
* mca_device_set_name - set the name of the device
* @mca_device: device to set the name of
* @name: name to set
*/
void mca_device_set_name(struct mca_device *mca_dev, const char *name)
{
if(!mca_dev)
return;
strlcpy(mca_dev->name, name, sizeof(mca_dev->name));
}
EXPORT_SYMBOL(mca_device_set_name);
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA driver support functions for sysfs.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/device.h>
#include <linux/mca.h>
#include <linux/module.h>
int mca_register_driver(struct mca_driver *mca_drv)
{
int r;
if (MCA_bus) {
mca_drv->driver.bus = &mca_bus_type;
if ((r = driver_register(&mca_drv->driver)) < 0)
return r;
mca_drv->integrated_id = 0;
}
return 0;
}
EXPORT_SYMBOL(mca_register_driver);
int mca_register_driver_integrated(struct mca_driver *mca_driver,
int integrated_id)
{
int r = mca_register_driver(mca_driver);
if (!r)
mca_driver->integrated_id = integrated_id;
return r;
}
EXPORT_SYMBOL(mca_register_driver_integrated);
void mca_unregister_driver(struct mca_driver *mca_drv)
{
if (MCA_bus)
driver_unregister(&mca_drv->driver);
}
EXPORT_SYMBOL(mca_unregister_driver);
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA bus support functions for legacy (2.4) API.
*
* Legacy API means the API that operates in terms of MCA slot number
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mca-legacy.h>
#include <asm/io.h>
/* NOTE: This structure is stack allocated */
struct mca_find_adapter_info {
int id;
int slot;
struct mca_device *mca_dev;
};
/* The purpose of this iterator is to loop over all the devices and
* find the one with the smallest slot number that's just greater than
* or equal to the required slot with a matching id */
static int mca_find_adapter_callback(struct device *dev, void *data)
{
struct mca_find_adapter_info *info = data;
struct mca_device *mca_dev = to_mca_device(dev);
if(mca_dev->pos_id != info->id)
return 0;
if(mca_dev->slot < info->slot)
return 0;
if(!info->mca_dev || info->mca_dev->slot >= mca_dev->slot)
info->mca_dev = mca_dev;
return 0;
}
/**
* mca_find_adapter - scan for adapters
* @id: MCA identification to search for
* @start: starting slot
*
* Search the MCA configuration for adapters matching the 16bit
* ID given. The first time it should be called with start as zero
* and then further calls made passing the return value of the
* previous call until %MCA_NOTFOUND is returned.
*
* Disabled adapters are not reported.
*/
int mca_find_adapter(int id, int start)
{
struct mca_find_adapter_info info;
if(id == 0xffff)
return MCA_NOTFOUND;
info.slot = start;
info.id = id;
info.mca_dev = NULL;
for(;;) {
bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
if(info.mca_dev == NULL)
return MCA_NOTFOUND;
if(info.mca_dev->status != MCA_ADAPTER_DISABLED)
break;
/* OK, found adapter but it was disabled. Go around
* again, excluding the slot we just found */
info.slot = info.mca_dev->slot + 1;
info.mca_dev = NULL;
}
return info.mca_dev->slot;
}
EXPORT_SYMBOL(mca_find_adapter);
/*--------------------------------------------------------------------*/
/**
* mca_find_unused_adapter - scan for unused adapters
* @id: MCA identification to search for
* @start: starting slot
*
* Search the MCA configuration for adapters matching the 16bit
* ID given. The first time it should be called with start as zero
* and then further calls made passing the return value of the
* previous call until %MCA_NOTFOUND is returned.
*
* Adapters that have been claimed by drivers and those that
* are disabled are not reported. This function thus allows a driver
* to scan for further cards when some may already be driven.
*/
int mca_find_unused_adapter(int id, int start)
{
struct mca_find_adapter_info info = { 0 };
if (!MCA_bus || id == 0xffff)
return MCA_NOTFOUND;
info.slot = start;
info.id = id;
info.mca_dev = NULL;
for(;;) {
bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
if(info.mca_dev == NULL)
return MCA_NOTFOUND;
if(info.mca_dev->status != MCA_ADAPTER_DISABLED
&& !info.mca_dev->driver_loaded)
break;
/* OK, found adapter but it was disabled or already in
* use. Go around again, excluding the slot we just
* found */
info.slot = info.mca_dev->slot + 1;
info.mca_dev = NULL;
}
return info.mca_dev->slot;
}
EXPORT_SYMBOL(mca_find_unused_adapter);
/* NOTE: stack allocated structure */
struct mca_find_device_by_slot_info {
int slot;
struct mca_device *mca_dev;
};
static int mca_find_device_by_slot_callback(struct device *dev, void *data)
{
struct mca_find_device_by_slot_info *info = data;
struct mca_device *mca_dev = to_mca_device(dev);
if(mca_dev->slot == info->slot)
info->mca_dev = mca_dev;
return 0;
}
struct mca_device *mca_find_device_by_slot(int slot)
{
struct mca_find_device_by_slot_info info;
info.slot = slot;
info.mca_dev = NULL;
bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_device_by_slot_callback);
return info.mca_dev;
}
/**
* mca_read_stored_pos - read POS register from boot data
* @slot: slot number to read from
* @reg: register to read from
*
* Fetch a POS value that was stored at boot time by the kernel
* when it scanned the MCA space. The register value is returned.
* Missing or invalid registers report 0.
*/
unsigned char mca_read_stored_pos(int slot, int reg)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return 0;
return mca_device_read_stored_pos(mca_dev, reg);
}
EXPORT_SYMBOL(mca_read_stored_pos);
/**
* mca_read_pos - read POS register from card
* @slot: slot number to read from
* @reg: register to read from
*
* Fetch a POS value directly from the hardware to obtain the
* current value. This is much slower than mca_read_stored_pos and
* may not be invoked from interrupt context. It handles the
* deep magic required for onboard devices transparently.
*/
unsigned char mca_read_pos(int slot, int reg)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return 0;
return mca_device_read_pos(mca_dev, reg);
}
EXPORT_SYMBOL(mca_read_pos);
/**
* mca_write_pos - read POS register from card
* @slot: slot number to read from
* @reg: register to read from
* @byte: byte to write to the POS registers
*
* Store a POS value directly from the hardware. You should not
* normally need to use this function and should have a very good
* knowledge of MCA bus before you do so. Doing this wrongly can
* damage the hardware.
*
* This function may not be used from interrupt context.
*
* Note that this a technically a Bad Thing, as IBM tech stuff says
* you should only set POS values through their utilities.
* However, some devices such as the 3c523 recommend that you write
* back some data to make sure the configuration is consistent.
* I'd say that IBM is right, but I like my drivers to work.
*
* This function can't do checks to see if multiple devices end up
* with the same resources, so you might see magic smoke if someone
* screws up.
*/
void mca_write_pos(int slot, int reg, unsigned char byte)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return;
mca_device_write_pos(mca_dev, reg, byte);
}
EXPORT_SYMBOL(mca_write_pos);
/**
* mca_set_adapter_name - Set the description of the card
* @slot: slot to name
* @name: text string for the namen
*
* This function sets the name reported via /proc for this
* adapter slot. This is for user information only. Setting a
* name deletes any previous name.
*/
void mca_set_adapter_name(int slot, char* name)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return;
mca_device_set_name(mca_dev, name);
}
EXPORT_SYMBOL(mca_set_adapter_name);
/**
* mca_mark_as_used - claim an MCA device
* @slot: slot to claim
* FIXME: should we make this threadsafe
*
* Claim an MCA slot for a device driver. If the
* slot is already taken the function returns 1,
* if it is not taken it is claimed and 0 is
* returned.
*/
int mca_mark_as_used(int slot)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
/* FIXME: this is actually a severe error */
return 1;
if(mca_device_claimed(mca_dev))
return 1;
mca_device_set_claim(mca_dev, 1);
return 0;
}
EXPORT_SYMBOL(mca_mark_as_used);
/**
* mca_mark_as_unused - release an MCA device
* @slot: slot to claim
*
* Release the slot for other drives to use.
*/
void mca_mark_as_unused(int slot)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return;
mca_device_set_claim(mca_dev, 0);
}
EXPORT_SYMBOL(mca_mark_as_unused);
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA bus support functions for the proc fs.
*
* NOTE: this code *requires* the legacy MCA api.
*
* Legacy API means the API that operates in terms of MCA slot number
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/mca.h>
static int get_mca_info_helper(struct mca_device *mca_dev, char *page, int len)
{
int j;
for(j=0; j<8; j++)
len += sprintf(page+len, "%02x ",
mca_dev ? mca_dev->pos[j] : 0xff);
len += sprintf(page+len, " %s\n", mca_dev ? mca_dev->name : "");
return len;
}
static int get_mca_info(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int i, len = 0;
if(MCA_bus) {
struct mca_device *mca_dev;
/* Format POS registers of eight MCA slots */
for(i=0; i<MCA_MAX_SLOT_NR; i++) {
mca_dev = mca_find_device_by_slot(i);
len += sprintf(page+len, "Slot %d: ", i+1);
len = get_mca_info_helper(mca_dev, page, len);
}
/* Format POS registers of integrated video subsystem */
mca_dev = mca_find_device_by_slot(MCA_INTEGVIDEO);
len += sprintf(page+len, "Video : ");
len = get_mca_info_helper(mca_dev, page, len);
/* Format POS registers of integrated SCSI subsystem */
mca_dev = mca_find_device_by_slot(MCA_INTEGSCSI);
len += sprintf(page+len, "SCSI : ");
len = get_mca_info_helper(mca_dev, page, len);
/* Format POS registers of motherboard */
mca_dev = mca_find_device_by_slot(MCA_MOTHERBOARD);
len += sprintf(page+len, "Planar: ");
len = get_mca_info_helper(mca_dev, page, len);
} else {
/* Leave it empty if MCA not detected - this should *never*
* happen!
*/
}
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*--------------------------------------------------------------------*/
static int mca_default_procfn(char* buf, struct mca_device *mca_dev)
{
int len = 0, i;
int slot = mca_dev->slot;
/* Print out the basic information */
if(slot < MCA_MAX_SLOT_NR) {
len += sprintf(buf+len, "Slot: %d\n", slot+1);
} else if(slot == MCA_INTEGSCSI) {
len += sprintf(buf+len, "Integrated SCSI Adapter\n");
} else if(slot == MCA_INTEGVIDEO) {
len += sprintf(buf+len, "Integrated Video Adapter\n");
} else if(slot == MCA_MOTHERBOARD) {
len += sprintf(buf+len, "Motherboard\n");
}
if (mca_dev->name[0]) {
/* Drivers might register a name without /proc handler... */
len += sprintf(buf+len, "Adapter Name: %s\n",
mca_dev->name);
} else {
len += sprintf(buf+len, "Adapter Name: Unknown\n");
}
len += sprintf(buf+len, "Id: %02x%02x\n",
mca_dev->pos[1], mca_dev->pos[0]);
len += sprintf(buf+len, "Enabled: %s\nPOS: ",
mca_device_status(mca_dev) == MCA_ADAPTER_NORMAL ?
"Yes" : "No");
for(i=0; i<8; i++) {
len += sprintf(buf+len, "%02x ", mca_dev->pos[i]);
}
len += sprintf(buf+len, "\nDriver Installed: %s",
mca_device_claimed(mca_dev) ? "Yes" : "No");
buf[len++] = '\n';
buf[len] = 0;
return len;
} /* mca_default_procfn() */
static int get_mca_machine_info(char* page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = 0;
len += sprintf(page+len, "Model Id: 0x%x\n", machine_id);
len += sprintf(page+len, "Submodel Id: 0x%x\n", machine_submodel_id);
len += sprintf(page+len, "BIOS Revision: 0x%x\n", BIOS_revision);
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
static int mca_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct mca_device *mca_dev = (struct mca_device *)data;
int len = 0;
/* Get the standard info */
len = mca_default_procfn(page, mca_dev);
/* Do any device-specific processing, if there is any */
if(mca_dev->procfn) {
len += mca_dev->procfn(page+len, mca_dev->slot,
mca_dev->proc_dev);
}
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
} /* mca_read_proc() */
/*--------------------------------------------------------------------*/
void __init mca_do_proc_init(void)
{
int i;
struct proc_dir_entry *proc_mca;
struct proc_dir_entry* node = NULL;
struct mca_device *mca_dev;
proc_mca = proc_mkdir("mca", NULL);
create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
/* Initialize /proc/mca entries for existing adapters */
for(i = 0; i < MCA_NUMADAPTERS; i++) {
enum MCA_AdapterStatus status;
mca_dev = mca_find_device_by_slot(i);
if(!mca_dev)
continue;
mca_dev->procfn = NULL;
if(i < MCA_MAX_SLOT_NR) sprintf(mca_dev->procname,"slot%d", i+1);
else if(i == MCA_INTEGVIDEO) sprintf(mca_dev->procname,"video");
else if(i == MCA_INTEGSCSI) sprintf(mca_dev->procname,"scsi");
else if(i == MCA_MOTHERBOARD) sprintf(mca_dev->procname,"planar");
status = mca_device_status(mca_dev);
if (status != MCA_ADAPTER_NORMAL &&
status != MCA_ADAPTER_DISABLED)
continue;
node = create_proc_read_entry(mca_dev->procname, 0, proc_mca,
mca_read_proc, (void *)mca_dev);
if(node == NULL) {
printk("Failed to allocate memory for MCA proc-entries!");
return;
}
}
} /* mca_do_proc_init() */
/**
* mca_set_adapter_procfn - Set the /proc callback
* @slot: slot to configure
* @procfn: callback function to call for /proc
* @dev: device information passed to the callback
*
* This sets up an information callback for /proc/mca/slot?. The
* function is called with the buffer, slot, and device pointer (or
* some equally informative context information, or nothing, if you
* prefer), and is expected to put useful information into the
* buffer. The adapter name, ID, and POS registers get printed
* before this is called though, so don't do it again.
*
* This should be called with a %NULL @procfn when a module
* unregisters, thus preventing kernel crashes and other such
* nastiness.
*/
void mca_set_adapter_procfn(int slot, MCA_ProcFn procfn, void* proc_dev)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return;
mca_dev->procfn = procfn;
mca_dev->proc_dev = proc_dev;
}
EXPORT_SYMBOL(mca_set_adapter_procfn);
...@@ -283,7 +283,6 @@ static char *bus_strings[] = { ...@@ -283,7 +283,6 @@ static char *bus_strings[] = {
"Local Bus", "Local Bus",
"ISA", "ISA",
"EISA", "EISA",
"MCA",
"PCI", "PCI",
"PCMCIA", "PCMCIA",
"NUBUS", "NUBUS",
...@@ -351,18 +350,6 @@ static int i2o_seq_show_hrt(struct seq_file *seq, void *v) ...@@ -351,18 +350,6 @@ static int i2o_seq_show_hrt(struct seq_file *seq, void *v)
EisaSlotNumber); EisaSlotNumber);
break; break;
case I2O_BUS_MCA:
seq_printf(seq, " IOBase: %0#6x,",
hrt->hrt_entry[i].bus.mca_bus.
McaBaseIOPort);
seq_printf(seq, " MemoryBase: %0#10x,",
hrt->hrt_entry[i].bus.mca_bus.
McaBaseMemoryAddress);
seq_printf(seq, " Slot: %0#4x,",
hrt->hrt_entry[i].bus.mca_bus.
McaSlotNumber);
break;
case I2O_BUS_PCI: case I2O_BUS_PCI:
seq_printf(seq, " Bus: %0#4x", seq_printf(seq, " Bus: %0#4x",
hrt->hrt_entry[i].bus.pci_bus. hrt->hrt_entry[i].bus.pci_bus.
......
...@@ -124,7 +124,7 @@ typedef struct i2o_sg_io_hdr { ...@@ -124,7 +124,7 @@ typedef struct i2o_sg_io_hdr {
#define I2O_BUS_LOCAL 0 #define I2O_BUS_LOCAL 0
#define I2O_BUS_ISA 1 #define I2O_BUS_ISA 1
#define I2O_BUS_EISA 2 #define I2O_BUS_EISA 2
#define I2O_BUS_MCA 3 /* was I2O_BUS_MCA 3 */
#define I2O_BUS_PCI 4 #define I2O_BUS_PCI 4
#define I2O_BUS_PCMCIA 5 #define I2O_BUS_PCMCIA 5
#define I2O_BUS_NUBUS 6 #define I2O_BUS_NUBUS 6
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* This is the function prototypes for the old legacy MCA interface
*
* Please move your driver to the new sysfs based one instead */
#ifndef _LINUX_MCA_LEGACY_H
#define _LINUX_MCA_LEGACY_H
#include <linux/mca.h>
#warning "MCA legacy - please move your driver to the new sysfs api"
/* MCA_NOTFOUND is an error condition. The other two indicate
* motherboard POS registers contain the adapter. They might be
* returned by the mca_find_adapter() function, and can be used as
* arguments to mca_read_stored_pos(). I'm not going to allow direct
* access to the motherboard registers until we run across an adapter
* that requires it. We don't know enough about them to know if it's
* safe.
*
* See Documentation/mca.txt or one of the existing drivers for
* more information.
*/
#define MCA_NOTFOUND (-1)
/* Returns the slot of the first enabled adapter matching id. User can
* specify a starting slot beyond zero, to deal with detecting multiple
* devices. Returns MCA_NOTFOUND if id not found. Also checks the
* integrated adapters.
*/
extern int mca_find_adapter(int id, int start);
extern int mca_find_unused_adapter(int id, int start);
extern int mca_mark_as_used(int slot);
extern void mca_mark_as_unused(int slot);
/* gets a byte out of POS register (stored in memory) */
extern unsigned char mca_read_stored_pos(int slot, int reg);
/* This can be expanded later. Right now, it gives us a way of
* getting meaningful information into the MCA_info structure,
* so we can have a more interesting /proc/mca.
*/
extern void mca_set_adapter_name(int slot, char* name);
/* These routines actually mess with the hardware POS registers. They
* temporarily disable the device (and interrupts), so make sure you know
* what you're doing if you use them. Furthermore, writing to a POS may
* result in two devices trying to share a resource, which in turn can
* result in multiple devices sharing memory spaces, IRQs, or even trashing
* hardware. YOU HAVE BEEN WARNED.
*
* You can only access slots with this. Motherboard registers are off
* limits.
*/
/* read a byte from the specified POS register. */
extern unsigned char mca_read_pos(int slot, int reg);
/* write a byte to the specified POS register. */
extern void mca_write_pos(int slot, int reg, unsigned char byte);
#endif
/*
* Header for Microchannel Architecture Bus
* Written by Martin Kolinek, February 1996
*/
#ifndef _LINUX_MCA_H
#define _LINUX_MCA_H
#include <linux/device.h>
#ifdef CONFIG_MCA
#include <asm/mca.h>
extern int MCA_bus;
#else
#define MCA_bus 0
#endif
/* This sets up an information callback for /proc/mca/slot?. The
* function is called with the buffer, slot, and device pointer (or
* some equally informative context information, or nothing, if you
* prefer), and is expected to put useful information into the
* buffer. The adapter name, id, and POS registers get printed
* before this is called though, so don't do it again.
*
* This should be called with a NULL procfn when a module
* unregisters, thus preventing kernel crashes and other such
* nastiness.
*/
typedef int (*MCA_ProcFn)(char* buf, int slot, void* dev);
/* Should only be called by the NMI interrupt handler, this will do some
* fancy stuff to figure out what might have generated a NMI.
*/
extern void mca_handle_nmi(void);
enum MCA_AdapterStatus {
MCA_ADAPTER_NORMAL = 0,
MCA_ADAPTER_NONE = 1,
MCA_ADAPTER_DISABLED = 2,
MCA_ADAPTER_ERROR = 3
};
struct mca_device {
u64 dma_mask;
int pos_id;
int slot;
/* index into id_table, set by the bus match routine */
int index;
/* is there a driver installed? 0 - No, 1 - Yes */
int driver_loaded;
/* POS registers */
unsigned char pos[8];
/* if a pseudo adapter of the motherboard, this is the motherboard
* register value to use for setup cycles */
short pos_register;
enum MCA_AdapterStatus status;
#ifdef CONFIG_MCA_PROC_FS
/* name of the proc/mca file */
char procname[8];
/* /proc info callback */
MCA_ProcFn procfn;
/* device/context info for proc callback */
void *proc_dev;
#endif
struct device dev;
char name[32];
};
#define to_mca_device(mdev) container_of(mdev, struct mca_device, dev)
struct mca_bus_accessor_functions {
unsigned char (*mca_read_pos)(struct mca_device *, int reg);
void (*mca_write_pos)(struct mca_device *, int reg,
unsigned char byte);
int (*mca_transform_irq)(struct mca_device *, int irq);
int (*mca_transform_ioport)(struct mca_device *,
int region);
void * (*mca_transform_memory)(struct mca_device *,
void *memory);
};
struct mca_bus {
u64 default_dma_mask;
int number;
struct mca_bus_accessor_functions f;
struct device dev;
char name[32];
};
#define to_mca_bus(mdev) container_of(mdev, struct mca_bus, dev)
struct mca_driver {
const short *id_table;
void *driver_data;
int integrated_id;
struct device_driver driver;
};
#define to_mca_driver(mdriver) container_of(mdriver, struct mca_driver, driver)
/* Ongoing supported API functions */
extern struct mca_device *mca_find_device_by_slot(int slot);
extern int mca_system_init(void);
extern struct mca_bus *mca_attach_bus(int);
extern unsigned char mca_device_read_stored_pos(struct mca_device *mca_dev,
int reg);
extern unsigned char mca_device_read_pos(struct mca_device *mca_dev, int reg);
extern void mca_device_write_pos(struct mca_device *mca_dev, int reg,
unsigned char byte);
extern int mca_device_transform_irq(struct mca_device *mca_dev, int irq);
extern int mca_device_transform_ioport(struct mca_device *mca_dev, int port);
extern void *mca_device_transform_memory(struct mca_device *mca_dev,
void *mem);
extern int mca_device_claimed(struct mca_device *mca_dev);
extern void mca_device_set_claim(struct mca_device *mca_dev, int val);
extern void mca_device_set_name(struct mca_device *mca_dev, const char *name);
static inline char *mca_device_get_name(struct mca_device *mca_dev)
{
return mca_dev ? mca_dev->name : NULL;
}
extern enum MCA_AdapterStatus mca_device_status(struct mca_device *mca_dev);
extern struct bus_type mca_bus_type;
extern int mca_register_driver(struct mca_driver *drv);
extern int mca_register_driver_integrated(struct mca_driver *, int);
extern void mca_unregister_driver(struct mca_driver *drv);
/* WARNING: only called by the boot time device setup */
extern int mca_register_device(int bus, struct mca_device *mca_dev);
#ifdef CONFIG_MCA_PROC_FS
extern void mca_do_proc_init(void);
extern void mca_set_adapter_procfn(int slot, MCA_ProcFn, void* dev);
#else
static inline void mca_do_proc_init(void)
{
}
static inline void mca_set_adapter_procfn(int slot, MCA_ProcFn fn, void* dev)
{
}
#endif
#endif /* _LINUX_MCA_H */
...@@ -240,7 +240,7 @@ search_help[] = N_( ...@@ -240,7 +240,7 @@ search_help[] = N_(
"Defined at drivers/pci/Kconfig:47\n" "Defined at drivers/pci/Kconfig:47\n"
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
"Location:\n" "Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
" -> PCI support (PCI [=y])\n" " -> PCI support (PCI [=y])\n"
" -> PCI access mode (<choice> [=y])\n" " -> PCI access mode (<choice> [=y])\n"
"Selects: LIBCRC32\n" "Selects: LIBCRC32\n"
......
...@@ -223,7 +223,7 @@ search_help[] = N_( ...@@ -223,7 +223,7 @@ search_help[] = N_(
"Defined at drivers/pci/Kconfig:47\n" "Defined at drivers/pci/Kconfig:47\n"
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
"Location:\n" "Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
" -> PCI support (PCI [ = y])\n" " -> PCI support (PCI [ = y])\n"
" -> PCI access mode (<choice> [ = y])\n" " -> PCI access mode (<choice> [ = y])\n"
"Selects: LIBCRC32\n" "Selects: LIBCRC32\n"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment