pcmcia: use autoconfiguration feature for ioports and iomem
[deliverable/linux.git] / drivers / staging / comedi / drivers / ni_daq_700.c
CommitLineData
1f9bbbe2
FB
1/*
2 * comedi/drivers/ni_daq_700.c
3 * Driver for DAQCard-700 DIO only
4 * copied from 8255
5 *
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25/*
26Driver: ni_daq_700
27Description: National Instruments PCMCIA DAQCard-700 DIO only
28Author: Fred Brooks <nsaspook@nsaspook.com>,
29 based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
30Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
31Status: works
32Updated: Thu, 21 Feb 2008 12:07:20 +0000
33
34The daqcard-700 appears in Comedi as a single digital I/O subdevice with
3516 channels. The channel 0 corresponds to the daqcard-700's output
36port, bit 0; channel 8 corresponds to the input port, bit 0.
37
38Direction configuration: channels 0-7 output, 8-15 input (8225 device
39emu as port A output, port B input, port C N/A).
40
41IRQ is assigned but not used.
42*/
43
25436dc9 44#include <linux/interrupt.h>
5a0e3ad6 45#include <linux/slab.h>
1f9bbbe2
FB
46#include "../comedidev.h"
47
48#include <linux/ioport.h>
1f9bbbe2 49
1f9bbbe2
FB
50#include <pcmcia/cistpl.h>
51#include <pcmcia/cisreg.h>
52#include <pcmcia/ds.h>
53
54static struct pcmcia_device *pcmcia_cur_dev = NULL;
55
2696fb57 56#define DIO700_SIZE 8 /* size of io region used by board */
1f9bbbe2 57
0a85b6f0
MT
58static int dio700_attach(struct comedi_device *dev,
59 struct comedi_devconfig *it);
da91b269 60static int dio700_detach(struct comedi_device *dev);
1f9bbbe2
FB
61
62enum dio700_bustype { pcmcia_bustype };
63
4cab3740 64struct dio700_board {
1f9bbbe2 65 const char *name;
2696fb57
BP
66 int device_id; /* device id for pcmcia board */
67 enum dio700_bustype bustype; /* PCMCIA */
68 int have_dio; /* have daqcard-700 dio */
69 /* function pointers so we can use inb/outb or readb/writeb */
70 /* as appropriate */
1f9bbbe2
FB
71 unsigned int (*read_byte) (unsigned int address);
72 void (*write_byte) (unsigned int byte, unsigned int address);
4cab3740 73};
1f9bbbe2 74
4cab3740 75static const struct dio700_board dio700_boards[] = {
1f9bbbe2 76 {
0a85b6f0 77 .name = "daqcard-700",
9a16a92c
GH
78 /* 0x10b is manufacturer id, 0x4743 is device id */
79 .device_id = 0x4743,
0a85b6f0
MT
80 .bustype = pcmcia_bustype,
81 .have_dio = 1,
82 },
1f9bbbe2 83 {
0a85b6f0 84 .name = "ni_daq_700",
9a16a92c
GH
85 /* 0x10b is manufacturer id, 0x4743 is device id */
86 .device_id = 0x4743,
0a85b6f0
MT
87 .bustype = pcmcia_bustype,
88 .have_dio = 1,
89 },
1f9bbbe2
FB
90};
91
92/*
93 * Useful for shorthand access to the particular board structure
94 */
4cab3740 95#define thisboard ((const struct dio700_board *)dev->board_ptr)
1f9bbbe2 96
adf32843
BP
97struct dio700_private {
98
1f9bbbe2 99 int data; /* number of data points left to be taken */
adf32843
BP
100};
101
adf32843 102#define devpriv ((struct dio700_private *)dev->private)
1f9bbbe2 103
139dfbdf 104static struct comedi_driver driver_dio700 = {
68c3dbff
BP
105 .driver_name = "ni_daq_700",
106 .module = THIS_MODULE,
107 .attach = dio700_attach,
108 .detach = dio700_detach,
8629efa4 109 .num_names = ARRAY_SIZE(dio700_boards),
68c3dbff
BP
110 .board_name = &dio700_boards[0].name,
111 .offset = sizeof(struct dio700_board),
1f9bbbe2
FB
112};
113
114/* the real driver routines */
115
116#define _700_SIZE 8
117
118#define _700_DATA 0
119
120#define DIO_W 0x04
121#define DIO_R 0x05
122
123struct subdev_700_struct {
124 unsigned long cb_arg;
125 int (*cb_func) (int, int, int, unsigned long);
126 int have_irq;
127};
128
129#define CALLBACK_ARG (((struct subdev_700_struct *)s->private)->cb_arg)
130#define CALLBACK_FUNC (((struct subdev_700_struct *)s->private)->cb_func)
131#define subdevpriv ((struct subdev_700_struct *)s->private)
132
da91b269 133static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
1f9bbbe2 134
da91b269 135void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
1f9bbbe2 136{
790c5541 137 short d;
1f9bbbe2
FB
138
139 d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
140
141 comedi_buf_put(s->async, d);
142 s->async->events |= COMEDI_CB_EOS;
143
144 comedi_event(dev, s);
145}
ee21350f 146EXPORT_SYMBOL(subdev_700_interrupt);
1f9bbbe2
FB
147
148static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
149{
150 /* port is always A for output and B for input (8255 emu) */
151 unsigned long iobase = arg;
152
153 if (dir) {
154 outb(data, iobase + DIO_W);
155 return 0;
156 } else {
157 return inb(iobase + DIO_R);
158 }
159}
160
0a85b6f0
MT
161static int subdev_700_insn(struct comedi_device *dev,
162 struct comedi_subdevice *s, struct comedi_insn *insn,
163 unsigned int *data)
1f9bbbe2
FB
164{
165 if (data[0]) {
166 s->state &= ~data[0];
167 s->state |= (data[0] & data[1]);
168
169 if (data[0] & 0xff)
170 CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
0a85b6f0 171 CALLBACK_ARG);
1f9bbbe2
FB
172 }
173
174 data[1] = s->state & 0xff;
175 data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
176
177 return 2;
178}
179
0a85b6f0
MT
180static int subdev_700_insn_config(struct comedi_device *dev,
181 struct comedi_subdevice *s,
182 struct comedi_insn *insn, unsigned int *data)
1f9bbbe2
FB
183{
184
185 switch (data[0]) {
186 case INSN_CONFIG_DIO_INPUT:
187 break;
188 case INSN_CONFIG_DIO_OUTPUT:
189 break;
190 case INSN_CONFIG_DIO_QUERY:
191 data[1] =
0a85b6f0
MT
192 (s->
193 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
194 COMEDI_INPUT;
1f9bbbe2
FB
195 return insn->n;
196 break;
197 default:
198 return -EINVAL;
199 }
200
201 return 1;
202}
203
da91b269 204static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
1f9bbbe2
FB
205{ /* use powerup defaults */
206 return;
207}
208
0a85b6f0
MT
209static int subdev_700_cmdtest(struct comedi_device *dev,
210 struct comedi_subdevice *s,
211 struct comedi_cmd *cmd)
1f9bbbe2
FB
212{
213 int err = 0;
214 unsigned int tmp;
215
216 /* step 1 */
217
218 tmp = cmd->start_src;
219 cmd->start_src &= TRIG_NOW;
220 if (!cmd->start_src || tmp != cmd->start_src)
221 err++;
222
223 tmp = cmd->scan_begin_src;
224 cmd->scan_begin_src &= TRIG_EXT;
225 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
226 err++;
227
228 tmp = cmd->convert_src;
229 cmd->convert_src &= TRIG_FOLLOW;
230 if (!cmd->convert_src || tmp != cmd->convert_src)
231 err++;
232
233 tmp = cmd->scan_end_src;
234 cmd->scan_end_src &= TRIG_COUNT;
235 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
236 err++;
237
238 tmp = cmd->stop_src;
239 cmd->stop_src &= TRIG_NONE;
240 if (!cmd->stop_src || tmp != cmd->stop_src)
241 err++;
242
243 if (err)
244 return 1;
245
246 /* step 2 */
247
248 if (err)
249 return 2;
250
251 /* step 3 */
252
253 if (cmd->start_arg != 0) {
254 cmd->start_arg = 0;
255 err++;
256 }
257 if (cmd->scan_begin_arg != 0) {
258 cmd->scan_begin_arg = 0;
259 err++;
260 }
261 if (cmd->convert_arg != 0) {
262 cmd->convert_arg = 0;
263 err++;
264 }
265 if (cmd->scan_end_arg != 1) {
266 cmd->scan_end_arg = 1;
267 err++;
268 }
269 if (cmd->stop_arg != 0) {
270 cmd->stop_arg = 0;
271 err++;
272 }
273
274 if (err)
275 return 3;
276
277 /* step 4 */
278
279 if (err)
280 return 4;
281
282 return 0;
283}
284
da91b269 285static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1f9bbbe2
FB
286{
287 /* FIXME */
288
289 return 0;
290}
291
0a85b6f0
MT
292static int subdev_700_cancel(struct comedi_device *dev,
293 struct comedi_subdevice *s)
1f9bbbe2
FB
294{
295 /* FIXME */
296
297 return 0;
298}
299
0a85b6f0
MT
300int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
301 int (*cb) (int, int, int, unsigned long), unsigned long arg)
1f9bbbe2
FB
302{
303 s->type = COMEDI_SUBD_DIO;
304 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
305 s->n_chan = 16;
306 s->range_table = &range_digital;
307 s->maxdata = 1;
308
309 s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
310 if (!s->private)
311 return -ENOMEM;
312
313 CALLBACK_ARG = arg;
9a16a92c 314 if (cb == NULL)
1f9bbbe2 315 CALLBACK_FUNC = subdev_700_cb;
9a16a92c 316 else
1f9bbbe2 317 CALLBACK_FUNC = cb;
9a16a92c 318
1f9bbbe2
FB
319 s->insn_bits = subdev_700_insn;
320 s->insn_config = subdev_700_insn_config;
321
322 s->state = 0;
323 s->io_bits = 0x00ff;
324 do_config(dev, s);
325
326 return 0;
327}
ee21350f 328EXPORT_SYMBOL(subdev_700_init);
1f9bbbe2 329
da91b269 330int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
331 int (*cb) (int, int, int, unsigned long),
332 unsigned long arg)
1f9bbbe2
FB
333{
334 int ret;
335
336 ret = subdev_700_init(dev, s, cb, arg);
337 if (ret < 0)
338 return ret;
339
340 s->do_cmdtest = subdev_700_cmdtest;
341 s->do_cmd = subdev_700_cmd;
342 s->cancel = subdev_700_cancel;
343
344 subdevpriv->have_irq = 1;
345
346 return 0;
347}
ee21350f 348EXPORT_SYMBOL(subdev_700_init_irq);
1f9bbbe2 349
da91b269 350void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
1f9bbbe2 351{
9a16a92c
GH
352 if (s->private)
353 if (subdevpriv->have_irq)
1f9bbbe2 354
9a16a92c 355 kfree(s->private);
1f9bbbe2 356}
1f9bbbe2 357EXPORT_SYMBOL(subdev_700_cleanup);
1f9bbbe2 358
da91b269 359static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1f9bbbe2 360{
34c43922 361 struct comedi_subdevice *s;
1f9bbbe2
FB
362 unsigned long iobase = 0;
363#ifdef incomplete
364 unsigned int irq = 0;
365#endif
366 struct pcmcia_device *link;
367
368 /* allocate and initialize dev->private */
adf32843 369 if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
1f9bbbe2
FB
370 return -ENOMEM;
371
2696fb57 372 /* get base address, irq etc. based on bustype */
1f9bbbe2
FB
373 switch (thisboard->bustype) {
374 case pcmcia_bustype:
375 link = pcmcia_cur_dev; /* XXX hack */
376 if (!link)
377 return -EIO;
9a017a91 378 iobase = link->resource[0]->start;
1f9bbbe2 379#ifdef incomplete
eb14120f 380 irq = link->irq;
1f9bbbe2
FB
381#endif
382 break;
383 default:
384 printk("bug! couldn't determine board type\n");
385 return -EINVAL;
386 break;
387 }
388 printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
0a85b6f0 389 thisboard->name, iobase);
1f9bbbe2 390#ifdef incomplete
9a16a92c 391 if (irq)
1f9bbbe2 392 printk(", irq %u", irq);
9a16a92c 393
1f9bbbe2
FB
394#endif
395
396 printk("\n");
397
398 if (iobase == 0) {
399 printk("io base address is zero!\n");
400 return -EINVAL;
401 }
402
403 dev->iobase = iobase;
404
405#ifdef incomplete
406 /* grab our IRQ */
407 dev->irq = irq;
408#endif
409
410 dev->board_name = thisboard->name;
411
412 if (alloc_subdevices(dev, 1) < 0)
413 return -ENOMEM;
414
415 /* DAQCard-700 dio */
416 s = dev->subdevices + 0;
417 subdev_700_init(dev, s, NULL, dev->iobase);
418
419 return 0;
420};
421
da91b269 422static int dio700_detach(struct comedi_device *dev)
1f9bbbe2
FB
423{
424 printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
425
426 if (dev->subdevices)
427 subdev_700_cleanup(dev, dev->subdevices + 0);
428
429 if (thisboard->bustype != pcmcia_bustype && dev->iobase)
430 release_region(dev->iobase, DIO700_SIZE);
431 if (dev->irq)
5f74ea14 432 free_irq(dev->irq, dev);
1f9bbbe2
FB
433
434 return 0;
435};
436
55a19b39 437/* PCMCIA crap -- watch your words, please! */
1f9bbbe2
FB
438
439static void dio700_config(struct pcmcia_device *link);
440static void dio700_release(struct pcmcia_device *link);
441static int dio700_cs_suspend(struct pcmcia_device *p_dev);
442static int dio700_cs_resume(struct pcmcia_device *p_dev);
443
444/*
445 The attach() and detach() entry points are used to create and destroy
446 "instances" of the driver, where each instance represents everything
447 needed to manage one actual PCMCIA card.
448*/
449
450static int dio700_cs_attach(struct pcmcia_device *);
451static void dio700_cs_detach(struct pcmcia_device *);
452
453/*
454 You'll also need to prototype all the functions that will actually
455 be used to talk to your device. See 'memory_cs' for a good example
456 of a fully self-sufficient driver; the other drivers rely more or
457 less on other parts of the kernel.
458*/
459
30570f0d 460struct local_info_t {
1f9bbbe2 461 struct pcmcia_device *link;
1f9bbbe2
FB
462 int stop;
463 struct bus_operations *bus;
30570f0d 464};
1f9bbbe2
FB
465
466/*======================================================================
467
468 dio700_cs_attach() creates an "instance" of the driver, allocating
469 local data structures for one device. The device is registered
470 with Card Services.
471
472 The dev_link structure is initialized, but we don't actually
473 configure the card at this point -- we wait until we receive a
474 card insertion event.
475
476======================================================================*/
477
478static int dio700_cs_attach(struct pcmcia_device *link)
479{
30570f0d 480 struct local_info_t *local;
1f9bbbe2
FB
481
482 printk(KERN_INFO "ni_daq_700: cs-attach\n");
483
55a19b39 484 dev_dbg(&link->dev, "dio700_cs_attach()\n");
1f9bbbe2
FB
485
486 /* Allocate space for private device-specific data */
30570f0d 487 local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
1f9bbbe2
FB
488 if (!local)
489 return -ENOMEM;
490 local->link = link;
491 link->priv = local;
492
1f9bbbe2
FB
493 pcmcia_cur_dev = link;
494
495 dio700_config(link);
496
497 return 0;
498} /* dio700_cs_attach */
499
500/*======================================================================
501
502 This deletes a driver "instance". The device is de-registered
503 with Card Services. If it has been released, all local data
504 structures are freed. Otherwise, the structures will be freed
505 when the device is released.
506
507======================================================================*/
508
509static void dio700_cs_detach(struct pcmcia_device *link)
510{
511
512 printk(KERN_INFO "ni_daq_700: cs-detach!\n");
513
55a19b39 514 dev_dbg(&link->dev, "dio700_cs_detach\n");
1f9bbbe2 515
cdc268b4
JMC
516 ((struct local_info_t *)link->priv)->stop = 1;
517 dio700_release(link);
1f9bbbe2 518
30570f0d 519 /* This points to the parent struct local_info_t struct */
f25bd6bf 520 kfree(link->priv);
1f9bbbe2
FB
521
522} /* dio700_cs_detach */
523
524/*======================================================================
525
526 dio700_config() is scheduled to run after a CARD_INSERTION event
527 is received, to configure the PCMCIA socket, and to make the
528 device available to the system.
529
530======================================================================*/
531
55a19b39 532static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
55a19b39 533 void *priv_data)
1f9bbbe2 534{
00990e7c
DB
535 if (p_dev->config_index == 0)
536 return -EINVAL;
c3744138 537
00990e7c 538 return pcmcia_request_io(p_dev);
55a19b39 539}
1f9bbbe2 540
55a19b39
DB
541static void dio700_config(struct pcmcia_device *link)
542{
55a19b39
DB
543 win_req_t req;
544 int ret;
1f9bbbe2 545
55a19b39 546 printk(KERN_INFO "ni_daq_700: cs-config\n");
1f9bbbe2 547
55a19b39 548 dev_dbg(&link->dev, "dio700_config\n");
c3744138 549
00990e7c
DB
550 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
551 CONF_AUTO_SET_IO;
440eed43 552
0f52e86d 553 ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
55a19b39
DB
554 if (ret) {
555 dev_warn(&link->dev, "no configuration found\n");
556 goto failed;
1f9bbbe2
FB
557 }
558
eb14120f
DB
559 if (!link->irq)
560 goto failed;
1f9bbbe2
FB
561
562 /*
563 This actually configures the PCMCIA socket -- setting up
564 the I/O windows and the interrupt mapping, and putting the
565 card and host interface into "Memory and IO" mode.
566 */
1ac71e5a 567 ret = pcmcia_enable_device(link);
55a19b39
DB
568 if (ret != 0)
569 goto failed;
1f9bbbe2 570
1f9bbbe2 571 /* Finally, report what we've done */
7feabb64 572 dev_info(&link->dev, "index 0x%02x", link->config_index);
1ac71e5a 573 printk(", irq %d", link->irq);
9a017a91
DB
574 if (link->resource[0])
575 printk(", io %pR", link->resource[0]);
576 if (link->resource[1])
577 printk(" & %pR", link->resource[1]);
1f9bbbe2
FB
578 printk("\n");
579
580 return;
581
55a19b39 582failed:
1f9bbbe2
FB
583 printk(KERN_INFO "ni_daq_700 cs failed");
584 dio700_release(link);
585
586} /* dio700_config */
587
588static void dio700_release(struct pcmcia_device *link)
589{
55a19b39 590 dev_dbg(&link->dev, "dio700_release\n");
1f9bbbe2
FB
591
592 pcmcia_disable_device(link);
593} /* dio700_release */
594
595/*======================================================================
596
597 The card status event handler. Mostly, this schedules other
598 stuff to run after an event is received.
599
600 When a CARD_REMOVAL event is received, we immediately set a
601 private flag to block future accesses to this device. All the
602 functions that actually access the device should check this flag
603 to make sure the card is still present.
604
605======================================================================*/
606
607static int dio700_cs_suspend(struct pcmcia_device *link)
608{
30570f0d 609 struct local_info_t *local = link->priv;
1f9bbbe2
FB
610
611 /* Mark the device as stopped, to block IO until later */
612 local->stop = 1;
613 return 0;
614} /* dio700_cs_suspend */
615
616static int dio700_cs_resume(struct pcmcia_device *link)
617{
30570f0d 618 struct local_info_t *local = link->priv;
1f9bbbe2
FB
619
620 local->stop = 0;
621 return 0;
622} /* dio700_cs_resume */
623
624/*====================================================================*/
625
626static struct pcmcia_device_id dio700_cs_ids[] = {
627 /* N.B. These IDs should match those in dio700_boards */
628 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), /* daqcard-700 */
629 PCMCIA_DEVICE_NULL
630};
631
6c7f8196 632
1f9bbbe2 633MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
6c7f8196
AK
634MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
635MODULE_DESCRIPTION("Comedi driver for National Instruments "
636 "PCMCIA DAQCard-700 DIO");
637MODULE_LICENSE("GPL");
1f9bbbe2
FB
638
639struct pcmcia_driver dio700_cs_driver = {
640 .probe = dio700_cs_attach,
641 .remove = dio700_cs_detach,
642 .suspend = dio700_cs_suspend,
643 .resume = dio700_cs_resume,
644 .id_table = dio700_cs_ids,
645 .owner = THIS_MODULE,
646 .drv = {
1685e633 647 .name = "ni_daq_700",
1f9bbbe2
FB
648 },
649};
650
651static int __init init_dio700_cs(void)
652{
1f9bbbe2
FB
653 pcmcia_register_driver(&dio700_cs_driver);
654 return 0;
655}
656
657static void __exit exit_dio700_cs(void)
658{
55a19b39 659 pr_debug("ni_daq_700: unloading\n");
1f9bbbe2
FB
660 pcmcia_unregister_driver(&dio700_cs_driver);
661}
0a85b6f0 662
1f9bbbe2
FB
663int __init init_module(void)
664{
665 int ret;
666
667 ret = init_dio700_cs();
668 if (ret < 0)
669 return ret;
670
671 return comedi_driver_register(&driver_dio700);
672}
673
674void __exit cleanup_module(void)
675{
676 exit_dio700_cs();
677 comedi_driver_unregister(&driver_dio700);
678}
This page took 0.241578 seconds and 5 git commands to generate.