File: /usr/src/linux/drivers/pcmcia/pci_socket.c

1     /*
2      * Generic PCI pccard driver interface.
3      *
4      * (C) Copyright 1999 Linus Torvalds
5      *
6      * This implements the common parts of PCI pccard drivers,
7      * notably detection and infrastructure conversion (ie change
8      * from socket index to "struct pci_dev" etc)
9      *
10      * This does NOT implement the actual low-level driver details,
11      * and this has on purpose been left generic enough that it can
12      * be used to set up a PCI PCMCIA controller (ie non-cardbus),
13      * or to set up a controller.
14      *
15      * See for example the "yenta" driver for PCI cardbus controllers
16      * conforming to the yenta cardbus specifications.
17      */
18     #include <linux/module.h>
19     
20     #include <linux/init.h>
21     #include <linux/pci.h>
22     #include <linux/sched.h>
23     #include <linux/interrupt.h>
24     
25     #include <pcmcia/ss.h>
26     
27     #include <asm/io.h>
28     
29     #include "pci_socket.h"
30     
31     
32     extern struct socket_info_t *pcmcia_register_socket (int slot,
33     		struct pccard_operations *vtable, int use_bus_pm);
34     extern void pcmcia_unregister_socket (struct socket_info_t *socket);
35     extern void pcmcia_suspend_socket (struct socket_info_t *socket);
36     extern void pcmcia_resume_socket (struct socket_info_t *socket);
37     
38     
39     /*
40      * Arbitrary define. This is the array of active cardbus
41      * entries.
42      */
43     #define MAX_SOCKETS (8)
44     static pci_socket_t pci_socket_array[MAX_SOCKETS];
45     
46     static int pci_init_socket(unsigned int sock)
47     {
48     	pci_socket_t *socket = pci_socket_array + sock;
49     
50     	if (socket->op && socket->op->init)
51     		return socket->op->init(socket);
52     	return -EINVAL;
53     }
54     
55     static int pci_suspend_socket(unsigned int sock)
56     {
57     	pci_socket_t *socket = pci_socket_array + sock;
58     
59     	if (socket->op && socket->op->suspend)
60     		return socket->op->suspend(socket);
61     	return -EINVAL;
62     }
63     
64     static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
65     {
66     	pci_socket_t *socket = pci_socket_array + sock;
67     
68     	socket->handler = handler;
69     	socket->info = info;
70     	if (handler)
71     		MOD_INC_USE_COUNT;
72     	else
73     		MOD_DEC_USE_COUNT;
74     	return 0;
75     }
76     
77     static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
78     {
79     	pci_socket_t *socket = pci_socket_array + sock;
80     
81     	*cap = socket->cap;
82     	return 0;
83     }
84     
85     static int pci_get_status(unsigned int sock, unsigned int *value)
86     {
87     	pci_socket_t *socket = pci_socket_array + sock;
88     
89     	if (socket->op && socket->op->get_status)
90     		return socket->op->get_status(socket, value);
91     	*value = 0;
92     	return -EINVAL;
93     }
94     
95     static int pci_get_socket(unsigned int sock, socket_state_t *state)
96     {
97     	pci_socket_t *socket = pci_socket_array + sock;
98     
99     	if (socket->op && socket->op->get_socket)
100     		return socket->op->get_socket(socket, state);
101     	return -EINVAL;
102     }
103     
104     static int pci_set_socket(unsigned int sock, socket_state_t *state)
105     {
106     	pci_socket_t *socket = pci_socket_array + sock;
107     
108     	if (socket->op && socket->op->set_socket)
109     		return socket->op->set_socket(socket, state);
110     	return -EINVAL;
111     }
112     
113     static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
114     {
115     	pci_socket_t *socket = pci_socket_array + sock;
116     
117     	if (socket->op && socket->op->get_io_map)
118     		return socket->op->get_io_map(socket, io);
119     	return -EINVAL;
120     }
121     
122     static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
123     {
124     	pci_socket_t *socket = pci_socket_array + sock;
125     
126     	if (socket->op && socket->op->set_io_map)
127     		return socket->op->set_io_map(socket, io);
128     	return -EINVAL;
129     }
130     
131     static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
132     {
133     	pci_socket_t *socket = pci_socket_array + sock;
134     
135     	if (socket->op && socket->op->get_mem_map)
136     		return socket->op->get_mem_map(socket, mem);
137     	return -EINVAL;
138     }
139     
140     static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
141     {
142     	pci_socket_t *socket = pci_socket_array + sock;
143     
144     	if (socket->op && socket->op->set_mem_map)
145     		return socket->op->set_mem_map(socket, mem);
146     	return -EINVAL;
147     }
148     
149     static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
150     {
151     	pci_socket_t *socket = pci_socket_array + sock;
152     
153     	if (socket->op && socket->op->proc_setup)
154     		socket->op->proc_setup(socket, base);
155     }
156     
157     static struct pccard_operations pci_socket_operations = {
158     	pci_init_socket,
159     	pci_suspend_socket,
160     	pci_register_callback,
161     	pci_inquire_socket,
162     	pci_get_status,
163     	pci_get_socket,
164     	pci_set_socket,
165     	pci_get_io_map,
166     	pci_set_io_map,
167     	pci_get_mem_map,
168     	pci_set_mem_map,
169     	pci_proc_setup
170     };
171     
172     static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
173     {
174     	pci_socket_t *socket = nr + pci_socket_array;
175     	int err;
176     	
177     	memset(socket, 0, sizeof(*socket));
178     	socket->dev = dev;
179     	socket->op = ops;
180     	dev->driver_data = socket;
181     	spin_lock_init(&socket->event_lock);
182     	err = socket->op->open(socket);
183     	if(err)
184     	{
185     		socket->dev = NULL;
186     		dev->driver_data = NULL;
187     	}
188     	return err;
189     }
190     
191     void cardbus_register(pci_socket_t *socket)
192     {
193     	int nr = socket - pci_socket_array;
194     
195     	socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1);
196     }
197     
198     static int __devinit
199     cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
200     {
201     	int	s;
202     
203     	for (s = 0; s < MAX_SOCKETS; s++) {
204     		if (pci_socket_array [s].dev == 0) {
205     			return add_pci_socket (s, dev, &yenta_operations);
206     		}
207     	}
208     	return -ENODEV;
209     }
210     
211     static void __devexit cardbus_remove (struct pci_dev *dev)
212     {
213     	pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
214     
215     	pcmcia_unregister_socket (socket->pcmcia_socket);
216     	if (socket->op && socket->op->close)
217     		socket->op->close(socket);
218     	dev->driver_data = 0;
219     }
220     
221     static int cardbus_suspend (struct pci_dev *dev, u32 state)
222     {
223     	pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
224     	pcmcia_suspend_socket (socket->pcmcia_socket);
225     	return 0;
226     }
227     
228     static int cardbus_resume (struct pci_dev *dev)
229     {
230     	pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
231     	pcmcia_resume_socket (socket->pcmcia_socket);
232     	return 0;
233     }
234     
235     
236     static struct pci_device_id cardbus_table [] __devinitdata = { {
237     	class:		PCI_CLASS_BRIDGE_CARDBUS << 8,
238     	class_mask:	~0,
239     
240     	vendor:		PCI_ANY_ID,
241     	device:		PCI_ANY_ID,
242     	subvendor:	PCI_ANY_ID,
243     	subdevice:	PCI_ANY_ID,
244     }, { /* all zeroes */ }
245     };
246     MODULE_DEVICE_TABLE(pci, cardbus_table);
247     
248     static struct pci_driver pci_cardbus_driver = {
249     	name:		"cardbus",
250     	id_table:	cardbus_table,
251     	probe:		cardbus_probe,
252     	remove:		cardbus_remove,
253     	suspend:	cardbus_suspend,
254     	resume:		cardbus_resume,
255     };
256     
257     static int __init pci_socket_init(void)
258     {
259     	return pci_module_init (&pci_cardbus_driver);
260     }
261     
262     static void __exit pci_socket_exit (void)
263     {
264     	pci_unregister_driver (&pci_cardbus_driver);
265     }
266     
267     module_init(pci_socket_init);
268     module_exit(pci_socket_exit);
269