Version:  2.0.40 2.2.26 2.4.37 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7

Linux/drivers/staging/comedi/drivers/adl_pci7x3x.c

  1 /*
  2  * COMEDI driver for the ADLINK PCI-723x/743x series boards.
  3  * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
  4  *
  5  * Based on the adl_pci7230 driver written by:
  6  *      David Fernandez <dfcastelao@gmail.com>
  7  * and the adl_pci7432 driver written by:
  8  *      Michel Lachaine <mike@mikelachaine.ca>
  9  *
 10  * COMEDI - Linux Control and Measurement Device Interface
 11  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
 12  *
 13  * This program is free software; you can redistribute it and/or modify
 14  * it under the terms of the GNU General Public License as published by
 15  * the Free Software Foundation; either version 2 of the License, or
 16  * (at your option) any later version.
 17  *
 18  * This program is distributed in the hope that it will be useful,
 19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  * GNU General Public License for more details.
 22  */
 23 
 24 /*
 25  * Driver: adl_pci7x3x
 26  * Description: 32/64-Channel Isolated Digital I/O Boards
 27  * Devices: [ADLink] PCI-7230 (adl_pci7230), PCI-7233 (adl_pci7233),
 28  *   PCI-7234 (adl_pci7234), PCI-7432 (adl_pci7432), PCI-7433 (adl_pci7433),
 29  *   PCI-7434 (adl_pci7434)
 30  * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
 31  * Updated: Thu, 02 Aug 2012 14:27:46 -0700
 32  * Status: untested
 33  *
 34  * One or two subdevices are setup by this driver depending on
 35  * the number of digital inputs and/or outputs provided by the
 36  * board. Each subdevice has a maximum of 32 channels.
 37  *
 38  *      PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output
 39  *      PCI-7233 - 1 subdevice: 0 - 32 input
 40  *      PCI-7234 - 1 subdevice: 0 - 32 output
 41  *      PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output
 42  *      PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input
 43  *      PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output
 44  *
 45  * The PCI-7230, PCI-7432 and PCI-7433 boards also support external
 46  * interrupt signals on digital input channels 0 and 1. The PCI-7233
 47  * has dual-interrupt sources for change-of-state (COS) on any 16
 48  * digital input channels of LSB and for COS on any 16 digital input
 49  * lines of MSB. Interrupts are not currently supported by this
 50  * driver.
 51  *
 52  * Configuration Options: not applicable, uses comedi PCI auto config
 53  */
 54 
 55 #include <linux/module.h>
 56 
 57 #include "../comedi_pci.h"
 58 
 59 /*
 60  * Register I/O map (32-bit access only)
 61  */
 62 #define PCI7X3X_DIO_REG         0x00
 63 #define PCI743X_DIO_REG         0x04
 64 
 65 enum apci1516_boardid {
 66         BOARD_PCI7230,
 67         BOARD_PCI7233,
 68         BOARD_PCI7234,
 69         BOARD_PCI7432,
 70         BOARD_PCI7433,
 71         BOARD_PCI7434,
 72 };
 73 
 74 struct adl_pci7x3x_boardinfo {
 75         const char *name;
 76         int nsubdevs;
 77         int di_nchan;
 78         int do_nchan;
 79 };
 80 
 81 static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
 82         [BOARD_PCI7230] = {
 83                 .name           = "adl_pci7230",
 84                 .nsubdevs       = 2,
 85                 .di_nchan       = 16,
 86                 .do_nchan       = 16,
 87         },
 88         [BOARD_PCI7233] = {
 89                 .name           = "adl_pci7233",
 90                 .nsubdevs       = 1,
 91                 .di_nchan       = 32,
 92         },
 93         [BOARD_PCI7234] = {
 94                 .name           = "adl_pci7234",
 95                 .nsubdevs       = 1,
 96                 .do_nchan       = 32,
 97         },
 98         [BOARD_PCI7432] = {
 99                 .name           = "adl_pci7432",
100                 .nsubdevs       = 2,
101                 .di_nchan       = 32,
102                 .do_nchan       = 32,
103         },
104         [BOARD_PCI7433] = {
105                 .name           = "adl_pci7433",
106                 .nsubdevs       = 2,
107                 .di_nchan       = 64,
108         },
109         [BOARD_PCI7434] = {
110                 .name           = "adl_pci7434",
111                 .nsubdevs       = 2,
112                 .do_nchan       = 64,
113         }
114 };
115 
116 static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
117                                     struct comedi_subdevice *s,
118                                     struct comedi_insn *insn,
119                                     unsigned int *data)
120 {
121         unsigned long reg = (unsigned long)s->private;
122 
123         if (comedi_dio_update_state(s, data)) {
124                 unsigned int val = s->state;
125 
126                 if (s->n_chan == 16) {
127                         /*
128                          * It seems the PCI-7230 needs the 16-bit DO state
129                          * to be shifted left by 16 bits before being written
130                          * to the 32-bit register.  Set the value in both
131                          * halves of the register to be sure.
132                          */
133                         val |= val << 16;
134                 }
135                 outl(val, dev->iobase + reg);
136         }
137 
138         data[1] = s->state;
139 
140         return insn->n;
141 }
142 
143 static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev,
144                                     struct comedi_subdevice *s,
145                                     struct comedi_insn *insn,
146                                     unsigned int *data)
147 {
148         unsigned long reg = (unsigned long)s->private;
149 
150         data[1] = inl(dev->iobase + reg);
151 
152         return insn->n;
153 }
154 
155 static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
156                                    unsigned long context)
157 {
158         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
159         const struct adl_pci7x3x_boardinfo *board = NULL;
160         struct comedi_subdevice *s;
161         int subdev;
162         int nchan;
163         int ret;
164 
165         if (context < ARRAY_SIZE(adl_pci7x3x_boards))
166                 board = &adl_pci7x3x_boards[context];
167         if (!board)
168                 return -ENODEV;
169         dev->board_ptr = board;
170         dev->board_name = board->name;
171 
172         ret = comedi_pci_enable(dev);
173         if (ret)
174                 return ret;
175         dev->iobase = pci_resource_start(pcidev, 2);
176 
177         ret = comedi_alloc_subdevices(dev, board->nsubdevs);
178         if (ret)
179                 return ret;
180 
181         subdev = 0;
182 
183         if (board->di_nchan) {
184                 nchan = min(board->di_nchan, 32);
185 
186                 s = &dev->subdevices[subdev];
187                 /* Isolated digital inputs 0 to 15/31 */
188                 s->type         = COMEDI_SUBD_DI;
189                 s->subdev_flags = SDF_READABLE;
190                 s->n_chan       = nchan;
191                 s->maxdata      = 1;
192                 s->insn_bits    = adl_pci7x3x_di_insn_bits;
193                 s->range_table  = &range_digital;
194 
195                 s->private      = (void *)PCI7X3X_DIO_REG;
196 
197                 subdev++;
198 
199                 nchan = board->di_nchan - nchan;
200                 if (nchan) {
201                         s = &dev->subdevices[subdev];
202                         /* Isolated digital inputs 32 to 63 */
203                         s->type         = COMEDI_SUBD_DI;
204                         s->subdev_flags = SDF_READABLE;
205                         s->n_chan       = nchan;
206                         s->maxdata      = 1;
207                         s->insn_bits    = adl_pci7x3x_di_insn_bits;
208                         s->range_table  = &range_digital;
209 
210                         s->private      = (void *)PCI743X_DIO_REG;
211 
212                         subdev++;
213                 }
214         }
215 
216         if (board->do_nchan) {
217                 nchan = min(board->do_nchan, 32);
218 
219                 s = &dev->subdevices[subdev];
220                 /* Isolated digital outputs 0 to 15/31 */
221                 s->type         = COMEDI_SUBD_DO;
222                 s->subdev_flags = SDF_WRITABLE;
223                 s->n_chan       = nchan;
224                 s->maxdata      = 1;
225                 s->insn_bits    = adl_pci7x3x_do_insn_bits;
226                 s->range_table  = &range_digital;
227 
228                 s->private      = (void *)PCI7X3X_DIO_REG;
229 
230                 subdev++;
231 
232                 nchan = board->do_nchan - nchan;
233                 if (nchan) {
234                         s = &dev->subdevices[subdev];
235                         /* Isolated digital outputs 32 to 63 */
236                         s->type         = COMEDI_SUBD_DO;
237                         s->subdev_flags = SDF_WRITABLE;
238                         s->n_chan       = nchan;
239                         s->maxdata      = 1;
240                         s->insn_bits    = adl_pci7x3x_do_insn_bits;
241                         s->range_table  = &range_digital;
242 
243                         s->private      = (void *)PCI743X_DIO_REG;
244 
245                         subdev++;
246                 }
247         }
248 
249         return 0;
250 }
251 
252 static struct comedi_driver adl_pci7x3x_driver = {
253         .driver_name    = "adl_pci7x3x",
254         .module         = THIS_MODULE,
255         .auto_attach    = adl_pci7x3x_auto_attach,
256         .detach         = comedi_pci_detach,
257 };
258 
259 static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
260                                  const struct pci_device_id *id)
261 {
262         return comedi_pci_auto_config(dev, &adl_pci7x3x_driver,
263                                       id->driver_data);
264 }
265 
266 static const struct pci_device_id adl_pci7x3x_pci_table[] = {
267         { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 },
268         { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 },
269         { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 },
270         { PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 },
271         { PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 },
272         { PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 },
273         { 0 }
274 };
275 MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
276 
277 static struct pci_driver adl_pci7x3x_pci_driver = {
278         .name           = "adl_pci7x3x",
279         .id_table       = adl_pci7x3x_pci_table,
280         .probe          = adl_pci7x3x_pci_probe,
281         .remove         = comedi_pci_auto_unconfig,
282 };
283 module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
284 
285 MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards");
286 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
287 MODULE_LICENSE("GPL");
288 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us