]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/pcl725.c
staging: comedi: export alloc_subdevices as comedi_alloc_subdevices
[~andy/linux] / 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_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
24                           struct comedi_insn *insn, unsigned int *data)
25 {
26         if (insn->n != 2)
27                 return -EINVAL;
28
29         if (data[0]) {
30                 s->state &= ~data[0];
31                 s->state |= (data[0] & data[1]);
32                 outb(s->state, dev->iobase + PCL725_DO);
33         }
34
35         data[1] = s->state;
36
37         return 2;
38 }
39
40 static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
41                           struct comedi_insn *insn, unsigned int *data)
42 {
43         if (insn->n != 2)
44                 return -EINVAL;
45
46         data[1] = inb(dev->iobase + PCL725_DI);
47
48         return 2;
49 }
50
51 static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
52 {
53         struct comedi_subdevice *s;
54         unsigned long iobase;
55
56         iobase = it->options[0];
57         printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
58         if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
59                 printk("I/O port conflict\n");
60                 return -EIO;
61         }
62         dev->board_name = "pcl725";
63         dev->iobase = iobase;
64         dev->irq = 0;
65
66         if (comedi_alloc_subdevices(dev, 2) < 0)
67                 return -ENOMEM;
68
69         s = dev->subdevices + 0;
70         /* do */
71         s->type = COMEDI_SUBD_DO;
72         s->subdev_flags = SDF_WRITABLE;
73         s->maxdata = 1;
74         s->n_chan = 8;
75         s->insn_bits = pcl725_do_insn;
76         s->range_table = &range_digital;
77
78         s = dev->subdevices + 1;
79         /* di */
80         s->type = COMEDI_SUBD_DI;
81         s->subdev_flags = SDF_READABLE;
82         s->maxdata = 1;
83         s->n_chan = 8;
84         s->insn_bits = pcl725_di_insn;
85         s->range_table = &range_digital;
86
87         printk(KERN_INFO "\n");
88
89         return 0;
90 }
91
92 static void pcl725_detach(struct comedi_device *dev)
93 {
94         if (dev->iobase)
95                 release_region(dev->iobase, PCL725_SIZE);
96 }
97
98 static struct comedi_driver pcl725_driver = {
99         .driver_name    = "pcl725",
100         .module         = THIS_MODULE,
101         .attach         = pcl725_attach,
102         .detach         = pcl725_detach,
103 };
104 module_comedi_driver(pcl725_driver);
105
106 MODULE_AUTHOR("Comedi http://www.comedi.org");
107 MODULE_DESCRIPTION("Comedi low-level driver");
108 MODULE_LICENSE("GPL");