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
43
44#include <linux/interrupt.h>
45#include "../comedidev.h"
46
47#include <linux/ioport.h>
48
49#include <pcmcia/cs_types.h>
50#include <pcmcia/cs.h>
51#include <pcmcia/cistpl.h>
52#include <pcmcia/cisreg.h>
53#include <pcmcia/ds.h>
54
55static struct pcmcia_device *pcmcia_cur_dev = NULL;
56
57#define DIO700_SIZE 8
58
59static int dio700_attach(struct comedi_device *dev,
60 struct comedi_devconfig *it);
61static int dio700_detach(struct comedi_device *dev);
62
63enum dio700_bustype { pcmcia_bustype };
64
65struct dio700_board {
66 const char *name;
67 int device_id;
68 enum dio700_bustype bustype;
69 int have_dio;
70
71
72 unsigned int (*read_byte) (unsigned int address);
73 void (*write_byte) (unsigned int byte, unsigned int address);
74};
75
76static const struct dio700_board dio700_boards[] = {
77 {
78 .name = "daqcard-700",
79 .device_id = 0x4743,
80 .bustype = pcmcia_bustype,
81 .have_dio = 1,
82 },
83 {
84 .name = "ni_daq_700",
85 .device_id = 0x4743,
86 .bustype = pcmcia_bustype,
87 .have_dio = 1,
88 },
89};
90
91
92
93
94#define thisboard ((const struct dio700_board *)dev->board_ptr)
95
96struct dio700_private {
97
98 int data;
99};
100
101#define devpriv ((struct dio700_private *)dev->private)
102
103static struct comedi_driver driver_dio700 = {
104 .driver_name = "ni_daq_700",
105 .module = THIS_MODULE,
106 .attach = dio700_attach,
107 .detach = dio700_detach,
108 .num_names = ARRAY_SIZE(dio700_boards),
109 .board_name = &dio700_boards[0].name,
110 .offset = sizeof(struct dio700_board),
111};
112
113
114
115#define _700_SIZE 8
116
117#define _700_DATA 0
118
119#define DIO_W 0x04
120#define DIO_R 0x05
121
122struct subdev_700_struct {
123 unsigned long cb_arg;
124 int (*cb_func) (int, int, int, unsigned long);
125 int have_irq;
126};
127
128#define CALLBACK_ARG (((struct subdev_700_struct *)s->private)->cb_arg)
129#define CALLBACK_FUNC (((struct subdev_700_struct *)s->private)->cb_func)
130#define subdevpriv ((struct subdev_700_struct *)s->private)
131
132static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
133
134void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
135{
136 short d;
137
138 d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
139
140 comedi_buf_put(s->async, d);
141 s->async->events |= COMEDI_CB_EOS;
142
143 comedi_event(dev, s);
144}
145
146static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
147{
148
149 unsigned long iobase = arg;
150
151 if (dir) {
152 outb(data, iobase + DIO_W);
153 return 0;
154 } else {
155 return inb(iobase + DIO_R);
156 }
157}
158
159static int subdev_700_insn(struct comedi_device *dev,
160 struct comedi_subdevice *s, struct comedi_insn *insn,
161 unsigned int *data)
162{
163 if (data[0]) {
164 s->state &= ~data[0];
165 s->state |= (data[0] & data[1]);
166
167 if (data[0] & 0xff)
168 CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
169 CALLBACK_ARG);
170 }
171
172 data[1] = s->state & 0xff;
173 data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
174
175 return 2;
176}
177
178static int subdev_700_insn_config(struct comedi_device *dev,
179 struct comedi_subdevice *s,
180 struct comedi_insn *insn, unsigned int *data)
181{
182
183 switch (data[0]) {
184 case INSN_CONFIG_DIO_INPUT:
185 break;
186 case INSN_CONFIG_DIO_OUTPUT:
187 break;
188 case INSN_CONFIG_DIO_QUERY:
189 data[1] =
190 (s->
191 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
192 COMEDI_INPUT;
193 return insn->n;
194 break;
195 default:
196 return -EINVAL;
197 }
198
199 return 1;
200}
201
202static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
203{
204 return;
205}
206
207static int subdev_700_cmdtest(struct comedi_device *dev,
208 struct comedi_subdevice *s,
209 struct comedi_cmd *cmd)
210{
211 int err = 0;
212 unsigned int tmp;
213
214
215
216 tmp = cmd->start_src;
217 cmd->start_src &= TRIG_NOW;
218 if (!cmd->start_src || tmp != cmd->start_src)
219 err++;
220
221 tmp = cmd->scan_begin_src;
222 cmd->scan_begin_src &= TRIG_EXT;
223 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
224 err++;
225
226 tmp = cmd->convert_src;
227 cmd->convert_src &= TRIG_FOLLOW;
228 if (!cmd->convert_src || tmp != cmd->convert_src)
229 err++;
230
231 tmp = cmd->scan_end_src;
232 cmd->scan_end_src &= TRIG_COUNT;
233 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
234 err++;
235
236 tmp = cmd->stop_src;
237 cmd->stop_src &= TRIG_NONE;
238 if (!cmd->stop_src || tmp != cmd->stop_src)
239 err++;
240
241 if (err)
242 return 1;
243
244
245
246 if (err)
247 return 2;
248
249
250
251 if (cmd->start_arg != 0) {
252 cmd->start_arg = 0;
253 err++;
254 }
255 if (cmd->scan_begin_arg != 0) {
256 cmd->scan_begin_arg = 0;
257 err++;
258 }
259 if (cmd->convert_arg != 0) {
260 cmd->convert_arg = 0;
261 err++;
262 }
263 if (cmd->scan_end_arg != 1) {
264 cmd->scan_end_arg = 1;
265 err++;
266 }
267 if (cmd->stop_arg != 0) {
268 cmd->stop_arg = 0;
269 err++;
270 }
271
272 if (err)
273 return 3;
274
275
276
277 if (err)
278 return 4;
279
280 return 0;
281}
282
283static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
284{
285
286
287 return 0;
288}
289
290static int subdev_700_cancel(struct comedi_device *dev,
291 struct comedi_subdevice *s)
292{
293
294
295 return 0;
296}
297
298int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
299 int (*cb) (int, int, int, unsigned long), unsigned long arg)
300{
301 s->type = COMEDI_SUBD_DIO;
302 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
303 s->n_chan = 16;
304 s->range_table = &range_digital;
305 s->maxdata = 1;
306
307 s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
308 if (!s->private)
309 return -ENOMEM;
310
311 CALLBACK_ARG = arg;
312 if (cb == NULL) {
313 CALLBACK_FUNC = subdev_700_cb;
314 } else {
315 CALLBACK_FUNC = cb;
316 }
317 s->insn_bits = subdev_700_insn;
318 s->insn_config = subdev_700_insn_config;
319
320 s->state = 0;
321 s->io_bits = 0x00ff;
322 do_config(dev, s);
323
324 return 0;
325}
326
327int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
328 int (*cb) (int, int, int, unsigned long),
329 unsigned long arg)
330{
331 int ret;
332
333 ret = subdev_700_init(dev, s, cb, arg);
334 if (ret < 0)
335 return ret;
336
337 s->do_cmdtest = subdev_700_cmdtest;
338 s->do_cmd = subdev_700_cmd;
339 s->cancel = subdev_700_cancel;
340
341 subdevpriv->have_irq = 1;
342
343 return 0;
344}
345
346void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
347{
348 if (s->private) {
349 if (subdevpriv->have_irq) {
350 }
351
352 kfree(s->private);
353 }
354}
355
356EXPORT_SYMBOL(subdev_700_init);
357EXPORT_SYMBOL(subdev_700_init_irq);
358EXPORT_SYMBOL(subdev_700_cleanup);
359EXPORT_SYMBOL(subdev_700_interrupt);
360
361static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
362{
363 struct comedi_subdevice *s;
364 unsigned long iobase = 0;
365#ifdef incomplete
366 unsigned int irq = 0;
367#endif
368 struct pcmcia_device *link;
369
370
371 if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
372 return -ENOMEM;
373
374
375 switch (thisboard->bustype) {
376 case pcmcia_bustype:
377 link = pcmcia_cur_dev;
378 if (!link)
379 return -EIO;
380 iobase = link->io.BasePort1;
381#ifdef incomplete
382 irq = link->irq.AssignedIRQ;
383#endif
384 break;
385 default:
386 printk("bug! couldn't determine board type\n");
387 return -EINVAL;
388 break;
389 }
390 printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
391 thisboard->name, iobase);
392#ifdef incomplete
393 if (irq) {
394 printk(", irq %u", irq);
395 }
396#endif
397
398 printk("\n");
399
400 if (iobase == 0) {
401 printk("io base address is zero!\n");
402 return -EINVAL;
403 }
404
405 dev->iobase = iobase;
406
407#ifdef incomplete
408
409 dev->irq = irq;
410#endif
411
412 dev->board_name = thisboard->name;
413
414 if (alloc_subdevices(dev, 1) < 0)
415 return -ENOMEM;
416
417
418 s = dev->subdevices + 0;
419 subdev_700_init(dev, s, NULL, dev->iobase);
420
421 return 0;
422};
423
424static int dio700_detach(struct comedi_device *dev)
425{
426 printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
427
428 if (dev->subdevices)
429 subdev_700_cleanup(dev, dev->subdevices + 0);
430
431 if (thisboard->bustype != pcmcia_bustype && dev->iobase)
432 release_region(dev->iobase, DIO700_SIZE);
433 if (dev->irq)
434 free_irq(dev->irq, dev);
435
436 return 0;
437};
438
439
440
441
442
443
444
445
446
447
448#ifdef PCMCIA_DEBUG
449static int pc_debug = PCMCIA_DEBUG;
450module_param(pc_debug, int, 0644);
451#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
452static char *version = "ni_daq_700.c, based on dummy_cs.c";
453#else
454#define DEBUG(n, args...)
455#endif
456
457
458
459static void dio700_config(struct pcmcia_device *link);
460static void dio700_release(struct pcmcia_device *link);
461static int dio700_cs_suspend(struct pcmcia_device *p_dev);
462static int dio700_cs_resume(struct pcmcia_device *p_dev);
463
464
465
466
467
468
469
470static int dio700_cs_attach(struct pcmcia_device *);
471static void dio700_cs_detach(struct pcmcia_device *);
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486static const dev_info_t dev_info = "ni_daq_700";
487
488struct local_info_t {
489 struct pcmcia_device *link;
490 dev_node_t node;
491 int stop;
492 struct bus_operations *bus;
493};
494
495
496
497
498
499
500
501
502
503
504
505
506
507static int dio700_cs_attach(struct pcmcia_device *link)
508{
509 struct local_info_t *local;
510
511 printk(KERN_INFO "ni_daq_700: cs-attach\n");
512
513 DEBUG(0, "dio700_cs_attach()\n");
514
515
516 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
517 if (!local)
518 return -ENOMEM;
519 local->link = link;
520 link->priv = local;
521
522
523 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
524 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
525 link->irq.Handler = NULL;
526
527
528
529
530
531
532
533
534 link->conf.Attributes = 0;
535 link->conf.IntType = INT_MEMORY_AND_IO;
536
537 pcmcia_cur_dev = link;
538
539 dio700_config(link);
540
541 return 0;
542}
543
544
545
546
547
548
549
550
551
552
553static void dio700_cs_detach(struct pcmcia_device *link)
554{
555
556 printk(KERN_INFO "ni_daq_700: cs-detach!\n");
557
558 DEBUG(0, "dio700_cs_detach(0x%p)\n", link);
559
560 if (link->dev_node) {
561 ((struct local_info_t *)link->priv)->stop = 1;
562 dio700_release(link);
563 }
564
565
566 if (link->priv)
567 kfree(link->priv);
568
569}
570
571
572
573
574
575
576
577
578
579static void dio700_config(struct pcmcia_device *link)
580{
581 struct local_info_t *dev = link->priv;
582 tuple_t tuple;
583 cisparse_t parse;
584 int last_ret;
585 u_char buf[64];
586 win_req_t req;
587 memreq_t map;
588 cistpl_cftable_entry_t dflt = { 0 };
589
590 printk(KERN_INFO "ni_daq_700: cs-config\n");
591
592 DEBUG(0, "dio700_config(0x%p)\n", link);
593
594
595
596
597
598 tuple.DesiredTuple = CISTPL_CONFIG;
599 tuple.Attributes = 0;
600 tuple.TupleData = buf;
601 tuple.TupleDataMax = sizeof(buf);
602 tuple.TupleOffset = 0;
603
604 last_ret = pcmcia_get_first_tuple(link, &tuple);
605 if (last_ret) {
606 cs_error(link, GetFirstTuple, last_ret);
607 goto cs_failed;
608 }
609
610 last_ret = pcmcia_get_tuple_data(link, &tuple);
611 if (last_ret) {
612 cs_error(link, GetTupleData, last_ret);
613 goto cs_failed;
614 }
615
616 last_ret = pcmcia_parse_tuple(&tuple, &parse);
617 if (last_ret) {
618 cs_error(link, ParseTuple, last_ret);
619 goto cs_failed;
620 }
621 link->conf.ConfigBase = parse.config.base;
622 link->conf.Present = parse.config.rmask[0];
623
624
625
626
627
628
629
630
631
632
633
634
635
636 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
637 last_ret = pcmcia_get_first_tuple(link, &tuple);
638 if (last_ret != 0) {
639 cs_error(link, GetFirstTuple, last_ret);
640 goto cs_failed;
641 }
642 while (1) {
643 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
644 if (pcmcia_get_tuple_data(link, &tuple) != 0)
645 goto next_entry;
646 if (pcmcia_parse_tuple(&tuple, &parse) != 0)
647 goto next_entry;
648
649 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
650 dflt = *cfg;
651 if (cfg->index == 0)
652 goto next_entry;
653 link->conf.ConfigIndex = cfg->index;
654
655
656 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
657 link->conf.Attributes |= CONF_ENABLE_SPKR;
658 link->conf.Status = CCSR_AUDIO_ENA;
659 }
660
661
662 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
663 link->conf.Attributes |= CONF_ENABLE_IRQ;
664
665
666 link->io.NumPorts1 = link->io.NumPorts2 = 0;
667 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
668 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
669 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
670 if (!(io->flags & CISTPL_IO_8BIT))
671 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
672 if (!(io->flags & CISTPL_IO_16BIT))
673 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
674 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
675 link->io.BasePort1 = io->win[0].base;
676 link->io.NumPorts1 = io->win[0].len;
677 if (io->nwin > 1) {
678 link->io.Attributes2 = link->io.Attributes1;
679 link->io.BasePort2 = io->win[1].base;
680 link->io.NumPorts2 = io->win[1].len;
681 }
682
683 if (pcmcia_request_io(link, &link->io) != 0)
684 goto next_entry;
685 }
686
687 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
688 cistpl_mem_t *mem =
689 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
690 req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
691 req.Attributes |= WIN_ENABLE;
692 req.Base = mem->win[0].host_addr;
693 req.Size = mem->win[0].len;
694 if (req.Size < 0x1000)
695 req.Size = 0x1000;
696 req.AccessSpeed = 0;
697 if (pcmcia_request_window(&link, &req, &link->win))
698 goto next_entry;
699 map.Page = 0;
700 map.CardOffset = mem->win[0].card_addr;
701 if (pcmcia_map_mem_page(link->win, &map))
702 goto next_entry;
703 }
704
705 break;
706
707next_entry:
708
709 last_ret = pcmcia_get_next_tuple(link, &tuple);
710 if (last_ret) {
711 cs_error(link, GetNextTuple, last_ret);
712 goto cs_failed;
713 }
714 }
715
716
717
718
719
720
721 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
722 last_ret = pcmcia_request_irq(link, &link->irq);
723 if (last_ret) {
724 cs_error(link, RequestIRQ, last_ret);
725 goto cs_failed;
726 }
727 }
728
729
730
731
732
733
734 last_ret = pcmcia_request_configuration(link, &link->conf);
735 if (last_ret != 0) {
736 cs_error(link, RequestConfiguration, last_ret);
737 goto cs_failed;
738 }
739
740
741
742
743
744 sprintf(dev->node.dev_name, "ni_daq_700");
745 dev->node.major = dev->node.minor = 0;
746 link->dev_node = &dev->node;
747
748
749 printk(KERN_INFO "%s: index 0x%02x",
750 dev->node.dev_name, link->conf.ConfigIndex);
751 if (link->conf.Attributes & CONF_ENABLE_IRQ)
752 printk(", irq %d", link->irq.AssignedIRQ);
753 if (link->io.NumPorts1)
754 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
755 link->io.BasePort1 + link->io.NumPorts1 - 1);
756 if (link->io.NumPorts2)
757 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
758 link->io.BasePort2 + link->io.NumPorts2 - 1);
759 if (link->win)
760 printk(", mem 0x%06lx-0x%06lx", req.Base,
761 req.Base + req.Size - 1);
762 printk("\n");
763
764 return;
765
766cs_failed:
767 printk(KERN_INFO "ni_daq_700 cs failed");
768 dio700_release(link);
769
770}
771
772static void dio700_release(struct pcmcia_device *link)
773{
774 DEBUG(0, "dio700_release(0x%p)\n", link);
775
776 pcmcia_disable_device(link);
777}
778
779
780
781
782
783
784
785
786
787
788
789
790
791static int dio700_cs_suspend(struct pcmcia_device *link)
792{
793 struct local_info_t *local = link->priv;
794
795
796 local->stop = 1;
797 return 0;
798}
799
800static int dio700_cs_resume(struct pcmcia_device *link)
801{
802 struct local_info_t *local = link->priv;
803
804 local->stop = 0;
805 return 0;
806}
807
808
809
810static struct pcmcia_device_id dio700_cs_ids[] = {
811
812 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),
813 PCMCIA_DEVICE_NULL
814};
815
816MODULE_LICENSE("GPL");
817MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
818
819struct pcmcia_driver dio700_cs_driver = {
820 .probe = dio700_cs_attach,
821 .remove = dio700_cs_detach,
822 .suspend = dio700_cs_suspend,
823 .resume = dio700_cs_resume,
824 .id_table = dio700_cs_ids,
825 .owner = THIS_MODULE,
826 .drv = {
827 .name = dev_info,
828 },
829};
830
831static int __init init_dio700_cs(void)
832{
833 printk("ni_daq_700: cs-init \n");
834 DEBUG(0, "%s\n", version);
835 pcmcia_register_driver(&dio700_cs_driver);
836 return 0;
837}
838
839static void __exit exit_dio700_cs(void)
840{
841 DEBUG(0, "ni_daq_700: unloading\n");
842 pcmcia_unregister_driver(&dio700_cs_driver);
843}
844
845int __init init_module(void)
846{
847 int ret;
848
849 ret = init_dio700_cs();
850 if (ret < 0)
851 return ret;
852
853 return comedi_driver_register(&driver_dio700);
854}
855
856void __exit cleanup_module(void)
857{
858 exit_dio700_cs();
859 comedi_driver_unregister(&driver_dio700);
860}
861