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 
pci_init_socket(unsigned int sock)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 
pci_suspend_socket(unsigned int sock)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 
pci_register_callback(unsigned int sock,void (* handler)(void *,unsigned int),void * info)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 
pci_inquire_socket(unsigned int sock,socket_cap_t * cap)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 
pci_get_status(unsigned int sock,unsigned int * value)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 
pci_get_socket(unsigned int sock,socket_state_t * state)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 
pci_set_socket(unsigned int sock,socket_state_t * state)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 
pci_get_io_map(unsigned int sock,struct pccard_io_map * io)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 
pci_set_io_map(unsigned int sock,struct pccard_io_map * io)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 
pci_get_mem_map(unsigned int sock,struct pccard_mem_map * mem)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 
pci_set_mem_map(unsigned int sock,struct pccard_mem_map * mem)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 
pci_proc_setup(unsigned int sock,struct proc_dir_entry * base)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 
add_pci_socket(int nr,struct pci_dev * dev,struct pci_socket_ops * ops)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 	pci_set_drvdata(dev, socket);
181 	spin_lock_init(&socket->event_lock);
182 	err = socket->op->open(socket);
183 	if(err)
184 	{
185 		socket->dev = NULL;
186 		pci_set_drvdata(dev, NULL);
187 	}
188 	return err;
189 }
190 
cardbus_register(pci_socket_t * socket)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
cardbus_probe(struct pci_dev * dev,const struct pci_device_id * id)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 
cardbus_remove(struct pci_dev * dev)211 static void __devexit cardbus_remove (struct pci_dev *dev)
212 {
213 	pci_socket_t *socket = pci_get_drvdata(dev);
214 
215 	pcmcia_unregister_socket (socket->pcmcia_socket);
216 	if (socket->op && socket->op->close)
217 		socket->op->close(socket);
218 	pci_set_drvdata(dev, NULL);
219 }
220 
cardbus_suspend(struct pci_dev * dev,u32 state)221 static int cardbus_suspend (struct pci_dev *dev, u32 state)
222 {
223 	pci_socket_t *socket = pci_get_drvdata(dev);
224 	pcmcia_suspend_socket (socket->pcmcia_socket);
225 	return 0;
226 }
227 
cardbus_resume(struct pci_dev * dev)228 static int cardbus_resume (struct pci_dev *dev)
229 {
230 	pci_socket_t *socket = pci_get_drvdata(dev);
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:		__devexit_p(cardbus_remove),
253 	suspend:	cardbus_suspend,
254 	resume:		cardbus_resume,
255 };
256 
pci_socket_init(void)257 static int __init pci_socket_init(void)
258 {
259 	return pci_module_init (&pci_cardbus_driver);
260 }
261 
pci_socket_exit(void)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