Merge branch 'kmemtrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / drivers / staging / comedi / drivers / pcl725.c
1 /*
2  * comedi/drivers/pcl725.c
3  * Driver for PCL725 and clones
4  * David A. Schleef
5  */
6 /*
7 Driver: pcl725
8 Description: Advantech PCL-725 (& compatibles)
9 Author: ds
10 Status: unknown
11 Devices: [Advantech] PCL-725 (pcl725)
12 */
13
14 #include "../comedidev.h"
15
16 #include <linux/ioport.h>
17
18 #define PCL725_SIZE 2
19
20 #define PCL725_DO 0
21 #define PCL725_DI 1
22
23 static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it);
24 static int pcl725_detach(struct comedi_device * dev);
25 static struct comedi_driver driver_pcl725 = {
26       driver_name:"pcl725",
27       module:THIS_MODULE,
28       attach:pcl725_attach,
29       detach:pcl725_detach,
30 };
31
32 COMEDI_INITCLEANUP(driver_pcl725);
33
34 static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
35         struct comedi_insn * insn, unsigned int * data)
36 {
37         if (insn->n != 2)
38                 return -EINVAL;
39
40         if (data[0]) {
41                 s->state &= ~data[0];
42                 s->state |= (data[0] & data[1]);
43                 outb(s->state, dev->iobase + PCL725_DO);
44         }
45
46         data[1] = s->state;
47
48         return 2;
49 }
50
51 static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
52         struct comedi_insn * insn, unsigned int * data)
53 {
54         if (insn->n != 2)
55                 return -EINVAL;
56
57         data[1] = inb(dev->iobase + PCL725_DI);
58
59         return 2;
60 }
61
62 static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it)
63 {
64         struct comedi_subdevice *s;
65         unsigned long iobase;
66
67         iobase = it->options[0];
68         printk("comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
69         if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
70                 printk("I/O port conflict\n");
71                 return -EIO;
72         }
73         dev->board_name = "pcl725";
74         dev->iobase = iobase;
75         dev->irq = 0;
76
77         if (alloc_subdevices(dev, 2) < 0)
78                 return -ENOMEM;
79
80         s = dev->subdevices + 0;
81         /* do */
82         s->type = COMEDI_SUBD_DO;
83         s->subdev_flags = SDF_WRITABLE;
84         s->maxdata = 1;
85         s->n_chan = 8;
86         s->insn_bits = pcl725_do_insn;
87         s->range_table = &range_digital;
88
89         s = dev->subdevices + 1;
90         /* di */
91         s->type = COMEDI_SUBD_DI;
92         s->subdev_flags = SDF_READABLE;
93         s->maxdata = 1;
94         s->n_chan = 8;
95         s->insn_bits = pcl725_di_insn;
96         s->range_table = &range_digital;
97
98         printk("\n");
99
100         return 0;
101 }
102
103 static int pcl725_detach(struct comedi_device * dev)
104 {
105         printk("comedi%d: pcl725: remove\n", dev->minor);
106
107         if (dev->iobase)
108                 release_region(dev->iobase, PCL725_SIZE);
109
110         return 0;
111 }