1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
32extern struct socket_info_t *pcmcia_register_socket (int slot,
33 struct pccard_operations *vtable, int use_bus_pm);
34extern void pcmcia_unregister_socket (struct socket_info_t *socket);
35extern void pcmcia_suspend_socket (struct socket_info_t *socket);
36extern void pcmcia_resume_socket (struct socket_info_t *socket);
37
38
39
40
41
42
43#define MAX_SOCKETS (8)
44static pci_socket_t pci_socket_array[MAX_SOCKETS];
45
46static 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
55static 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
64static 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
77static 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
85static 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
95static 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
104static 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
113static 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
122static 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
131static 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
140static 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
149static 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
157static 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
172static 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
191void 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
198static int __devinit
199cardbus_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, ¥ta_operations);
206 }
207 }
208 return -ENODEV;
209}
210
211static 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
221static 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
228static 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
236static 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}, { }
245};
246MODULE_DEVICE_TABLE(pci, cardbus_table);
247
248static 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
257static int __init pci_socket_init(void)
258{
259 return pci_module_init (&pci_cardbus_driver);
260}
261
262static void __exit pci_socket_exit (void)
263{
264 pci_unregister_driver (&pci_cardbus_driver);
265}
266
267module_init(pci_socket_init);
268module_exit(pci_socket_exit);
269