Commit | Line | Data |
---|---|---|
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 | /* | |
20 | Driver: cb_pcimdda | |
21 | Description: Measurement Computing PCIM-DDA06-16 | |
22 | Devices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda) | |
23 | Author: Calin Culianu <calin@ajvar.org> | |
24 | Updated: Mon, 14 Apr 2008 15:15:51 +0100 | |
25 | Status: works | |
26 | ||
27 | All features of the PCIM-DDA06-16 board are supported. This board | |
28 | has 6 16-bit AO channels, and the usual 8255 DIO setup. (24 channels, | |
29 | configurable in banks of 8 and 4, etc.). This board does not support commands. | |
30 | ||
31 | The board has a peculiar way of specifying AO gain/range settings -- You have | |
32 | 1 jumper bank on the card, which either makes all 6 AO channels either | |
33 | 5 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar. | |
34 | ||
35 | Since 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 | |
38 | default setting of +/-5V. | |
39 | ||
40 | Also of note is the fact that this board features another jumper, whose | |
41 | state is also completely invisible to software. It toggles two possible AO | |
42 | output 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 | 55 | Configuration 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 |
92 | static 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 |
122 | static 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 | 135 | static 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 |
170 | static 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 | 177 | static 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 | 184 | static 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 | }; | |
188 | MODULE_DEVICE_TABLE(pci, cb_pcimdda_pci_table); | |
189 | ||
190 | static 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 | }; |
196 | module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver); | |
197 | ||
198 | MODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>"); | |
199 | MODULE_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. :) ) "); | |
202 | MODULE_LICENSE("GPL"); |