Commit d61c31bb authored by Marc Zyngier's avatar Marc Zyngier Committed by Linus Torvalds

[PATCH] EISA/sysfs updates

This is an update to the EISA/sysfs code :

 - Separate bus root code from generic code.
 - Add driver for PCI/EISA bridge.
 - Hacked parisc eisa driver so it can act as a root device.
 - Add driver for so-called virtual root (for bridge-less systems).
 - Allow multiple roots.
 - Moved quirk_eisa_bridge from alpha to generic code, since
   the EISA code needs it now (on x86, for example...).
 - 3c59x :
   Prevent driver from returning ENODEV in case it has registered with
   the EISA framework, but no device has been found yet (it happends
   when the driver is built into the kernel, and the EISA bus root has
   not been discovered yet).

It's been discussed on lkml, and all suggestions (mainly from Ivan
Kokshaysky <ink@jurassic.park.msu.ru>) have been taken into account.
parent bb89c58c
......@@ -56,12 +56,6 @@ struct pci_controller *pci_isa_hose;
* Quirks.
*/
static void __init
quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
static void __init
quirk_isa_bridge(struct pci_dev *dev)
{
......@@ -125,8 +119,6 @@ pcibios_fixup_final(struct pci_dev *dev)
}
struct pci_fixup pcibios_fixups[] __initdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
quirk_eisa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
quirk_isa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
......
#
# PCI configuration
# EISA configuration
#
config EISA_PCI_EISA
bool "Generic PCI/EISA bridge"
depends on PCI && EISA
default y
---help---
Activate this option if your system contains a PCI to EISA
bridge. If your system have both PCI and EISA slots, you
certainly need this option.
When in doubt, say Y.
config EISA_VIRTUAL_ROOT
bool "EISA virtual root device"
depends on EISA
default y
---help---
Activate this option if your system only have EISA bus
(no PCI slots). The Alpha Jensen is an example of such
a system.
When in doubt, say Y.
config EISA_NAMES
bool "EISA device name database"
depends on EISA
......
# Makefile for the Linux device tree
obj-$(CONFIG_EISA) += eisa-bus.o
obj-$(CONFIG_EISA) += eisa-bus.o
obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
# virtual_root.o should be the last EISA root device to initialize,
# so leave it at the end of the list.
obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
clean-files:= devlist.h
......
......@@ -15,6 +15,8 @@
#include <linux/ioport.h>
#include <asm/io.h>
#define SLOT_ADDRESS(r,n) (r->bus_base_addr + (0x1000 * n))
#define EISA_DEVINFO(i,s) { .id = { .sig = i }, .name = s }
struct eisa_device_info {
......@@ -95,12 +97,6 @@ struct bus_type eisa_bus_type = {
.match = eisa_bus_match,
};
/* The default EISA device parent (virtual root device). */
static struct device eisa_bus_root = {
.name = "EISA Bridge",
.bus_id = "eisa",
};
int eisa_driver_register (struct eisa_driver *edrv)
{
int r;
......@@ -109,7 +105,7 @@ int eisa_driver_register (struct eisa_driver *edrv)
if ((r = driver_register (&edrv->driver)) < 0)
return r;
return 1;
return 0;
}
void eisa_driver_unregister (struct eisa_driver *edrv)
......@@ -125,7 +121,8 @@ static ssize_t eisa_show_sig (struct device *dev, char *buf)
static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
static void __init eisa_register_device (char *sig, int slot)
static void __init eisa_register_device (struct eisa_root_device *root,
char *sig, int slot)
{
struct eisa_device *edev;
......@@ -135,11 +132,11 @@ static void __init eisa_register_device (char *sig, int slot)
memset (edev, 0, sizeof (*edev));
memcpy (edev->id.sig, sig, 7);
edev->slot = slot;
edev->base_addr = 0x1000 * slot;
edev->base_addr = SLOT_ADDRESS (root, slot);
eisa_name_device (edev);
edev->dev.parent = &eisa_bus_root;
edev->dev.parent = root->dev;
edev->dev.bus = &eisa_bus_type;
sprintf (edev->dev.bus_id, "00:%02X", slot);
sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
/* Don't register resource for slot 0, since this will surely
* fail... :-( */
......@@ -150,7 +147,7 @@ static void __init eisa_register_device (char *sig, int slot)
edev->res.end = edev->res.start + 0xfff;
edev->res.flags = IORESOURCE_IO;
if (request_resource (&ioport_resource, &edev->res)) {
if (request_resource (root->res, &edev->res)) {
printk (KERN_WARNING \
"Cannot allocate resource for EISA slot %d\n",
slot);
......@@ -167,16 +164,18 @@ static void __init eisa_register_device (char *sig, int slot)
device_create_file (&edev->dev, &dev_attr_signature);
}
static int __init eisa_probe (void)
static int __init eisa_probe (struct eisa_root_device *root)
{
int i, c;
char *str;
unsigned long slot_addr;
unsigned long sig_addr;
printk (KERN_INFO "EISA: Probing bus...\n");
for (c = 0, i = 0; i <= EISA_MAX_SLOTS; i++) {
slot_addr = (0x1000 * i) + EISA_VENDOR_ID_OFFSET;
if ((str = decode_eisa_sig (slot_addr))) {
printk (KERN_INFO "EISA: Probing bus %d at %s\n",
root->bus_nr, root->dev->name);
for (c = 0, i = 0; i <= root->slots; i++) {
sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
if ((str = decode_eisa_sig (sig_addr))) {
if (!i)
printk (KERN_INFO "EISA: Motherboard %s detected\n",
str);
......@@ -187,7 +186,7 @@ static int __init eisa_probe (void)
c++;
}
eisa_register_device (str, i);
eisa_register_device (root, str, i);
}
}
printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
......@@ -195,20 +194,40 @@ static int __init eisa_probe (void)
return 0;
}
static LIST_HEAD (eisa_root_head);
static int eisa_bus_count;
int eisa_root_register (struct eisa_root_device *root)
{
struct list_head *node;
struct eisa_root_device *tmp_root;
/* Check if this bus base address has been already
* registered. This prevents the virtual root device from
* registering after the real one has, for example... */
list_for_each (node, &eisa_root_head) {
tmp_root = list_entry (node, struct eisa_root_device, node);
if (tmp_root->bus_base_addr == root->bus_base_addr)
return -1; /* Space already taken, buddy... */
}
root->bus_nr = eisa_bus_count++;
list_add_tail (&root->node, &eisa_root_head);
return eisa_probe (root);
}
static int __init eisa_init (void)
{
int r;
if ((r = bus_register (&eisa_bus_type)))
return r;
if ((r = device_register (&eisa_bus_root))) {
bus_unregister (&eisa_bus_type);
return r;
}
printk (KERN_INFO "EISA bus registered\n");
return eisa_probe ();
return 0;
}
postcore_initcall (eisa_init);
......
/*
* Minimalist driver for a generic PCI-to-EISA bridge.
*
* (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
*
* This code is released under the GPL version 2.
*
* Ivan Kokshaysky <ink@jurassic.park.msu.ru> :
* Generalisation from i82375 to PCI_CLASS_BRIDGE_EISA.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/eisa.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/init.h>
/* There is only *one* pci_eisa device per machine, right ? */
static struct eisa_root_device pci_eisa_root;
static int __devinit pci_eisa_init (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int rc;
if ((rc = pci_enable_device (pdev))) {
printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
pdev->slot_name);
return rc;
}
pci_eisa_root.dev = &pdev->dev;
pci_eisa_root.dev->driver_data = &pci_eisa_root;
pci_eisa_root.res = pdev->bus->resource[0];
pci_eisa_root.bus_base_addr = pdev->bus->resource[0]->start;
pci_eisa_root.slots = EISA_MAX_SLOTS;
if (eisa_root_register (&pci_eisa_root)) {
printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
return -1;
}
return 0;
}
static struct pci_device_id pci_eisa_pci_tbl[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
{ 0, }
};
static struct pci_driver pci_eisa_driver = {
.name = "pci_eisa",
.id_table = pci_eisa_pci_tbl,
.probe = pci_eisa_init,
};
static int __init pci_eisa_init_module (void)
{
return pci_module_init (&pci_eisa_driver);
}
device_initcall(pci_eisa_init_module);
/*
* Virtual EISA root driver.
* Acts as a placeholder if we don't have a proper EISA bridge.
*
* (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
*
* This code is released under the GPL version 2.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/eisa.h>
#include <linux/module.h>
#include <linux/init.h>
/* The default EISA device parent (virtual root device). */
static struct device eisa_root_dev = {
.name = "Virtual EISA Bridge",
.bus_id = "eisa",
};
static struct eisa_root_device eisa_bus_root = {
.dev = &eisa_root_dev,
.bus_base_addr = 0,
.res = &ioport_resource,
.slots = EISA_MAX_SLOTS,
};
static int virtual_eisa_root_init (void)
{
int r;
if ((r = device_register (&eisa_root_dev))) {
return r;
}
eisa_root_dev.driver_data = &eisa_bus_root;
if (eisa_root_register (&eisa_bus_root)) {
/* A real bridge may have been registered before
* us. So quietly unregister. */
device_unregister (&eisa_root_dev);
return -1;
}
return 0;
}
device_initcall (virtual_eisa_root_init);
......@@ -1007,6 +1007,7 @@ static int vortex_eisa_remove (struct device *device)
/* returns count found (>= 0), or negative on error */
static int __init vortex_eisa_init (void)
{
int eisa_found = 0;
int orig_cards_found = vortex_cards_found;
/* Now check all slots of the EISA bus. */
......@@ -1014,8 +1015,14 @@ static int __init vortex_eisa_init (void)
return 0;
#ifdef CONFIG_EISA
if (eisa_driver_register (&vortex_eisa_driver) < 0) {
eisa_driver_unregister (&vortex_eisa_driver);
if (eisa_driver_register (&vortex_eisa_driver) >= 0) {
/* Because of the way EISA bus is probed, we cannot assume
* any device have been found when we exit from
* eisa_driver_register (the bus root driver may not be
* initialized yet). So we blindly assume something was
* found, and let the sysfs magic happend... */
eisa_found = 1;
}
#endif
......@@ -1025,7 +1032,7 @@ static int __init vortex_eisa_init (void)
compaq_device_id, vortex_cards_found++);
}
return vortex_cards_found - orig_cards_found;
return vortex_cards_found - orig_cards_found + eisa_found;
}
/* returns count (>= 0), or negative on error */
......
......@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/eisa.h>
#include <asm/byteorder.h>
#include <asm/io.h>
......@@ -61,6 +62,7 @@ static spinlock_t eisa_irq_lock = SPIN_LOCK_UNLOCKED;
static struct eisa_ba {
struct pci_hba_data hba;
unsigned long eeprom_addr;
struct eisa_root_device root;
} eisa_dev;
/* Port ops */
......@@ -376,6 +378,18 @@ static int __devinit eisa_probe(struct parisc_device *dev)
eisa_eeprom_init(eisa_dev.eeprom_addr);
eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
init_eisa_pic();
/* FIXME : Get the number of slots from the enumerator, not a
* hadcoded value. Also don't enumerate the bus twice. */
eisa_dev.root.dev = &dev->dev;
dev->dev.driver_data = &eisa_dev.root;
eisa_dev.root.bus_base_addr = 0;
eisa_dev.root.res = &eisa_dev.hba.io_space;
eisa_dev.root.slots = EISA_MAX_SLOTS;
if (eisa_root_register (&eisa_dev.root)) {
printk(KERN_ERR "EISA: Failed to register EISA root\n");
return -1;
}
return 0;
}
......
......@@ -535,6 +535,15 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
}
}
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
*/
static void __init quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
/*
* The main table of quirks.
*/
......@@ -604,6 +613,7 @@ static struct pci_fixup pci_fixups[] __devinitdata = {
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge },
{ 0 }
};
......
......@@ -24,7 +24,8 @@ struct eisa_device_id {
};
/* There is not much we can say about an EISA device, apart from
* signature, slot number, and base address */
* signature, slot number, and base address. */
struct eisa_device {
struct eisa_device_id id;
int slot;
......@@ -57,4 +58,18 @@ static inline void eisa_set_drvdata (struct eisa_device *edev, void *data)
edev->dev.driver_data = data;
}
/* The EISA root device. There's rumours about machines with multiple
* busses (PA-RISC ?), so we try to handle that. */
struct eisa_root_device {
struct list_head node;
struct device *dev; /* Pointer to bridge device */
struct resource *res;
unsigned long bus_base_addr;
int slots; /* Max slot number */
int bus_nr; /* Set by eisa_root_register */
};
int eisa_root_register (struct eisa_root_device *root);
#endif
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