staging: comedi: propogate error code from comedi_alloc_subdevices
[deliverable/linux.git] / drivers / staging / comedi / drivers / pcm3730.c
CommitLineData
be06e5d5
BL
1/*
2 * comedi/drivers/pcm3730.c
3 * Driver for PCM3730 and clones
4 * Blaine Lee
5 * from pcl725 by David S.
6 */
7/*
8Driver: pcm3730
9Description: PCM3730
10Author: Blaine Lee
11Devices: [Advantech] PCM-3730 (pcm3730)
12Status: unknown
13
14Configuration options:
15 [0] - I/O port base
16*/
17
18#include "../comedidev.h"
19
20#include <linux/ioport.h>
21
2696fb57 22#define PCM3730_SIZE 4 /* consecutive io port addresses */
be06e5d5 23
2696fb57 24#define PCM3730_DOA 0 /* offsets for each port */
be06e5d5
BL
25#define PCM3730_DOB 2
26#define PCM3730_DOC 3
27#define PCM3730_DIA 0
28#define PCM3730_DIB 2
29#define PCM3730_DIC 3
30
0a85b6f0
MT
31static int pcm3730_do_insn_bits(struct comedi_device *dev,
32 struct comedi_subdevice *s,
33 struct comedi_insn *insn, unsigned int *data)
be06e5d5
BL
34{
35 if (insn->n != 2)
36 return -EINVAL;
37 if (data[0]) {
38 s->state &= ~data[0];
39 s->state |= (data[0] & data[1]);
40 outb(s->state, dev->iobase + (unsigned long)(s->private));
41 }
42 data[1] = s->state;
43
44 return 2;
45}
46
0a85b6f0
MT
47static int pcm3730_di_insn_bits(struct comedi_device *dev,
48 struct comedi_subdevice *s,
49 struct comedi_insn *insn, unsigned int *data)
be06e5d5
BL
50{
51 if (insn->n != 2)
52 return -EINVAL;
53 data[1] = inb(dev->iobase + (unsigned long)(s->private));
54 return 2;
55}
56
0a85b6f0
MT
57static int pcm3730_attach(struct comedi_device *dev,
58 struct comedi_devconfig *it)
be06e5d5 59{
34c43922 60 struct comedi_subdevice *s;
be06e5d5 61 unsigned long iobase;
8b6c5694 62 int ret;
be06e5d5
BL
63
64 iobase = it->options[0];
b1e68ea5 65 printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
be06e5d5
BL
66 if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) {
67 printk("I/O port conflict\n");
68 return -EIO;
69 }
70 dev->iobase = iobase;
71 dev->board_name = "pcm3730";
72 dev->iobase = dev->iobase;
73 dev->irq = 0;
74
8b6c5694
HS
75 ret = comedi_alloc_subdevices(dev, 6);
76 if (ret)
77 return ret;
be06e5d5
BL
78
79 s = dev->subdevices + 0;
80 s->type = COMEDI_SUBD_DO;
81 s->subdev_flags = SDF_WRITABLE;
82 s->maxdata = 1;
83 s->n_chan = 8;
84 s->insn_bits = pcm3730_do_insn_bits;
85 s->range_table = &range_digital;
86 s->private = (void *)PCM3730_DOA;
87
88 s = dev->subdevices + 1;
89 s->type = COMEDI_SUBD_DO;
90 s->subdev_flags = SDF_WRITABLE;
91 s->maxdata = 1;
92 s->n_chan = 8;
93 s->insn_bits = pcm3730_do_insn_bits;
94 s->range_table = &range_digital;
95 s->private = (void *)PCM3730_DOB;
96
97 s = dev->subdevices + 2;
98 s->type = COMEDI_SUBD_DO;
99 s->subdev_flags = SDF_WRITABLE;
100 s->maxdata = 1;
101 s->n_chan = 8;
102 s->insn_bits = pcm3730_do_insn_bits;
103 s->range_table = &range_digital;
104 s->private = (void *)PCM3730_DOC;
105
106 s = dev->subdevices + 3;
107 s->type = COMEDI_SUBD_DI;
108 s->subdev_flags = SDF_READABLE;
109 s->maxdata = 1;
110 s->n_chan = 8;
111 s->insn_bits = pcm3730_di_insn_bits;
112 s->range_table = &range_digital;
113 s->private = (void *)PCM3730_DIA;
114
115 s = dev->subdevices + 4;
116 s->type = COMEDI_SUBD_DI;
117 s->subdev_flags = SDF_READABLE;
118 s->maxdata = 1;
119 s->n_chan = 8;
120 s->insn_bits = pcm3730_di_insn_bits;
121 s->range_table = &range_digital;
122 s->private = (void *)PCM3730_DIB;
123
124 s = dev->subdevices + 5;
125 s->type = COMEDI_SUBD_DI;
126 s->subdev_flags = SDF_READABLE;
127 s->maxdata = 1;
128 s->n_chan = 8;
129 s->insn_bits = pcm3730_di_insn_bits;
130 s->range_table = &range_digital;
131 s->private = (void *)PCM3730_DIC;
132
b1e68ea5 133 printk(KERN_INFO "\n");
be06e5d5
BL
134
135 return 0;
136}
137
484ecc95 138static void pcm3730_detach(struct comedi_device *dev)
be06e5d5 139{
be06e5d5
BL
140 if (dev->iobase)
141 release_region(dev->iobase, PCM3730_SIZE);
be06e5d5 142}
90f703d3 143
294f930d 144static struct comedi_driver pcm3730_driver = {
f3ebaf4b
HS
145 .driver_name = "pcm3730",
146 .module = THIS_MODULE,
147 .attach = pcm3730_attach,
148 .detach = pcm3730_detach,
149};
294f930d 150module_comedi_driver(pcm3730_driver);
f3ebaf4b 151
90f703d3
AT
152MODULE_AUTHOR("Comedi http://www.comedi.org");
153MODULE_DESCRIPTION("Comedi low-level driver");
154MODULE_LICENSE("GPL");
This page took 0.383298 seconds and 5 git commands to generate.