Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcl730.c
Go to the documentation of this file.
1 /*
2  * comedi/drivers/pcl730.c
3  * Driver for Advantech PCL-730 and clones
4  * José Luis Sánchez
5  */
6 /*
7 Driver: pcl730
8 Description: Advantech PCL-730 (& compatibles)
9 Author: José Luis Sánchez ([email protected])
10 Status: untested
11 Devices: [Advantech] PCL-730 (pcl730), [ICP] ISO-730 (iso730),
12  [Adlink] ACL-7130 (acl7130)
13 
14 Interrupts are not supported.
15 The ACL-7130 card have an 8254 timer/counter not supported by this driver.
16 */
17 
18 #include "../comedidev.h"
19 
20 #include <linux/ioport.h>
21 
22 #define PCL730_SIZE 4
23 #define ACL7130_SIZE 8
24 #define PCL730_IDIO_LO 0 /* Isolated Digital I/O low byte (ID0-ID7) */
25 #define PCL730_IDIO_HI 1 /* Isolated Digital I/O high byte (ID8-ID15) */
26 #define PCL730_DIO_LO 2 /* TTL Digital I/O low byte (D0-D7) */
27 #define PCL730_DIO_HI 3 /* TTL Digital I/O high byte (D8-D15) */
28 
29 struct pcl730_board {
30 
31  const char *name; /* board name */
32  unsigned int io_range; /* len of I/O space */
33 };
34 
35 static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
36  struct comedi_insn *insn, unsigned int *data)
37 {
38  if (data[0]) {
39  s->state &= ~data[0];
40  s->state |= (data[0] & data[1]);
41  }
42  if (data[0] & 0x00ff)
43  outb(s->state & 0xff,
44  dev->iobase + ((unsigned long)s->private));
45  if (data[0] & 0xff00)
46  outb((s->state >> 8),
47  dev->iobase + ((unsigned long)s->private) + 1);
48 
49  data[1] = s->state;
50 
51  return insn->n;
52 }
53 
54 static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
55  struct comedi_insn *insn, unsigned int *data)
56 {
57  data[1] = inb(dev->iobase + ((unsigned long)s->private)) |
58  (inb(dev->iobase + ((unsigned long)s->private) + 1) << 8);
59 
60  return insn->n;
61 }
62 
63 static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
64 {
65  const struct pcl730_board *board = comedi_board(dev);
66  struct comedi_subdevice *s;
67  unsigned long iobase;
68  unsigned int iorange;
69  int ret;
70 
71  iobase = it->options[0];
72  iorange = board->io_range;
73  printk(KERN_INFO "comedi%d: pcl730: board=%s 0x%04lx ", dev->minor,
74  board->name, iobase);
75  if (!request_region(iobase, iorange, "pcl730")) {
76  printk("I/O port conflict\n");
77  return -EIO;
78  }
79  dev->board_name = board->name;
80  dev->iobase = iobase;
81  dev->irq = 0;
82 
83  ret = comedi_alloc_subdevices(dev, 4);
84  if (ret)
85  return ret;
86 
87  s = &dev->subdevices[0];
88  /* Isolated do */
89  s->type = COMEDI_SUBD_DO;
91  s->maxdata = 1;
92  s->n_chan = 16;
93  s->insn_bits = pcl730_do_insn;
95  s->private = (void *)PCL730_IDIO_LO;
96 
97  s = &dev->subdevices[1];
98  /* Isolated di */
99  s->type = COMEDI_SUBD_DI;
101  s->maxdata = 1;
102  s->n_chan = 16;
103  s->insn_bits = pcl730_di_insn;
105  s->private = (void *)PCL730_IDIO_LO;
106 
107  s = &dev->subdevices[2];
108  /* TTL do */
109  s->type = COMEDI_SUBD_DO;
111  s->maxdata = 1;
112  s->n_chan = 16;
113  s->insn_bits = pcl730_do_insn;
115  s->private = (void *)PCL730_DIO_LO;
116 
117  s = &dev->subdevices[3];
118  /* TTL di */
119  s->type = COMEDI_SUBD_DI;
121  s->maxdata = 1;
122  s->n_chan = 16;
123  s->insn_bits = pcl730_di_insn;
125  s->private = (void *)PCL730_DIO_LO;
126 
127  printk(KERN_INFO "\n");
128 
129  return 0;
130 }
131 
132 static void pcl730_detach(struct comedi_device *dev)
133 {
134  const struct pcl730_board *board = comedi_board(dev);
135 
136  if (dev->iobase)
137  release_region(dev->iobase, board->io_range);
138 }
139 
140 static const struct pcl730_board boardtypes[] = {
141  { "pcl730", PCL730_SIZE, },
142  { "iso730", PCL730_SIZE, },
143  { "acl7130", ACL7130_SIZE, },
144 };
145 
146 static struct comedi_driver pcl730_driver = {
147  .driver_name = "pcl730",
148  .module = THIS_MODULE,
149  .attach = pcl730_attach,
150  .detach = pcl730_detach,
151  .board_name = &boardtypes[0].name,
152  .num_names = ARRAY_SIZE(boardtypes),
153  .offset = sizeof(struct pcl730_board),
154 };
155 module_comedi_driver(pcl730_driver);
156 
157 MODULE_AUTHOR("Comedi http://www.comedi.org");
158 MODULE_DESCRIPTION("Comedi low-level driver");
159 MODULE_LICENSE("GPL");