staging: comedi: comedi_test: simplify time since last AI scan
[deliverable/linux.git] / drivers / staging / comedi / drivers / cb_pcimdda.c
CommitLineData
7f62d87d
CC
1/*
2 comedi/drivers/cb_pcimdda.c
3 Computer Boards PCIM-DDA06-16 Comedi driver
4 Author: Calin Culianu <calin@ajvar.org>
5
6 COMEDI - Linux Control and Measurement Device Interface
7 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
7f62d87d
CC
18*/
19/*
20Driver: cb_pcimdda
21Description: Measurement Computing PCIM-DDA06-16
22Devices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda)
23Author: Calin Culianu <calin@ajvar.org>
24Updated: Mon, 14 Apr 2008 15:15:51 +0100
25Status: works
26
27All features of the PCIM-DDA06-16 board are supported. This board
28has 6 16-bit AO channels, and the usual 8255 DIO setup. (24 channels,
29configurable in banks of 8 and 4, etc.). This board does not support commands.
30
31The board has a peculiar way of specifying AO gain/range settings -- You have
321 jumper bank on the card, which either makes all 6 AO channels either
335 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar.
34
35Since there is absolutely _no_ way to tell in software how this jumper is set
36(well, at least according to the rather thin spec. from Measurement Computing
37 that comes with the board), the driver assumes the jumper is at its factory
38default setting of +/-5V.
39
40Also of note is the fact that this board features another jumper, whose
41state is also completely invisible to software. It toggles two possible AO
42output modes on the board:
43
44 - Update Mode: Writing to an AO channel instantaneously updates the actual
45 signal output by the DAC on the board (this is the factory default).
46 - Simultaneous XFER Mode: Writing to an AO channel has no effect until
47 you read from any one of the AO channels. This is useful for loading
48 all 6 AO values, and then reading from any one of the AO channels on the
49 device to instantly update all 6 AO values in unison. Useful for some
50 control apps, I would assume? If your jumper is in this setting, then you
51 need to issue your comedi_data_write()s to load all the values you want,
52 then issue one comedi_data_read() on any channel on the AO subdevice
53 to initiate the simultaneous XFER.
54
22f2f541 55Configuration Options: not applicable, uses PCI auto config
7f62d87d
CC
56*/
57
58/*
59 This is a driver for the Computer Boards PCIM-DDA06-16 Analog Output
60 card. This board has a unique register layout and as such probably
61 deserves its own driver file.
62
63 It is theoretically possible to integrate this board into the cb_pcidda
64 file, but since that isn't my code, I didn't want to significantly
65 modify that file to support this board (I thought it impolite to do so).
66
67 At any rate, if you feel ambitious, please feel free to take
68 the code out of this file and combine it with a more unified driver
69 file.
70
71 I would like to thank Timothy Curry <Timothy.Curry@rdec.redstone.army.mil>
72 for lending me a board so that I could write this driver.
73
74 -Calin Culianu <calin@ajvar.org>
75 */
76
ce157f80 77#include <linux/module.h>
33782dd5 78
bf5a5c0b 79#include "../comedi_pci.h"
7f62d87d 80
7f62d87d
CC
81#include "8255.h"
82
83/* device ids of the cards we support -- currently only 1 card supported */
558587e2 84#define PCI_ID_PCIM_DDA06_16 0x0053
7f62d87d 85
d9e33afb
HS
86/*
87 * Register map, 8-bit access only
88 */
89#define PCIMDDA_DA_CHAN(x) (0x00 + (x) * 2)
90#define PCIMDDA_8255_BASE_REG 0x0c
91
e2e01ecb
HS
92static int cb_pcimdda_ao_insn_write(struct comedi_device *dev,
93 struct comedi_subdevice *s,
94 struct comedi_insn *insn,
95 unsigned int *data)
7f62d87d 96{
aee815b5
HS
97 unsigned int chan = CR_CHAN(insn->chanspec);
98 unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan);
e2e01ecb 99 unsigned int val = s->readback[chan];
7f62d87d 100 int i;
7f62d87d 101
7f62d87d 102 for (i = 0; i < insn->n; i++) {
aee815b5
HS
103 val = data[i];
104
105 /*
106 * Write the LSB then MSB.
107 *
108 * If the simultaneous xfer mode is selected by the
109 * jumper on the card, a read instruction is needed
110 * in order to initiate the simultaneous transfer.
111 * Otherwise, the DAC will be updated when the MSB
112 * is written.
113 */
114 outb(val & 0x00ff, offset);
115 outb((val >> 8) & 0x00ff, offset + 1);
7f62d87d 116 }
e2e01ecb 117 s->readback[chan] = val;
7f62d87d 118
aee815b5
HS
119 return insn->n;
120}
7f62d87d 121
e2e01ecb
HS
122static int cb_pcimdda_ao_insn_read(struct comedi_device *dev,
123 struct comedi_subdevice *s,
124 struct comedi_insn *insn,
125 unsigned int *data)
7f62d87d 126{
e2e01ecb 127 unsigned int chan = CR_CHAN(insn->chanspec);
aee815b5 128
e2e01ecb
HS
129 /* Initiate the simultaneous transfer */
130 inw(dev->iobase + PCIMDDA_DA_CHAN(chan));
7f62d87d 131
e2e01ecb 132 return comedi_readback_insn_read(dev, s, insn, data);
7f62d87d
CC
133}
134
a690b7e5 135static int cb_pcimdda_auto_attach(struct comedi_device *dev,
6c7d2c8b 136 unsigned long context_unused)
fa090ab2 137{
750af5e5 138 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
fa090ab2 139 struct comedi_subdevice *s;
ce774eab 140 int ret;
fa090ab2 141
818f569f 142 ret = comedi_pci_enable(dev);
ce774eab
HS
143 if (ret)
144 return ret;
c8dd8e93 145 dev->iobase = pci_resource_start(pcidev, 3);
b41bf58f 146
ce774eab
HS
147 ret = comedi_alloc_subdevices(dev, 2);
148 if (ret)
149 return ret;
fa090ab2 150
6807d64d 151 s = &dev->subdevices[0];
fa090ab2 152 /* analog output subdevice */
22f2f541
HS
153 s->type = COMEDI_SUBD_AO;
154 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
155 s->n_chan = 6;
156 s->maxdata = 0xffff;
157 s->range_table = &range_bipolar5;
e2e01ecb
HS
158 s->insn_write = cb_pcimdda_ao_insn_write;
159 s->insn_read = cb_pcimdda_ao_insn_read;
160
161 ret = comedi_alloc_subdev_readback(s);
162 if (ret)
163 return ret;
fa090ab2 164
6807d64d 165 s = &dev->subdevices[1];
fa090ab2 166 /* digital i/o subdevice */
e6f2804d 167 return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG);
fa090ab2
HS
168}
169
48b992b4
HS
170static struct comedi_driver cb_pcimdda_driver = {
171 .driver_name = "cb_pcimdda",
172 .module = THIS_MODULE,
750af5e5 173 .auto_attach = cb_pcimdda_auto_attach,
aac307f9 174 .detach = comedi_pci_detach,
48b992b4
HS
175};
176
a690b7e5 177static int cb_pcimdda_pci_probe(struct pci_dev *dev,
b8f4ac23 178 const struct pci_device_id *id)
48b992b4 179{
b8f4ac23
HS
180 return comedi_pci_auto_config(dev, &cb_pcimdda_driver,
181 id->driver_data);
48b992b4
HS
182}
183
41e043fc 184static const struct pci_device_id cb_pcimdda_pci_table[] = {
cb3e9d86 185 { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_ID_PCIM_DDA06_16) },
48b992b4
HS
186 { 0 }
187};
188MODULE_DEVICE_TABLE(pci, cb_pcimdda_pci_table);
189
190static struct pci_driver cb_pcimdda_driver_pci_driver = {
191 .name = "cb_pcimdda",
192 .id_table = cb_pcimdda_pci_table,
193 .probe = cb_pcimdda_pci_probe,
9901a4d7 194 .remove = comedi_pci_auto_unconfig,
48b992b4
HS
195};
196module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver);
197
198MODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>");
199MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
200 "series. Currently only supports PCIM-DDA06-16 (which "
201 "also happens to be the only board in this series. :) ) ");
202MODULE_LICENSE("GPL");
This page took 0.796362 seconds and 5 git commands to generate.