1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/*
* 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/ide.h>
#include <linux/init.h>
#include <linux/isapnp.h>
#ifndef PREPARE_FUNC
#define PREPARE_FUNC(dev) (dev->prepare)
#define ACTIVATE_FUNC(dev) (dev->activate)
#define DEACTIVATE_FUNC(dev) (dev->deactivate)
#endif
#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, DEV_IRQ(dev, 0));
index = ide_register_hw(&hw, NULL);
if (index != -1) {
printk("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 }
};
#ifdef MODULE
#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;
#endif
/*
* Probe for ISA PnP IDE interfaces.
*/
void __init pnpide_init(int enable)
{
struct pci_dev *dev = NULL;
struct pnp_dev_t *dev_type;
if (!isapnp_present())
return;
#ifdef MODULE
/* Module unload, deactivate all registered devices. */
if (!enable) {
int i;
for (i = 0; i < pnp_ide_dev_idx; i++) {
devices[i].dev_type->init_fn(dev, 0);
if (DEACTIVATE_FUNC(devices[i].dev))
DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev);
}
return;
}
#endif
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 (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) {
printk("ide: %s prepare failed\n", DEV_NAME(dev));
continue;
}
if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) {
printk("ide: %s activate failed\n", DEV_NAME(dev));
continue;
}
/* Call device initialization function */
if (dev_type->init_fn(dev, 1)) {
if (DEACTIVATE_FUNC(dev))
DEACTIVATE_FUNC(dev)(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
}
}
}
}
|