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#undef LABPC_DEBUG
42
43#include <linux/interrupt.h>
44#include "../comedidev.h"
45
46#include <linux/ioport.h>
47
48#include "8255.h"
49
50#include <pcmcia/cs_types.h>
51#include <pcmcia/cs.h>
52#include <pcmcia/cistpl.h>
53#include <pcmcia/cisreg.h>
54#include <pcmcia/ds.h>
55
56static struct pcmcia_device *pcmcia_cur_dev = NULL;
57
58#define DIO24_SIZE 4
59
60static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
61static int dio24_detach(struct comedi_device *dev);
62
63enum dio24_bustype { pcmcia_bustype };
64
65struct dio24_board_struct {
66 const char *name;
67 int device_id;
68 enum dio24_bustype bustype;
69 int have_dio;
70
71 unsigned int (*read_byte) (unsigned int address);
72 void (*write_byte) (unsigned int byte, unsigned int address);
73};
74
75static const struct dio24_board_struct dio24_boards[] = {
76 {
77 .name = "daqcard-dio24",
78 .device_id = 0x475c,
79 .bustype = pcmcia_bustype,
80 .have_dio = 1,
81 },
82 {
83 .name = "ni_daq_dio24",
84 .device_id = 0x475c,
85 .bustype = pcmcia_bustype,
86 .have_dio = 1,
87 },
88};
89
90
91
92
93#define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
94
95struct dio24_private {
96
97 int data;
98};
99
100#define devpriv ((struct dio24_private *)dev->private)
101
102static struct comedi_driver driver_dio24 = {
103 .driver_name = "ni_daq_dio24",
104 .module = THIS_MODULE,
105 .attach = dio24_attach,
106 .detach = dio24_detach,
107 .num_names = ARRAY_SIZE(dio24_boards),
108 .board_name = &dio24_boards[0].name,
109 .offset = sizeof(struct dio24_board_struct),
110};
111
112static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
113{
114 struct comedi_subdevice *s;
115 unsigned long iobase = 0;
116#ifdef incomplete
117 unsigned int irq = 0;
118#endif
119 struct pcmcia_device *link;
120
121
122 if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
123 return -ENOMEM;
124
125
126 switch (thisboard->bustype) {
127 case pcmcia_bustype:
128 link = pcmcia_cur_dev;
129 if (!link)
130 return -EIO;
131 iobase = link->io.BasePort1;
132#ifdef incomplete
133 irq = link->irq.AssignedIRQ;
134#endif
135 break;
136 default:
137 printk("bug! couldn't determine board type\n");
138 return -EINVAL;
139 break;
140 }
141 printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
142 thisboard->name, iobase);
143#ifdef incomplete
144 if (irq) {
145 printk(", irq %u", irq);
146 }
147#endif
148
149 printk("\n");
150
151 if (iobase == 0) {
152 printk("io base address is zero!\n");
153 return -EINVAL;
154 }
155
156 dev->iobase = iobase;
157
158#ifdef incomplete
159
160 dev->irq = irq;
161#endif
162
163 dev->board_name = thisboard->name;
164
165 if (alloc_subdevices(dev, 1) < 0)
166 return -ENOMEM;
167
168
169 s = dev->subdevices + 0;
170 subdev_8255_init(dev, s, NULL, dev->iobase);
171
172 return 0;
173};
174
175static int dio24_detach(struct comedi_device *dev)
176{
177 printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
178
179 if (dev->subdevices)
180 subdev_8255_cleanup(dev, dev->subdevices + 0);
181
182 if (thisboard->bustype != pcmcia_bustype && dev->iobase)
183 release_region(dev->iobase, DIO24_SIZE);
184 if (dev->irq)
185 free_irq(dev->irq, dev);
186
187 return 0;
188};
189
190
191
192
193
194
195
196
197
198
199#ifdef PCMCIA_DEBUG
200static int pc_debug = PCMCIA_DEBUG;
201module_param(pc_debug, int, 0644);
202#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
203static char *version = "ni_daq_dio24.c, based on dummy_cs.c";
204#else
205#define DEBUG(n, args...)
206#endif
207
208
209
210static void dio24_config(struct pcmcia_device *link);
211static void dio24_release(struct pcmcia_device *link);
212static int dio24_cs_suspend(struct pcmcia_device *p_dev);
213static int dio24_cs_resume(struct pcmcia_device *p_dev);
214
215
216
217
218
219
220
221static int dio24_cs_attach(struct pcmcia_device *);
222static void dio24_cs_detach(struct pcmcia_device *);
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237static const dev_info_t dev_info = "ni_daq_dio24";
238
239struct local_info_t {
240 struct pcmcia_device *link;
241 dev_node_t node;
242 int stop;
243 struct bus_operations *bus;
244};
245
246
247
248
249
250
251
252
253
254
255
256
257
258static int dio24_cs_attach(struct pcmcia_device *link)
259{
260 struct local_info_t *local;
261
262 printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
263
264 DEBUG(0, "dio24_cs_attach()\n");
265
266
267 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
268 if (!local)
269 return -ENOMEM;
270 local->link = link;
271 link->priv = local;
272
273
274 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
275 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
276 link->irq.Handler = NULL;
277
278
279
280
281
282
283
284
285 link->conf.Attributes = 0;
286 link->conf.IntType = INT_MEMORY_AND_IO;
287
288 pcmcia_cur_dev = link;
289
290 dio24_config(link);
291
292 return 0;
293}
294
295
296
297
298
299
300
301
302
303
304static void dio24_cs_detach(struct pcmcia_device *link)
305{
306
307 printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
308
309 DEBUG(0, "dio24_cs_detach(0x%p)\n", link);
310
311 if (link->dev_node) {
312 ((struct local_info_t *)link->priv)->stop = 1;
313 dio24_release(link);
314 }
315
316
317 if (link->priv)
318 kfree(link->priv);
319
320}
321
322
323
324
325
326
327
328
329
330static void dio24_config(struct pcmcia_device *link)
331{
332 struct local_info_t *dev = link->priv;
333 tuple_t tuple;
334 cisparse_t parse;
335 int last_ret;
336 u_char buf[64];
337 win_req_t req;
338 memreq_t map;
339 cistpl_cftable_entry_t dflt = { 0 };
340
341 printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
342
343 DEBUG(0, "dio24_config(0x%p)\n", link);
344
345
346
347
348
349 tuple.DesiredTuple = CISTPL_CONFIG;
350 tuple.Attributes = 0;
351 tuple.TupleData = buf;
352 tuple.TupleDataMax = sizeof(buf);
353 tuple.TupleOffset = 0;
354
355 last_ret = pcmcia_get_first_tuple(link, &tuple);
356 if (last_ret) {
357 cs_error(link, GetFirstTuple, last_ret);
358 goto cs_failed;
359 }
360
361 last_ret = pcmcia_get_tuple_data(link, &tuple);
362 if (last_ret) {
363 cs_error(link, GetTupleData, last_ret);
364 goto cs_failed;
365 }
366
367 last_ret = pcmcia_parse_tuple(&tuple, &parse);
368 if (last_ret) {
369 cs_error(link, ParseTuple, last_ret);
370 goto cs_failed;
371 }
372 link->conf.ConfigBase = parse.config.base;
373 link->conf.Present = parse.config.rmask[0];
374
375
376
377
378
379
380
381
382
383
384
385
386
387 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
388
389 last_ret = pcmcia_get_first_tuple(link, &tuple);
390 if (last_ret) {
391 cs_error(link, GetFirstTuple, last_ret);
392 goto cs_failed;
393 }
394 while (1) {
395 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
396 if (pcmcia_get_tuple_data(link, &tuple) != 0)
397 goto next_entry;
398 if (pcmcia_parse_tuple(&tuple, &parse) != 0)
399 goto next_entry;
400
401 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
402 dflt = *cfg;
403 if (cfg->index == 0)
404 goto next_entry;
405 link->conf.ConfigIndex = cfg->index;
406
407
408 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
409 link->conf.Attributes |= CONF_ENABLE_SPKR;
410 link->conf.Status = CCSR_AUDIO_ENA;
411 }
412
413
414 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
415 link->conf.Attributes |= CONF_ENABLE_IRQ;
416
417
418 link->io.NumPorts1 = link->io.NumPorts2 = 0;
419 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
420 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
421 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
422 if (!(io->flags & CISTPL_IO_8BIT))
423 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
424 if (!(io->flags & CISTPL_IO_16BIT))
425 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
426 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
427 link->io.BasePort1 = io->win[0].base;
428 link->io.NumPorts1 = io->win[0].len;
429 if (io->nwin > 1) {
430 link->io.Attributes2 = link->io.Attributes1;
431 link->io.BasePort2 = io->win[1].base;
432 link->io.NumPorts2 = io->win[1].len;
433 }
434
435 if (pcmcia_request_io(link, &link->io) != 0)
436 goto next_entry;
437 }
438
439 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
440 cistpl_mem_t *mem =
441 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
442 req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
443 req.Attributes |= WIN_ENABLE;
444 req.Base = mem->win[0].host_addr;
445 req.Size = mem->win[0].len;
446 if (req.Size < 0x1000)
447 req.Size = 0x1000;
448 req.AccessSpeed = 0;
449 if (pcmcia_request_window(&link, &req, &link->win))
450 goto next_entry;
451 map.Page = 0;
452 map.CardOffset = mem->win[0].card_addr;
453 if (pcmcia_map_mem_page(link->win, &map))
454 goto next_entry;
455 }
456
457 break;
458
459next_entry:
460
461 last_ret = pcmcia_get_next_tuple(link, &tuple);
462 if (last_ret) {
463 cs_error(link, GetNextTuple, last_ret);
464 goto cs_failed;
465 }
466 }
467
468
469
470
471
472
473 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
474 last_ret = pcmcia_request_irq(link, &link->irq);
475 if (last_ret) {
476 cs_error(link, RequestIRQ, last_ret);
477 goto cs_failed;
478 }
479 }
480
481
482
483
484
485
486 last_ret = pcmcia_request_configuration(link, &link->conf);
487 if (last_ret) {
488 cs_error(link, RequestConfiguration, last_ret);
489 goto cs_failed;
490 }
491
492
493
494
495
496 sprintf(dev->node.dev_name, "ni_daq_dio24");
497 dev->node.major = dev->node.minor = 0;
498 link->dev_node = &dev->node;
499
500
501 printk(KERN_INFO "%s: index 0x%02x",
502 dev->node.dev_name, link->conf.ConfigIndex);
503 if (link->conf.Attributes & CONF_ENABLE_IRQ)
504 printk(", irq %d", link->irq.AssignedIRQ);
505 if (link->io.NumPorts1)
506 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
507 link->io.BasePort1 + link->io.NumPorts1 - 1);
508 if (link->io.NumPorts2)
509 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
510 link->io.BasePort2 + link->io.NumPorts2 - 1);
511 if (link->win)
512 printk(", mem 0x%06lx-0x%06lx", req.Base,
513 req.Base + req.Size - 1);
514 printk("\n");
515
516 return;
517
518cs_failed:
519 printk(KERN_INFO "Fallo");
520 dio24_release(link);
521
522}
523
524static void dio24_release(struct pcmcia_device *link)
525{
526 DEBUG(0, "dio24_release(0x%p)\n", link);
527
528 pcmcia_disable_device(link);
529}
530
531
532
533
534
535
536
537
538
539
540
541
542
543static int dio24_cs_suspend(struct pcmcia_device *link)
544{
545 struct local_info_t *local = link->priv;
546
547
548 local->stop = 1;
549 return 0;
550}
551
552static int dio24_cs_resume(struct pcmcia_device *link)
553{
554 struct local_info_t *local = link->priv;
555
556 local->stop = 0;
557 return 0;
558}
559
560
561
562static struct pcmcia_device_id dio24_cs_ids[] = {
563
564 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),
565 PCMCIA_DEVICE_NULL
566};
567
568MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
569
570struct pcmcia_driver dio24_cs_driver = {
571 .probe = dio24_cs_attach,
572 .remove = dio24_cs_detach,
573 .suspend = dio24_cs_suspend,
574 .resume = dio24_cs_resume,
575 .id_table = dio24_cs_ids,
576 .owner = THIS_MODULE,
577 .drv = {
578 .name = dev_info,
579 },
580};
581
582static int __init init_dio24_cs(void)
583{
584 printk("ni_daq_dio24: HOLA SOY YO!\n");
585 DEBUG(0, "%s\n", version);
586 pcmcia_register_driver(&dio24_cs_driver);
587 return 0;
588}
589
590static void __exit exit_dio24_cs(void)
591{
592 DEBUG(0, "ni_dio24: unloading\n");
593 pcmcia_unregister_driver(&dio24_cs_driver);
594}
595
596int __init init_module(void)
597{
598 int ret;
599
600 ret = init_dio24_cs();
601 if (ret < 0)
602 return ret;
603
604 return comedi_driver_register(&driver_dio24);
605}
606
607void __exit cleanup_module(void)
608{
609 exit_dio24_cs();
610 comedi_driver_unregister(&driver_dio24);
611}
612