File: /usr/src/linux/drivers/ide/ide-pnp.c

1     /*
2      * linux/drivers/ide/ide-pnp.c
3      *
4      * This file provides autodetection for ISA PnP IDE interfaces.
5      * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
6      *
7      * Copyright (C) 2000 Andrey Panin <pazke@orbita.don.sitek.net>
8      *
9      * This program is free software; you can redistribute it and/or modify
10      * it under the terms of the GNU General Public License as published by
11      * the Free Software Foundation; either version 2, or (at your option)
12      * any later version.
13      *
14      * You should have received a copy of the GNU General Public License
15      * (for example /usr/src/linux/COPYING); if not, write to the Free
16      * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
17      */
18     
19     #include <linux/ide.h>
20     #include <linux/init.h>
21     
22     #include <linux/isapnp.h>
23     
24     #ifndef PREPARE_FUNC
25     #define PREPARE_FUNC(dev)  (dev->prepare)
26     #define ACTIVATE_FUNC(dev)  (dev->activate)
27     #define DEACTIVATE_FUNC(dev)  (dev->deactivate)
28     #endif
29     
30     #define DEV_IO(dev, index) (dev->resource[index].start)
31     #define DEV_IRQ(dev, index) (dev->irq_resource[index].start)
32     
33     #define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP")
34     
35     #define GENERIC_HD_DATA		0
36     #define GENERIC_HD_ERROR	1
37     #define GENERIC_HD_NSECTOR	2
38     #define GENERIC_HD_SECTOR	3
39     #define GENERIC_HD_LCYL		4
40     #define GENERIC_HD_HCYL		5
41     #define GENERIC_HD_SELECT	6
42     #define GENERIC_HD_STATUS	7
43     
44     static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
45     	GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR, 
46     	GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL,
47     	GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1
48     };
49     
50     /* ISA PnP device table entry */
51     struct pnp_dev_t {
52     	unsigned short card_vendor, card_device, vendor, device;
53     	int (*init_fn)(struct pci_dev *dev, int enable);
54     };
55     
56     /* Generic initialisation function for ISA PnP IDE interface */
57     static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
58     {
59     	hw_regs_t hw;
60     	int index;
61     
62     	if (!enable)
63     		return 0;
64     
65     	if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0)))
66     		return 1;
67     
68     	ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0),
69     			generic_ide_offsets, (ide_ioreg_t) DEV_IO(dev, 1),
70     			0, NULL, DEV_IRQ(dev, 0));
71     
72     	index = ide_register_hw(&hw, NULL);
73     
74     	if (index != -1) {
75     	    	printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev));
76     		return 0;
77     	}
78     
79     	return 1;
80     }
81     
82     /* Add your devices here :)) */
83     struct pnp_dev_t idepnp_devices[] __initdata = {
84       	/* Generic ESDI/IDE/ATA compatible hard disk controller */
85     	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
86     		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
87     		pnpide_generic_init },
88     	{	0 }
89     };
90     
91     #ifdef MODULE
92     #define NR_PNP_DEVICES 8
93     struct pnp_dev_inst {
94     	struct pci_dev *dev;
95     	struct pnp_dev_t *dev_type;
96     };
97     static struct pnp_dev_inst devices[NR_PNP_DEVICES];
98     static int pnp_ide_dev_idx = 0;
99     #endif
100     
101     /*
102      * Probe for ISA PnP IDE interfaces.
103      */
104     void __init pnpide_init(int enable)
105     {
106     	struct pci_dev *dev = NULL;
107     	struct pnp_dev_t *dev_type;
108     
109     	if (!isapnp_present())
110     		return;
111     
112     #ifdef MODULE
113     	/* Module unload, deactivate all registered devices. */
114     	if (!enable) {
115     		int i;
116     		for (i = 0; i < pnp_ide_dev_idx; i++) {
117     			devices[i].dev_type->init_fn(dev, 0);
118     
119     			if (DEACTIVATE_FUNC(devices[i].dev))
120     				DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev);
121     		}
122     		return;
123     	}
124     #endif
125     	for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) {
126     		while ((dev = isapnp_find_dev(NULL, dev_type->vendor,
127     			dev_type->device, dev))) {
128     
129     			if (dev->active)
130     				continue;
131     
132            			if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) {
133     				printk("ide: %s prepare failed\n", DEV_NAME(dev));
134     				continue;
135     			}
136     
137     			if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) {
138     				printk("ide: %s activate failed\n", DEV_NAME(dev));
139     				continue;
140     			}
141     
142     			/* Call device initialization function */
143     			if (dev_type->init_fn(dev, 1)) {
144     				if (DEACTIVATE_FUNC(dev))
145     					DEACTIVATE_FUNC(dev)(dev);
146     			} else {
147     #ifdef MODULE
148     				/*
149     				 * Register device in the array to
150     				 * deactivate it on a module unload.
151     				 */
152     				if (pnp_ide_dev_idx >= NR_PNP_DEVICES)
153     					return;
154     				devices[pnp_ide_dev_idx].dev = dev;
155     				devices[pnp_ide_dev_idx].dev_type = dev_type;
156     				pnp_ide_dev_idx++;
157     #endif
158     			}
159     		}
160     	}
161     }
162