Commit | Line | Data |
---|---|---|
086df5b5 | 1 | /* |
3bb18724 HS |
2 | * comedi/drivers/cb_pcidda.c |
3 | * Driver for the ComputerBoards / MeasurementComputing PCI-DDA series. | |
4 | * | |
5 | * Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com> | |
6 | * Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net> | |
7 | * | |
8 | * COMEDI - Linux Control and Measurement Device Interface | |
9 | * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
3bb18724 | 20 | */ |
086df5b5 | 21 | |
086df5b5 | 22 | /* |
3bb18724 HS |
23 | * Driver: cb_pcidda |
24 | * Description: MeasurementComputing PCI-DDA series | |
25 | * Devices: (Measurement Computing) PCI-DDA08/12 [pci-dda08/12] | |
26 | * (Measurement Computing) PCI-DDA04/12 [pci-dda04/12] | |
27 | * (Measurement Computing) PCI-DDA02/12 [pci-dda02/12] | |
28 | * (Measurement Computing) PCI-DDA08/16 [pci-dda08/16] | |
29 | * (Measurement Computing) PCI-DDA04/16 [pci-dda04/16] | |
30 | * (Measurement Computing) PCI-DDA02/16 [pci-dda02/16] | |
31 | * Author: Ivan Martinez <ivanmr@altavista.com> | |
32 | * Frank Mori Hess <fmhess@users.sourceforge.net> | |
33 | * Status: works | |
34 | * | |
35 | * Configuration options: not applicable, uses PCI auto config | |
36 | * | |
37 | * Only simple analog output writing is supported. | |
38 | */ | |
086df5b5 | 39 | |
ce157f80 | 40 | #include <linux/module.h> |
33782dd5 HS |
41 | #include <linux/pci.h> |
42 | ||
086df5b5 IM |
43 | #include "../comedidev.h" |
44 | ||
27020ffe | 45 | #include "comedi_fc.h" |
086df5b5 IM |
46 | #include "8255.h" |
47 | ||
2696fb57 | 48 | #define EEPROM_SIZE 128 /* number of entries in eeprom */ |
3c5510ba RKM |
49 | /* maximum number of ao channels for supported boards */ |
50 | #define MAX_AO_CHANNELS 8 | |
086df5b5 | 51 | |
086df5b5 | 52 | /* Digital I/O registers */ |
c8ffd143 HS |
53 | #define CB_DDA_DIO0_8255_BASE 0x00 |
54 | #define CB_DDA_DIO1_8255_BASE 0x04 | |
086df5b5 IM |
55 | |
56 | /* DAC registers */ | |
be2fcdbf HS |
57 | #define CB_DDA_DA_CTRL_REG 0x00 /* D/A Control Register */ |
58 | #define CB_DDA_DA_CTRL_SU (1 << 0) /* Simultaneous update */ | |
59 | #define CB_DDA_DA_CTRL_EN (1 << 1) /* Enable specified DAC */ | |
60 | #define CB_DDA_DA_CTRL_DAC(x) ((x) << 2) /* Specify DAC channel */ | |
61 | #define CB_DDA_DA_CTRL_RANGE2V5 (0 << 6) /* 2.5V range */ | |
62 | #define CB_DDA_DA_CTRL_RANGE5V (2 << 6) /* 5V range */ | |
63 | #define CB_DDA_DA_CTRL_RANGE10V (3 << 6) /* 10V range */ | |
64 | #define CB_DDA_DA_CTRL_UNIP (1 << 8) /* Unipolar range */ | |
2696fb57 BP |
65 | |
66 | #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */ | |
67 | /* write bits */ | |
3c5510ba RKM |
68 | /* serial data input for eeprom, caldacs, reference dac */ |
69 | #define SERIAL_IN_BIT 0x1 | |
086df5b5 IM |
70 | #define CAL_CHANNEL_MASK (0x7 << 1) |
71 | #define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK) | |
2696fb57 | 72 | /* read bits */ |
086df5b5 | 73 | #define CAL_COUNTER_MASK 0x1f |
3c5510ba RKM |
74 | /* calibration counter overflow status bit */ |
75 | #define CAL_COUNTER_OVERFLOW_BIT 0x20 | |
76 | /* analog output is less than reference dac voltage */ | |
77 | #define AO_BELOW_REF_BIT 0x40 | |
2696fb57 | 78 | #define SERIAL_OUT_BIT 0x80 /* serial data out, for reading from eeprom */ |
086df5b5 | 79 | |
2696fb57 BP |
80 | #define DACALIBRATION2 6 /* D/A CALIBRATION REGISTER 2 */ |
81 | #define SELECT_EEPROM_BIT 0x1 /* send serial data in to eeprom */ | |
3c5510ba RKM |
82 | /* don't send serial data to MAX542 reference dac */ |
83 | #define DESELECT_REF_DAC_BIT 0x2 | |
84 | /* don't send serial data to caldac n */ | |
85 | #define DESELECT_CALDAC_BIT(n) (0x4 << (n)) | |
86 | /* manual says to set this bit with no explanation */ | |
87 | #define DUMMY_BIT 0x40 | |
086df5b5 | 88 | |
87c4e2c6 | 89 | #define CB_DDA_DA_DATA_REG(x) (0x08 + ((x) * 2)) |
086df5b5 | 90 | |
809ec5bc HS |
91 | /* Offsets for the caldac channels */ |
92 | #define CB_DDA_CALDAC_FINE_GAIN 0 | |
93 | #define CB_DDA_CALDAC_COURSE_GAIN 1 | |
94 | #define CB_DDA_CALDAC_COURSE_OFFSET 2 | |
95 | #define CB_DDA_CALDAC_FINE_OFFSET 3 | |
96 | ||
9ced1de6 | 97 | static const struct comedi_lrange cb_pcidda_ranges = { |
f9c62f3f HS |
98 | 6, { |
99 | BIP_RANGE(10), | |
100 | BIP_RANGE(5), | |
101 | BIP_RANGE(2.5), | |
102 | UNI_RANGE(10), | |
103 | UNI_RANGE(5), | |
104 | UNI_RANGE(2.5) | |
105 | } | |
086df5b5 IM |
106 | }; |
107 | ||
e125f753 HS |
108 | enum cb_pcidda_boardid { |
109 | BOARD_DDA02_12, | |
110 | BOARD_DDA04_12, | |
111 | BOARD_DDA08_12, | |
112 | BOARD_DDA02_16, | |
113 | BOARD_DDA04_16, | |
114 | BOARD_DDA08_16, | |
115 | }; | |
116 | ||
1657e325 | 117 | struct cb_pcidda_board { |
086df5b5 | 118 | const char *name; |
086df5b5 IM |
119 | int ao_chans; |
120 | int ao_bits; | |
1657e325 | 121 | }; |
2696fb57 | 122 | |
1657e325 | 123 | static const struct cb_pcidda_board cb_pcidda_boards[] = { |
e125f753 | 124 | [BOARD_DDA02_12] = { |
0963fa1c | 125 | .name = "pci-dda02/12", |
0963fa1c HS |
126 | .ao_chans = 2, |
127 | .ao_bits = 12, | |
e125f753 HS |
128 | }, |
129 | [BOARD_DDA04_12] = { | |
0963fa1c | 130 | .name = "pci-dda04/12", |
0963fa1c HS |
131 | .ao_chans = 4, |
132 | .ao_bits = 12, | |
e125f753 HS |
133 | }, |
134 | [BOARD_DDA08_12] = { | |
0963fa1c | 135 | .name = "pci-dda08/12", |
0963fa1c HS |
136 | .ao_chans = 8, |
137 | .ao_bits = 12, | |
e125f753 HS |
138 | }, |
139 | [BOARD_DDA02_16] = { | |
0963fa1c | 140 | .name = "pci-dda02/16", |
0963fa1c HS |
141 | .ao_chans = 2, |
142 | .ao_bits = 16, | |
e125f753 HS |
143 | }, |
144 | [BOARD_DDA04_16] = { | |
0963fa1c | 145 | .name = "pci-dda04/16", |
0963fa1c HS |
146 | .ao_chans = 4, |
147 | .ao_bits = 16, | |
e125f753 HS |
148 | }, |
149 | [BOARD_DDA08_16] = { | |
0963fa1c | 150 | .name = "pci-dda08/16", |
0963fa1c HS |
151 | .ao_chans = 8, |
152 | .ao_bits = 16, | |
153 | }, | |
086df5b5 IM |
154 | }; |
155 | ||
cc7bb61e | 156 | struct cb_pcidda_private { |
f254029b | 157 | unsigned long daqio; |
3c5510ba RKM |
158 | /* bits last written to da calibration register 1 */ |
159 | unsigned int dac_cal1_bits; | |
160 | /* current range settings for output channels */ | |
161 | unsigned int ao_range[MAX_AO_CHANNELS]; | |
2696fb57 | 162 | u16 eeprom_data[EEPROM_SIZE]; /* software copy of board's eeprom */ |
cc7bb61e | 163 | }; |
086df5b5 | 164 | |
2696fb57 | 165 | /* lowlevel read from eeprom */ |
da91b269 | 166 | static unsigned int cb_pcidda_serial_in(struct comedi_device *dev) |
086df5b5 | 167 | { |
f254029b | 168 | struct cb_pcidda_private *devpriv = dev->private; |
086df5b5 IM |
169 | unsigned int value = 0; |
170 | int i; | |
2696fb57 | 171 | const int value_width = 16; /* number of bits wide values are */ |
086df5b5 IM |
172 | |
173 | for (i = 1; i <= value_width; i++) { | |
2696fb57 | 174 | /* read bits most significant bit first */ |
f254029b | 175 | if (inw_p(devpriv->daqio + DACALIBRATION1) & SERIAL_OUT_BIT) |
086df5b5 | 176 | value |= 1 << (value_width - i); |
086df5b5 IM |
177 | } |
178 | ||
179 | return value; | |
180 | } | |
181 | ||
2696fb57 | 182 | /* lowlevel write to eeprom/dac */ |
da91b269 | 183 | static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value, |
0a85b6f0 | 184 | unsigned int num_bits) |
086df5b5 | 185 | { |
c6ad306b | 186 | struct cb_pcidda_private *devpriv = dev->private; |
086df5b5 IM |
187 | int i; |
188 | ||
189 | for (i = 1; i <= num_bits; i++) { | |
2696fb57 | 190 | /* send bits most significant bit first */ |
086df5b5 IM |
191 | if (value & (1 << (num_bits - i))) |
192 | devpriv->dac_cal1_bits |= SERIAL_IN_BIT; | |
193 | else | |
194 | devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT; | |
f254029b | 195 | outw_p(devpriv->dac_cal1_bits, devpriv->daqio + DACALIBRATION1); |
086df5b5 IM |
196 | } |
197 | } | |
198 | ||
2696fb57 | 199 | /* reads a 16 bit value from board's eeprom */ |
da91b269 | 200 | static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev, |
0a85b6f0 | 201 | unsigned int address) |
086df5b5 | 202 | { |
f254029b | 203 | struct cb_pcidda_private *devpriv = dev->private; |
086df5b5 IM |
204 | unsigned int i; |
205 | unsigned int cal2_bits; | |
206 | unsigned int value; | |
3c5510ba RKM |
207 | /* one caldac for every two dac channels */ |
208 | const int max_num_caldacs = 4; | |
209 | /* bits to send to tell eeprom we want to read */ | |
210 | const int read_instruction = 0x6; | |
086df5b5 IM |
211 | const int instruction_length = 3; |
212 | const int address_length = 8; | |
213 | ||
2696fb57 | 214 | /* send serial output stream to eeprom */ |
086df5b5 | 215 | cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT; |
2696fb57 | 216 | /* deactivate caldacs (one caldac for every two channels) */ |
20db7d7d | 217 | for (i = 0; i < max_num_caldacs; i++) |
086df5b5 | 218 | cal2_bits |= DESELECT_CALDAC_BIT(i); |
f254029b | 219 | outw_p(cal2_bits, devpriv->daqio + DACALIBRATION2); |
086df5b5 | 220 | |
2696fb57 | 221 | /* tell eeprom we want to read */ |
086df5b5 | 222 | cb_pcidda_serial_out(dev, read_instruction, instruction_length); |
2696fb57 | 223 | /* send address we want to read from */ |
086df5b5 IM |
224 | cb_pcidda_serial_out(dev, address, address_length); |
225 | ||
226 | value = cb_pcidda_serial_in(dev); | |
227 | ||
2696fb57 | 228 | /* deactivate eeprom */ |
086df5b5 | 229 | cal2_bits &= ~SELECT_EEPROM_BIT; |
f254029b | 230 | outw_p(cal2_bits, devpriv->daqio + DACALIBRATION2); |
086df5b5 IM |
231 | |
232 | return value; | |
233 | } | |
234 | ||
2696fb57 | 235 | /* writes to 8 bit calibration dacs */ |
0a85b6f0 MT |
236 | static void cb_pcidda_write_caldac(struct comedi_device *dev, |
237 | unsigned int caldac, unsigned int channel, | |
238 | unsigned int value) | |
086df5b5 | 239 | { |
f254029b | 240 | struct cb_pcidda_private *devpriv = dev->private; |
086df5b5 IM |
241 | unsigned int cal2_bits; |
242 | unsigned int i; | |
3c5510ba RKM |
243 | /* caldacs use 3 bit channel specification */ |
244 | const int num_channel_bits = 3; | |
2696fb57 | 245 | const int num_caldac_bits = 8; /* 8 bit calibration dacs */ |
3c5510ba RKM |
246 | /* one caldac for every two dac channels */ |
247 | const int max_num_caldacs = 4; | |
086df5b5 IM |
248 | |
249 | /* write 3 bit channel */ | |
250 | cb_pcidda_serial_out(dev, channel, num_channel_bits); | |
2696fb57 | 251 | /* write 8 bit caldac value */ |
086df5b5 IM |
252 | cb_pcidda_serial_out(dev, value, num_caldac_bits); |
253 | ||
2696fb57 BP |
254 | /* |
255 | * latch stream into appropriate caldac deselect reference dac | |
256 | */ | |
086df5b5 | 257 | cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT; |
2696fb57 | 258 | /* deactivate caldacs (one caldac for every two channels) */ |
20db7d7d | 259 | for (i = 0; i < max_num_caldacs; i++) |
086df5b5 | 260 | cal2_bits |= DESELECT_CALDAC_BIT(i); |
2696fb57 | 261 | /* activate the caldac we want */ |
086df5b5 | 262 | cal2_bits &= ~DESELECT_CALDAC_BIT(caldac); |
f254029b | 263 | outw_p(cal2_bits, devpriv->daqio + DACALIBRATION2); |
2696fb57 | 264 | /* deactivate caldac */ |
086df5b5 | 265 | cal2_bits |= DESELECT_CALDAC_BIT(caldac); |
f254029b | 266 | outw_p(cal2_bits, devpriv->daqio + DACALIBRATION2); |
086df5b5 IM |
267 | } |
268 | ||
2696fb57 | 269 | /* set caldacs to eeprom values for given channel and range */ |
da91b269 | 270 | static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel, |
0a85b6f0 | 271 | unsigned int range) |
086df5b5 | 272 | { |
c6ad306b | 273 | struct cb_pcidda_private *devpriv = dev->private; |
809ec5bc HS |
274 | unsigned int caldac = channel / 2; /* two caldacs per channel */ |
275 | unsigned int chan = 4 * (channel % 2); /* caldac channel base */ | |
276 | unsigned int index = 2 * range + 12 * channel; | |
277 | unsigned int offset; | |
278 | unsigned int gain; | |
086df5b5 | 279 | |
809ec5bc | 280 | /* save range so we can tell when we need to readjust calibration */ |
086df5b5 IM |
281 | devpriv->ao_range[channel] = range; |
282 | ||
809ec5bc HS |
283 | /* get values from eeprom data */ |
284 | offset = devpriv->eeprom_data[0x7 + index]; | |
285 | gain = devpriv->eeprom_data[0x8 + index]; | |
286 | ||
287 | /* set caldacs */ | |
288 | cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_COURSE_OFFSET, | |
289 | (offset >> 8) & 0xff); | |
290 | cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_FINE_OFFSET, | |
291 | offset & 0xff); | |
292 | cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_COURSE_GAIN, | |
293 | (gain >> 8) & 0xff); | |
294 | cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_FINE_GAIN, | |
295 | gain & 0xff); | |
086df5b5 IM |
296 | } |
297 | ||
2e54209e HS |
298 | static int cb_pcidda_ao_insn_write(struct comedi_device *dev, |
299 | struct comedi_subdevice *s, | |
300 | struct comedi_insn *insn, | |
301 | unsigned int *data) | |
6d336a56 HS |
302 | { |
303 | struct cb_pcidda_private *devpriv = dev->private; | |
be2fcdbf HS |
304 | unsigned int channel = CR_CHAN(insn->chanspec); |
305 | unsigned int range = CR_RANGE(insn->chanspec); | |
306 | unsigned int ctrl; | |
6d336a56 | 307 | |
6d336a56 HS |
308 | if (range != devpriv->ao_range[channel]) |
309 | cb_pcidda_calibrate(dev, channel, range); | |
310 | ||
be2fcdbf | 311 | ctrl = CB_DDA_DA_CTRL_EN | CB_DDA_DA_CTRL_DAC(channel); |
6d336a56 | 312 | |
6d336a56 HS |
313 | switch (range) { |
314 | case 0: | |
6d336a56 | 315 | case 3: |
be2fcdbf | 316 | ctrl |= CB_DDA_DA_CTRL_RANGE10V; |
6d336a56 | 317 | break; |
be2fcdbf | 318 | case 1: |
6d336a56 | 319 | case 4: |
be2fcdbf | 320 | ctrl |= CB_DDA_DA_CTRL_RANGE5V; |
6d336a56 | 321 | break; |
be2fcdbf | 322 | case 2: |
6d336a56 | 323 | case 5: |
be2fcdbf | 324 | ctrl |= CB_DDA_DA_CTRL_RANGE2V5; |
6d336a56 HS |
325 | break; |
326 | } | |
327 | ||
be2fcdbf HS |
328 | if (range > 2) |
329 | ctrl |= CB_DDA_DA_CTRL_UNIP; | |
330 | ||
f254029b | 331 | outw(ctrl, devpriv->daqio + CB_DDA_DA_CTRL_REG); |
6d336a56 | 332 | |
f254029b | 333 | outw(data[0], devpriv->daqio + CB_DDA_DA_DATA_REG(channel)); |
6d336a56 | 334 | |
2e54209e | 335 | return insn->n; |
6d336a56 HS |
336 | } |
337 | ||
a690b7e5 | 338 | static int cb_pcidda_auto_attach(struct comedi_device *dev, |
e125f753 | 339 | unsigned long context) |
6d336a56 | 340 | { |
750af5e5 | 341 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
e125f753 | 342 | const struct cb_pcidda_board *thisboard = NULL; |
6d336a56 | 343 | struct cb_pcidda_private *devpriv; |
6d336a56 | 344 | struct comedi_subdevice *s; |
2730c736 | 345 | int i; |
6d336a56 HS |
346 | int ret; |
347 | ||
e125f753 HS |
348 | if (context < ARRAY_SIZE(cb_pcidda_boards)) |
349 | thisboard = &cb_pcidda_boards[context]; | |
ff331f7d | 350 | if (!thisboard) |
2c0db011 HS |
351 | return -ENODEV; |
352 | dev->board_ptr = thisboard; | |
353 | dev->board_name = thisboard->name; | |
354 | ||
0bdab509 | 355 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
c34fa261 HS |
356 | if (!devpriv) |
357 | return -ENOMEM; | |
6d336a56 | 358 | |
818f569f | 359 | ret = comedi_pci_enable(dev); |
2c0db011 HS |
360 | if (ret) |
361 | return ret; | |
f254029b HS |
362 | dev->iobase = pci_resource_start(pcidev, 2); |
363 | devpriv->daqio = pci_resource_start(pcidev, 3); | |
6d336a56 | 364 | |
6d336a56 HS |
365 | ret = comedi_alloc_subdevices(dev, 3); |
366 | if (ret) | |
367 | return ret; | |
368 | ||
82ec595a | 369 | s = &dev->subdevices[0]; |
6d336a56 HS |
370 | /* analog output subdevice */ |
371 | s->type = COMEDI_SUBD_AO; | |
372 | s->subdev_flags = SDF_WRITABLE; | |
373 | s->n_chan = thisboard->ao_chans; | |
374 | s->maxdata = (1 << thisboard->ao_bits) - 1; | |
f9c62f3f | 375 | s->range_table = &cb_pcidda_ranges; |
2e54209e | 376 | s->insn_write = cb_pcidda_ao_insn_write; |
6d336a56 | 377 | |
618351ae HS |
378 | /* two 8255 digital io subdevices */ |
379 | for (i = 0; i < 2; i++) { | |
380 | s = &dev->subdevices[1 + i]; | |
f0162091 | 381 | ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE); |
618351ae HS |
382 | if (ret) |
383 | return ret; | |
384 | } | |
6d336a56 | 385 | |
66483378 | 386 | /* Read the caldac eeprom data */ |
2730c736 HS |
387 | for (i = 0; i < EEPROM_SIZE; i++) |
388 | devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i); | |
6d336a56 HS |
389 | |
390 | /* set calibrations dacs */ | |
2730c736 HS |
391 | for (i = 0; i < thisboard->ao_chans; i++) |
392 | cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]); | |
6d336a56 | 393 | |
2c0db011 | 394 | return 0; |
6d336a56 HS |
395 | } |
396 | ||
954ca6c9 HS |
397 | static struct comedi_driver cb_pcidda_driver = { |
398 | .driver_name = "cb_pcidda", | |
399 | .module = THIS_MODULE, | |
750af5e5 | 400 | .auto_attach = cb_pcidda_auto_attach, |
588ba6dc | 401 | .detach = comedi_pci_disable, |
954ca6c9 HS |
402 | }; |
403 | ||
a690b7e5 | 404 | static int cb_pcidda_pci_probe(struct pci_dev *dev, |
b8f4ac23 | 405 | const struct pci_device_id *id) |
727b286b | 406 | { |
b8f4ac23 HS |
407 | return comedi_pci_auto_config(dev, &cb_pcidda_driver, |
408 | id->driver_data); | |
727b286b AT |
409 | } |
410 | ||
41e043fc | 411 | static const struct pci_device_id cb_pcidda_pci_table[] = { |
e125f753 HS |
412 | { PCI_VDEVICE(CB, 0x0020), BOARD_DDA02_12 }, |
413 | { PCI_VDEVICE(CB, 0x0021), BOARD_DDA04_12 }, | |
414 | { PCI_VDEVICE(CB, 0x0022), BOARD_DDA08_12 }, | |
415 | { PCI_VDEVICE(CB, 0x0023), BOARD_DDA02_16 }, | |
416 | { PCI_VDEVICE(CB, 0x0024), BOARD_DDA04_16 }, | |
417 | { PCI_VDEVICE(CB, 0x0025), BOARD_DDA08_16 }, | |
954ca6c9 | 418 | { 0 } |
727b286b | 419 | }; |
954ca6c9 | 420 | MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table); |
727b286b | 421 | |
954ca6c9 HS |
422 | static struct pci_driver cb_pcidda_pci_driver = { |
423 | .name = "cb_pcidda", | |
424 | .id_table = cb_pcidda_pci_table, | |
425 | .probe = cb_pcidda_pci_probe, | |
9901a4d7 | 426 | .remove = comedi_pci_auto_unconfig, |
954ca6c9 HS |
427 | }; |
428 | module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver); | |
90f703d3 AT |
429 | |
430 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | |
431 | MODULE_DESCRIPTION("Comedi low-level driver"); | |
432 | MODULE_LICENSE("GPL"); |