blob: 8c770f31caea5de973a298f4a5bd144f79c7d977 [file] [log] [blame]
/*
* linux/drivers/ide/ide-pnp.c
*
* This file provides autodetection for ISA PnP IDE interfaces.
* It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
*
* Copyright (C) 2000 Andrey Panin <pazke@orbita.don.sitek.net>
*
* 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, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example /usr/src/linux/COPYING); if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/isapnp.h>
#define DEV_IO(dev, index) (dev->resource[index].start)
#define DEV_IRQ(dev, index) (dev->irq_resource[index].start)
#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP")
#define GENERIC_HD_DATA 0
#define GENERIC_HD_ERROR 1
#define GENERIC_HD_NSECTOR 2
#define GENERIC_HD_SECTOR 3
#define GENERIC_HD_LCYL 4
#define GENERIC_HD_HCYL 5
#define GENERIC_HD_SELECT 6
#define GENERIC_HD_STATUS 7
static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR,
GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL,
GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1
};
/* ISA PnP device table entry */
struct pnp_dev_t {
unsigned short card_vendor, card_device, vendor, device;
int (*init_fn)(struct pci_dev *dev, int enable);
};
/* Generic initialisation function for ISA PnP IDE interface */
static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
{
hw_regs_t hw;
int index;
if (!enable)
return 0;
if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0)))
return 1;
ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0),
generic_ide_offsets,
(ide_ioreg_t) DEV_IO(dev, 1),
0, NULL,
// generic_pnp_ide_iops,
DEV_IRQ(dev, 0));
index = ide_register_hw(&hw, NULL);
if (index != -1) {
printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev));
return 0;
}
return 1;
}
/* Add your devices here :)) */
struct pnp_dev_t idepnp_devices[] __initdata = {
/* Generic ESDI/IDE/ATA compatible hard disk controller */
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
pnpide_generic_init },
{ 0 }
};
#define NR_PNP_DEVICES 8
struct pnp_dev_inst {
struct pci_dev *dev;
struct pnp_dev_t *dev_type;
};
static struct pnp_dev_inst devices[NR_PNP_DEVICES];
static int pnp_ide_dev_idx = 0;
/*
* Probe for ISA PnP IDE interfaces.
*/
static void pnpide_init(int enable)
{
struct pci_dev *dev = NULL;
struct pnp_dev_t *dev_type;
if (!isapnp_present())
return;
/* Module unload, deactivate all registered devices. */
if (!enable) {
int i;
for (i = 0; i < pnp_ide_dev_idx; i++) {
dev = devices[i].dev;
devices[i].dev_type->init_fn(dev, 0);
if (dev->deactivate)
dev->deactivate(dev);
}
return;
}
for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) {
while ((dev = isapnp_find_dev(NULL, dev_type->vendor,
dev_type->device, dev))) {
if (dev->active)
continue;
if (dev->prepare && dev->prepare(dev) < 0) {
printk(KERN_ERR"ide-pnp: %s prepare failed\n", DEV_NAME(dev));
continue;
}
if (dev->activate && dev->activate(dev) < 0) {
printk(KERN_ERR"ide: %s activate failed\n", DEV_NAME(dev));
continue;
}
/* Call device initialization function */
if (dev_type->init_fn(dev, 1)) {
if (dev->deactivate(dev))
dev->deactivate(dev);
} else {
#ifdef MODULE
/*
* Register device in the array to
* deactivate it on a module unload.
*/
if (pnp_ide_dev_idx >= NR_PNP_DEVICES)
return;
devices[pnp_ide_dev_idx].dev = dev;
devices[pnp_ide_dev_idx].dev_type = dev_type;
pnp_ide_dev_idx++;
#endif
}
}
}
}
static void __init pnpide_begin(void)
{
pnpide_init(1);
}
static int pnpide_init_module(void)
{
ide_register_driver(pnpide_begin);
return 0;
}
static void pnpide_unload(void)
{
pnpide_init(0);
}
module_init(pnpide_init_module);
module_exit(pnpide_unload);
MODULE_AUTHOR("Andrey Panin");
MODULE_DESCRIPTION("Enabler for ISAPNP IDE devices");
MODULE_LICENSE("GPL");