1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42#include "../comedidev.h"
43
44#include <linux/delay.h>
45#include <linux/pci.h>
46
47#include "das08.h"
48
49
50#include <pcmcia/cs_types.h>
51#include <pcmcia/cs.h>
52#include <pcmcia/cistpl.h>
53#include <pcmcia/ds.h>
54
55static struct pcmcia_device *cur_dev = NULL;
56
57#define thisboard ((const struct das08_board_struct *)dev->board_ptr)
58
59static int das08_cs_attach(struct comedi_device *dev,
60 struct comedi_devconfig *it);
61
62static struct comedi_driver driver_das08_cs = {
63 .driver_name = "das08_cs",
64 .module = THIS_MODULE,
65 .attach = das08_cs_attach,
66 .detach = das08_common_detach,
67 .board_name = &das08_cs_boards[0].name,
68 .num_names = ARRAY_SIZE(das08_cs_boards),
69 .offset = sizeof(struct das08_board_struct),
70};
71
72static int das08_cs_attach(struct comedi_device *dev,
73 struct comedi_devconfig *it)
74{
75 int ret;
76 unsigned long iobase;
77 struct pcmcia_device *link = cur_dev;
78
79 ret = alloc_private(dev, sizeof(struct das08_private_struct));
80 if (ret < 0)
81 return ret;
82
83 printk("comedi%d: das08_cs: ", dev->minor);
84
85
86 if (thisboard->bustype == pcmcia) {
87 if (link == NULL) {
88 printk(" no pcmcia cards found\n");
89 return -EIO;
90 }
91 iobase = link->io.BasePort1;
92 } else {
93 printk(" bug! board does not have PCMCIA bustype\n");
94 return -EINVAL;
95 }
96
97 printk("\n");
98
99 return das08_common_attach(dev, iobase);
100}
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121#ifdef PCMCIA_DEBUG
122static int pc_debug = PCMCIA_DEBUG;
123module_param(pc_debug, int, 0644);
124#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
125static const char *version =
126 "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
127#else
128#define DEBUG(n, args...)
129#endif
130
131
132static void das08_pcmcia_config(struct pcmcia_device *link);
133static void das08_pcmcia_release(struct pcmcia_device *link);
134static int das08_pcmcia_suspend(struct pcmcia_device *p_dev);
135static int das08_pcmcia_resume(struct pcmcia_device *p_dev);
136
137
138
139
140
141
142
143static int das08_pcmcia_attach(struct pcmcia_device *);
144static void das08_pcmcia_detach(struct pcmcia_device *);
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159static const dev_info_t dev_info = "pcm-das08";
160
161struct local_info_t {
162 struct pcmcia_device *link;
163 dev_node_t node;
164 int stop;
165 struct bus_operations *bus;
166};
167
168
169
170
171
172
173
174
175
176
177
178
179
180static int das08_pcmcia_attach(struct pcmcia_device *link)
181{
182 struct local_info_t *local;
183
184 DEBUG(0, "das08_pcmcia_attach()\n");
185
186
187 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
188 if (!local)
189 return -ENOMEM;
190 local->link = link;
191 link->priv = local;
192
193
194 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
195 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
196 link->irq.Handler = NULL;
197
198
199
200
201
202
203
204
205 link->conf.Attributes = 0;
206 link->conf.IntType = INT_MEMORY_AND_IO;
207
208 cur_dev = link;
209
210 das08_pcmcia_config(link);
211
212 return 0;
213}
214
215
216
217
218
219
220
221
222
223
224static void das08_pcmcia_detach(struct pcmcia_device *link)
225{
226
227 DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link);
228
229 if (link->dev_node) {
230 ((struct local_info_t *)link->priv)->stop = 1;
231 das08_pcmcia_release(link);
232 }
233
234
235 if (link->priv)
236 kfree(link->priv);
237
238}
239
240
241
242
243
244
245
246
247
248static void das08_pcmcia_config(struct pcmcia_device *link)
249{
250 struct local_info_t *dev = link->priv;
251 tuple_t tuple;
252 cisparse_t parse;
253 int last_fn, last_ret;
254 u_char buf[64];
255 cistpl_cftable_entry_t dflt = { 0 };
256
257 DEBUG(0, "das08_pcmcia_config(0x%p)\n", link);
258
259
260
261
262
263 tuple.DesiredTuple = CISTPL_CONFIG;
264 tuple.Attributes = 0;
265 tuple.TupleData = buf;
266 tuple.TupleDataMax = sizeof(buf);
267 tuple.TupleOffset = 0;
268 last_fn = GetFirstTuple;
269
270 last_ret = pcmcia_get_first_tuple(link, &tuple);
271 if (last_ret)
272 goto cs_failed;
273
274 last_fn = GetTupleData;
275
276 last_ret = pcmcia_get_tuple_data(link, &tuple);
277 if (last_ret)
278 goto cs_failed;
279
280 last_fn = ParseTuple;
281
282 last_ret = pcmcia_parse_tuple(&tuple, &parse);
283 if (last_ret)
284 goto cs_failed;
285
286 link->conf.ConfigBase = parse.config.base;
287 link->conf.Present = parse.config.rmask[0];
288
289
290
291
292
293
294
295
296
297
298
299
300
301 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
302 last_fn = GetFirstTuple;
303
304 last_ret = pcmcia_get_first_tuple(link, &tuple);
305 if (last_ret)
306 goto cs_failed;
307
308 while (1) {
309 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
310
311 last_ret = pcmcia_get_tuple_data(link, &tuple);
312 if (last_ret)
313 goto next_entry;
314
315 last_ret = pcmcia_parse_tuple(&tuple, &parse);
316 if (last_ret)
317 goto next_entry;
318
319 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
320 dflt = *cfg;
321 if (cfg->index == 0)
322 goto next_entry;
323 link->conf.ConfigIndex = cfg->index;
324
325
326
327
328
329
330
331
332 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
333 link->conf.Attributes |= CONF_ENABLE_IRQ;
334
335
336 link->io.NumPorts1 = link->io.NumPorts2 = 0;
337 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
338 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
339 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
340 if (!(io->flags & CISTPL_IO_8BIT))
341 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
342 if (!(io->flags & CISTPL_IO_16BIT))
343 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
344 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
345 link->io.BasePort1 = io->win[0].base;
346 link->io.NumPorts1 = io->win[0].len;
347 if (io->nwin > 1) {
348 link->io.Attributes2 = link->io.Attributes1;
349 link->io.BasePort2 = io->win[1].base;
350 link->io.NumPorts2 = io->win[1].len;
351 }
352
353 if (pcmcia_request_io(link, &link->io) != 0)
354 goto next_entry;
355 }
356
357
358 break;
359
360next_entry:
361 last_fn = GetNextTuple;
362
363 last_ret = pcmcia_get_next_tuple(link, &tuple);
364 if (last_ret)
365 goto cs_failed;
366 }
367
368 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
369 last_fn = RequestIRQ;
370 last_ret = pcmcia_request_irq(link, &link->irq);
371 if (last_ret)
372 goto cs_failed;
373 }
374
375
376
377
378
379
380 last_fn = RequestConfiguration;
381 last_ret = pcmcia_request_configuration(link, &link->conf);
382 if (last_ret)
383 goto cs_failed;
384
385
386
387
388
389 sprintf(dev->node.dev_name, "pcm-das08");
390 dev->node.major = dev->node.minor = 0;
391 link->dev_node = &dev->node;
392
393
394 printk(KERN_INFO "%s: index 0x%02x",
395 dev->node.dev_name, link->conf.ConfigIndex);
396 if (link->conf.Attributes & CONF_ENABLE_IRQ)
397 printk(", irq %u", link->irq.AssignedIRQ);
398 if (link->io.NumPorts1)
399 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
400 link->io.BasePort1 + link->io.NumPorts1 - 1);
401 if (link->io.NumPorts2)
402 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
403 link->io.BasePort2 + link->io.NumPorts2 - 1);
404 printk("\n");
405
406 return;
407
408cs_failed:
409 cs_error(link, last_fn, last_ret);
410 das08_pcmcia_release(link);
411
412}
413
414
415
416
417
418
419
420
421
422static void das08_pcmcia_release(struct pcmcia_device *link)
423{
424 DEBUG(0, "das08_pcmcia_release(0x%p)\n", link);
425 pcmcia_disable_device(link);
426}
427
428
429
430
431
432
433
434
435
436
437
438
439
440static int das08_pcmcia_suspend(struct pcmcia_device *link)
441{
442 struct local_info_t *local = link->priv;
443
444 local->stop = 1;
445
446 return 0;
447}
448
449static int das08_pcmcia_resume(struct pcmcia_device *link)
450{
451 struct local_info_t *local = link->priv;
452
453 local->stop = 0;
454 return 0;
455}
456
457
458
459static struct pcmcia_device_id das08_cs_id_table[] = {
460 PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001),
461 PCMCIA_DEVICE_NULL
462};
463
464MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table);
465
466struct pcmcia_driver das08_cs_driver = {
467 .probe = das08_pcmcia_attach,
468 .remove = das08_pcmcia_detach,
469 .suspend = das08_pcmcia_suspend,
470 .resume = das08_pcmcia_resume,
471 .id_table = das08_cs_id_table,
472 .owner = THIS_MODULE,
473 .drv = {
474 .name = dev_info,
475 },
476};
477
478static int __init init_das08_pcmcia_cs(void)
479{
480 DEBUG(0, "%s\n", version);
481 pcmcia_register_driver(&das08_cs_driver);
482 return 0;
483}
484
485static void __exit exit_das08_pcmcia_cs(void)
486{
487 DEBUG(0, "das08_pcmcia_cs: unloading\n");
488 pcmcia_unregister_driver(&das08_cs_driver);
489}
490
491static int __init das08_cs_init_module(void)
492{
493 int ret;
494
495 ret = init_das08_pcmcia_cs();
496 if (ret < 0)
497 return ret;
498
499 return comedi_driver_register(&driver_das08_cs);
500}
501
502static void __exit das08_cs_exit_module(void)
503{
504 exit_das08_pcmcia_cs();
505 comedi_driver_unregister(&driver_das08_cs);
506}
507
508MODULE_LICENSE("GPL");
509module_init(das08_cs_init_module);
510module_exit(das08_cs_exit_module);
511