- Kai Germaschewski: ymfpci cleanups and resource leak fixes
[davej-history.git] / drivers / pcmcia / pci_socket.c
blob03a026f1758e534a5a1dd9d24c3b5fcb40249b5c
1 /*
2 * Generic PCI pccard driver interface.
4 * (C) Copyright 1999 Linus Torvalds
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)
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.
15 * See for example the "yenta" driver for PCI cardbus controllers
16 * conforming to the yenta cardbus specifications.
18 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/pci.h>
22 #include <linux/sched.h>
23 #include <linux/interrupt.h>
25 #include <pcmcia/ss.h>
27 #include <asm/io.h>
29 #include "pci_socket.h"
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);
40 * Arbitrary define. This is the array of active cardbus
41 * entries.
43 #define MAX_SOCKETS (8)
44 static pci_socket_t pci_socket_array[MAX_SOCKETS];
46 static int pci_init_socket(unsigned int sock)
48 pci_socket_t *socket = pci_socket_array + sock;
50 if (socket->op && socket->op->init)
51 return socket->op->init(socket);
52 return -EINVAL;
55 static int pci_suspend_socket(unsigned int sock)
57 pci_socket_t *socket = pci_socket_array + sock;
59 if (socket->op && socket->op->suspend)
60 return socket->op->suspend(socket);
61 return -EINVAL;
64 static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
66 pci_socket_t *socket = pci_socket_array + sock;
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;
77 static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
79 pci_socket_t *socket = pci_socket_array + sock;
81 *cap = socket->cap;
82 return 0;
85 static int pci_get_status(unsigned int sock, unsigned int *value)
87 pci_socket_t *socket = pci_socket_array + sock;
89 if (socket->op && socket->op->get_status)
90 return socket->op->get_status(socket, value);
91 *value = 0;
92 return -EINVAL;
95 static int pci_get_socket(unsigned int sock, socket_state_t *state)
97 pci_socket_t *socket = pci_socket_array + sock;
99 if (socket->op && socket->op->get_socket)
100 return socket->op->get_socket(socket, state);
101 return -EINVAL;
104 static int pci_set_socket(unsigned int sock, socket_state_t *state)
106 pci_socket_t *socket = pci_socket_array + sock;
108 if (socket->op && socket->op->set_socket)
109 return socket->op->set_socket(socket, state);
110 return -EINVAL;
113 static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
115 pci_socket_t *socket = pci_socket_array + sock;
117 if (socket->op && socket->op->get_io_map)
118 return socket->op->get_io_map(socket, io);
119 return -EINVAL;
122 static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
124 pci_socket_t *socket = pci_socket_array + sock;
126 if (socket->op && socket->op->set_io_map)
127 return socket->op->set_io_map(socket, io);
128 return -EINVAL;
131 static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
133 pci_socket_t *socket = pci_socket_array + sock;
135 if (socket->op && socket->op->get_mem_map)
136 return socket->op->get_mem_map(socket, mem);
137 return -EINVAL;
140 static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
142 pci_socket_t *socket = pci_socket_array + sock;
144 if (socket->op && socket->op->set_mem_map)
145 return socket->op->set_mem_map(socket, mem);
146 return -EINVAL;
149 static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
151 pci_socket_t *socket = pci_socket_array + sock;
153 if (socket->op && socket->op->proc_setup)
154 socket->op->proc_setup(socket, base);
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
172 static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
174 pci_socket_t *socket = nr + pci_socket_array;
176 memset(socket, 0, sizeof(*socket));
177 socket->dev = dev;
178 socket->op = ops;
179 dev->driver_data = socket;
180 spin_lock_init(&socket->event_lock);
181 return socket->op->open(socket);
184 void cardbus_register(pci_socket_t *socket)
186 int nr = socket - pci_socket_array;
188 socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1);
191 static int __devinit
192 cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
194 int s;
196 for (s = 0; s < MAX_SOCKETS; s++) {
197 if (pci_socket_array [s].dev == 0) {
198 add_pci_socket (s, dev, &yenta_operations);
199 return 0;
202 return -ENODEV;
205 static void __devexit cardbus_remove (struct pci_dev *dev)
207 pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
209 pcmcia_unregister_socket (socket->pcmcia_socket);
210 if (socket->op && socket->op->close)
211 socket->op->close(socket);
212 dev->driver_data = 0;
215 static void cardbus_suspend (struct pci_dev *dev)
217 pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
218 pcmcia_suspend_socket (socket->pcmcia_socket);
221 static void cardbus_resume (struct pci_dev *dev)
223 pci_socket_t *socket = (pci_socket_t *) dev->driver_data;
224 pcmcia_resume_socket (socket->pcmcia_socket);
228 static struct pci_device_id cardbus_table [] __devinitdata = { {
229 class: PCI_CLASS_BRIDGE_CARDBUS << 8,
230 class_mask: ~0,
232 vendor: PCI_ANY_ID,
233 device: PCI_ANY_ID,
234 subvendor: PCI_ANY_ID,
235 subdevice: PCI_ANY_ID,
236 }, { /* all zeroes */ }
238 MODULE_DEVICE_TABLE(pci, cardbus_table);
240 static struct pci_driver pci_cardbus_driver = {
241 name: "cardbus",
242 id_table: cardbus_table,
243 probe: cardbus_probe,
244 remove: cardbus_remove,
245 suspend: cardbus_suspend,
246 resume: cardbus_resume,
249 static int __init pci_socket_init(void)
251 return pci_module_init (&pci_cardbus_driver);
254 static void __exit pci_socket_exit (void)
256 pci_unregister_driver (&pci_cardbus_driver);
259 module_init(pci_socket_init);
260 module_exit(pci_socket_exit);