2 comedi/drivers/cb_pcidda.c
3 This intends to be a driver for the ComputerBoards / MeasurementComputing
6 Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
7 Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
9 COMEDI - Linux Control and Measurement Device Interface
10 Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 Description: MeasurementComputing PCI-DDA series
30 Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
31 Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
32 Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
33 PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
35 Configuration options:
36 [0] - PCI bus of device (optional)
37 [1] - PCI slot of device (optional)
38 If bus/slot is not specified, the first available PCI
41 Only simple analog output writing is supported.
43 So far it has only been tested with:
45 Please report success/failure with other different cards to
49 #include "../comedidev.h"
51 #include "comedi_fc.h"
54 /* PCI vendor number of ComputerBoards */
55 #define PCI_VENDOR_ID_CB 0x1307
56 #define EEPROM_SIZE 128 /* number of entries in eeprom */
57 /* maximum number of ao channels for supported boards */
58 #define MAX_AO_CHANNELS 8
60 /* Digital I/O registers */
61 #define PORT1A 0 /* PORT 1A DATA */
63 #define PORT1B 1 /* PORT 1B DATA */
65 #define PORT1C 2 /* PORT 1C DATA */
67 #define CONTROL1 3 /* CONTROL REGISTER 1 */
69 #define PORT2A 4 /* PORT 2A DATA */
71 #define PORT2B 5 /* PORT 2B DATA */
73 #define PORT2C 6 /* PORT 2C DATA */
75 #define CONTROL2 7 /* CONTROL REGISTER 2 */
78 #define DACONTROL 0 /* D/A CONTROL REGISTER */
79 #define SU 0000001 /* Simultaneous update enabled */
80 #define NOSU 0000000 /* Simultaneous update disabled */
81 #define ENABLEDAC 0000002 /* Enable specified DAC */
82 #define DISABLEDAC 0000000 /* Disable specified DAC */
83 #define RANGE2V5 0000000 /* 2.5V */
84 #define RANGE5V 0000200 /* 5V */
85 #define RANGE10V 0000300 /* 10V */
86 #define UNIP 0000400 /* Unipolar outputs */
87 #define BIP 0000000 /* Bipolar outputs */
89 #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */
91 /* serial data input for eeprom, caldacs, reference dac */
92 #define SERIAL_IN_BIT 0x1
93 #define CAL_CHANNEL_MASK (0x7 << 1)
94 #define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK)
96 #define CAL_COUNTER_MASK 0x1f
97 /* calibration counter overflow status bit */
98 #define CAL_COUNTER_OVERFLOW_BIT 0x20
99 /* analog output is less than reference dac voltage */
100 #define AO_BELOW_REF_BIT 0x40
101 #define SERIAL_OUT_BIT 0x80 /* serial data out, for reading from eeprom */
103 #define DACALIBRATION2 6 /* D/A CALIBRATION REGISTER 2 */
104 #define SELECT_EEPROM_BIT 0x1 /* send serial data in to eeprom */
105 /* don't send serial data to MAX542 reference dac */
106 #define DESELECT_REF_DAC_BIT 0x2
107 /* don't send serial data to caldac n */
108 #define DESELECT_CALDAC_BIT(n) (0x4 << (n))
109 /* manual says to set this bit with no explanation */
110 #define DUMMY_BIT 0x40
112 #define DADATA 8 /* FIRST D/A DATA REGISTER (0) */
114 static const struct comedi_lrange cb_pcidda_ranges
= {
127 * Board descriptions for two imaginary boards. Describing the
128 * boards in this way is optional, and completely driver-dependent.
129 * Some drivers use arrays such as this, other do not.
131 struct cb_pcidda_board
{
133 char status
; /* Driver status: */
137 * 1 - manual read, not tested
138 * 2 - manual not read
141 unsigned short device_id
;
144 const struct comedi_lrange
*ranges
;
147 static const struct cb_pcidda_board cb_pcidda_boards
[] = {
149 .name
= "pci-dda02/12",
154 .ranges
= &cb_pcidda_ranges
,
157 .name
= "pci-dda04/12",
162 .ranges
= &cb_pcidda_ranges
,
165 .name
= "pci-dda08/12",
170 .ranges
= &cb_pcidda_ranges
,
173 .name
= "pci-dda02/16",
178 .ranges
= &cb_pcidda_ranges
,
181 .name
= "pci-dda04/16",
186 .ranges
= &cb_pcidda_ranges
,
189 .name
= "pci-dda08/16",
194 .ranges
= &cb_pcidda_ranges
,
199 * this structure is for data unique to this hardware driver. If
200 * several hardware drivers keep similar information in this structure,
201 * feel free to suggest moving the variable to the struct comedi_device
204 struct cb_pcidda_private
{
207 unsigned long digitalio
;
210 /* unsigned long control_status; */
211 /* unsigned long adc_fifo; */
213 /* bits last written to da calibration register 1 */
214 unsigned int dac_cal1_bits
;
215 /* current range settings for output channels */
216 unsigned int ao_range
[MAX_AO_CHANNELS
];
217 u16 eeprom_data
[EEPROM_SIZE
]; /* software copy of board's eeprom */
221 * I will program this later... ;-)
224 static int cb_pcidda_ai_cmd(struct comedi_device
*dev
,
225 struct comedi_subdevice
*s
)
227 printk("cb_pcidda_ai_cmd\n");
228 printk("subdev: %d\n", cmd
->subdev
);
229 printk("flags: %d\n", cmd
->flags
);
230 printk("start_src: %d\n", cmd
->start_src
);
231 printk("start_arg: %d\n", cmd
->start_arg
);
232 printk("scan_begin_src: %d\n", cmd
->scan_begin_src
);
233 printk("convert_src: %d\n", cmd
->convert_src
);
234 printk("convert_arg: %d\n", cmd
->convert_arg
);
235 printk("scan_end_src: %d\n", cmd
->scan_end_src
);
236 printk("scan_end_arg: %d\n", cmd
->scan_end_arg
);
237 printk("stop_src: %d\n", cmd
->stop_src
);
238 printk("stop_arg: %d\n", cmd
->stop_arg
);
239 printk("chanlist_len: %d\n", cmd
->chanlist_len
);
244 static int cb_pcidda_ai_cmdtest(struct comedi_device
*dev
,
245 struct comedi_subdevice
*s
,
246 struct comedi_cmd
*cmd
)
251 /* Step 1 : check if triggers are trivially valid */
253 err
|= cfc_check_trigger_src(&cmd
->start_src
, TRIG_NOW
);
254 err
|= cfc_check_trigger_src(&cmd
->scan_begin_src
,
255 TRIG_TIMER
| TRIG_EXT
);
256 err
|= cfc_check_trigger_src(&cmd
->convert_src
,
257 TRIG_TIMER
| TRIG_EXT
);
258 err
|= cfc_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
259 err
|= cfc_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
264 /* Step 2a : make sure trigger sources are unique */
266 err
|= cfc_check_trigger_is_unique(cmd
->scan_begin_src
);
267 err
|= cfc_check_trigger_is_unique(cmd
->convert_src
);
268 err
|= cfc_check_trigger_is_unique(cmd
->stop_src
);
270 /* Step 2b : and mutually compatible */
275 /* step 3: make sure arguments are trivially compatible */
277 if (cmd
->start_arg
!= 0) {
281 #define MAX_SPEED 10000 /* in nanoseconds */
282 #define MIN_SPEED 1000000000 /* in nanoseconds */
284 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
285 if (cmd
->scan_begin_arg
< MAX_SPEED
) {
286 cmd
->scan_begin_arg
= MAX_SPEED
;
289 if (cmd
->scan_begin_arg
> MIN_SPEED
) {
290 cmd
->scan_begin_arg
= MIN_SPEED
;
294 /* external trigger */
295 /* should be level/edge, hi/lo specification here */
296 /* should specify multiple external triggers */
297 if (cmd
->scan_begin_arg
> 9) {
298 cmd
->scan_begin_arg
= 9;
302 if (cmd
->convert_src
== TRIG_TIMER
) {
303 if (cmd
->convert_arg
< MAX_SPEED
) {
304 cmd
->convert_arg
= MAX_SPEED
;
307 if (cmd
->convert_arg
> MIN_SPEED
) {
308 cmd
->convert_arg
= MIN_SPEED
;
312 /* external trigger */
314 if (cmd
->convert_arg
> 9) {
315 cmd
->convert_arg
= 9;
320 if (cmd
->scan_end_arg
!= cmd
->chanlist_len
) {
321 cmd
->scan_end_arg
= cmd
->chanlist_len
;
324 if (cmd
->stop_src
== TRIG_COUNT
) {
325 if (cmd
->stop_arg
> 0x00ffffff) {
326 cmd
->stop_arg
= 0x00ffffff;
331 if (cmd
->stop_arg
!= 0) {
340 /* step 4: fix up any arguments */
342 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
343 tmp
= cmd
->scan_begin_arg
;
344 cb_pcidda_ns_to_timer(&cmd
->scan_begin_arg
,
345 cmd
->flags
& TRIG_ROUND_MASK
);
346 if (tmp
!= cmd
->scan_begin_arg
)
349 if (cmd
->convert_src
== TRIG_TIMER
) {
350 tmp
= cmd
->convert_arg
;
351 cb_pcidda_ns_to_timer(&cmd
->convert_arg
,
352 cmd
->flags
& TRIG_ROUND_MASK
);
353 if (tmp
!= cmd
->convert_arg
)
355 if (cmd
->scan_begin_src
== TRIG_TIMER
&&
356 cmd
->scan_begin_arg
<
357 cmd
->convert_arg
* cmd
->scan_end_arg
) {
358 cmd
->scan_begin_arg
=
359 cmd
->convert_arg
* cmd
->scan_end_arg
;
371 /* This function doesn't require a particular form, this is just
372 * what happens to be used in some of the drivers. It should
373 * convert ns nanoseconds to a counter value suitable for programming
374 * the device. Also, it should adjust ns so that it cooresponds to
375 * the actual time that the device will use. */
377 static int cb_pcidda_ns_to_timer(unsigned int *ns
, int round
)
384 /* lowlevel read from eeprom */
385 static unsigned int cb_pcidda_serial_in(struct comedi_device
*dev
)
387 struct cb_pcidda_private
*devpriv
= dev
->private;
388 unsigned int value
= 0;
390 const int value_width
= 16; /* number of bits wide values are */
392 for (i
= 1; i
<= value_width
; i
++) {
393 /* read bits most significant bit first */
394 if (inw_p(devpriv
->dac
+ DACALIBRATION1
) & SERIAL_OUT_BIT
)
395 value
|= 1 << (value_width
- i
);
401 /* lowlevel write to eeprom/dac */
402 static void cb_pcidda_serial_out(struct comedi_device
*dev
, unsigned int value
,
403 unsigned int num_bits
)
405 struct cb_pcidda_private
*devpriv
= dev
->private;
408 for (i
= 1; i
<= num_bits
; i
++) {
409 /* send bits most significant bit first */
410 if (value
& (1 << (num_bits
- i
)))
411 devpriv
->dac_cal1_bits
|= SERIAL_IN_BIT
;
413 devpriv
->dac_cal1_bits
&= ~SERIAL_IN_BIT
;
414 outw_p(devpriv
->dac_cal1_bits
, devpriv
->dac
+ DACALIBRATION1
);
418 /* reads a 16 bit value from board's eeprom */
419 static unsigned int cb_pcidda_read_eeprom(struct comedi_device
*dev
,
420 unsigned int address
)
422 struct cb_pcidda_private
*devpriv
= dev
->private;
424 unsigned int cal2_bits
;
426 /* one caldac for every two dac channels */
427 const int max_num_caldacs
= 4;
428 /* bits to send to tell eeprom we want to read */
429 const int read_instruction
= 0x6;
430 const int instruction_length
= 3;
431 const int address_length
= 8;
433 /* send serial output stream to eeprom */
434 cal2_bits
= SELECT_EEPROM_BIT
| DESELECT_REF_DAC_BIT
| DUMMY_BIT
;
435 /* deactivate caldacs (one caldac for every two channels) */
436 for (i
= 0; i
< max_num_caldacs
; i
++)
437 cal2_bits
|= DESELECT_CALDAC_BIT(i
);
438 outw_p(cal2_bits
, devpriv
->dac
+ DACALIBRATION2
);
440 /* tell eeprom we want to read */
441 cb_pcidda_serial_out(dev
, read_instruction
, instruction_length
);
442 /* send address we want to read from */
443 cb_pcidda_serial_out(dev
, address
, address_length
);
445 value
= cb_pcidda_serial_in(dev
);
447 /* deactivate eeprom */
448 cal2_bits
&= ~SELECT_EEPROM_BIT
;
449 outw_p(cal2_bits
, devpriv
->dac
+ DACALIBRATION2
);
454 /* writes to 8 bit calibration dacs */
455 static void cb_pcidda_write_caldac(struct comedi_device
*dev
,
456 unsigned int caldac
, unsigned int channel
,
459 struct cb_pcidda_private
*devpriv
= dev
->private;
460 unsigned int cal2_bits
;
462 /* caldacs use 3 bit channel specification */
463 const int num_channel_bits
= 3;
464 const int num_caldac_bits
= 8; /* 8 bit calibration dacs */
465 /* one caldac for every two dac channels */
466 const int max_num_caldacs
= 4;
468 /* write 3 bit channel */
469 cb_pcidda_serial_out(dev
, channel
, num_channel_bits
);
470 /* write 8 bit caldac value */
471 cb_pcidda_serial_out(dev
, value
, num_caldac_bits
);
474 * latch stream into appropriate caldac deselect reference dac
476 cal2_bits
= DESELECT_REF_DAC_BIT
| DUMMY_BIT
;
477 /* deactivate caldacs (one caldac for every two channels) */
478 for (i
= 0; i
< max_num_caldacs
; i
++)
479 cal2_bits
|= DESELECT_CALDAC_BIT(i
);
480 /* activate the caldac we want */
481 cal2_bits
&= ~DESELECT_CALDAC_BIT(caldac
);
482 outw_p(cal2_bits
, devpriv
->dac
+ DACALIBRATION2
);
483 /* deactivate caldac */
484 cal2_bits
|= DESELECT_CALDAC_BIT(caldac
);
485 outw_p(cal2_bits
, devpriv
->dac
+ DACALIBRATION2
);
488 /* returns caldac that calibrates given analog out channel */
489 static unsigned int caldac_number(unsigned int channel
)
494 /* returns caldac channel that provides fine gain for given ao channel */
495 static unsigned int fine_gain_channel(unsigned int ao_channel
)
497 return 4 * (ao_channel
% 2);
500 /* returns caldac channel that provides coarse gain for given ao channel */
501 static unsigned int coarse_gain_channel(unsigned int ao_channel
)
503 return 1 + 4 * (ao_channel
% 2);
506 /* returns caldac channel that provides coarse offset for given ao channel */
507 static unsigned int coarse_offset_channel(unsigned int ao_channel
)
509 return 2 + 4 * (ao_channel
% 2);
512 /* returns caldac channel that provides fine offset for given ao channel */
513 static unsigned int fine_offset_channel(unsigned int ao_channel
)
515 return 3 + 4 * (ao_channel
% 2);
518 /* returns eeprom address that provides offset for given ao channel and range */
519 static unsigned int offset_eeprom_address(unsigned int ao_channel
,
522 return 0x7 + 2 * range
+ 12 * ao_channel
;
526 * returns eeprom address that provides gain calibration for given ao
529 static unsigned int gain_eeprom_address(unsigned int ao_channel
,
532 return 0x8 + 2 * range
+ 12 * ao_channel
;
536 * returns upper byte of eeprom entry, which gives the coarse adjustment
539 static unsigned int eeprom_coarse_byte(unsigned int word
)
541 return (word
>> 8) & 0xff;
544 /* returns lower byte of eeprom entry, which gives the fine adjustment values */
545 static unsigned int eeprom_fine_byte(unsigned int word
)
550 /* set caldacs to eeprom values for given channel and range */
551 static void cb_pcidda_calibrate(struct comedi_device
*dev
, unsigned int channel
,
554 struct cb_pcidda_private
*devpriv
= dev
->private;
555 unsigned int coarse_offset
, fine_offset
, coarse_gain
, fine_gain
;
557 /* remember range so we can tell when we need to readjust calibration */
558 devpriv
->ao_range
[channel
] = range
;
560 /* get values from eeprom data */
562 eeprom_coarse_byte(devpriv
->eeprom_data
563 [offset_eeprom_address(channel
, range
)]);
565 eeprom_fine_byte(devpriv
->eeprom_data
566 [offset_eeprom_address(channel
, range
)]);
568 eeprom_coarse_byte(devpriv
->eeprom_data
569 [gain_eeprom_address(channel
, range
)]);
571 eeprom_fine_byte(devpriv
->eeprom_data
572 [gain_eeprom_address(channel
, range
)]);
575 cb_pcidda_write_caldac(dev
, caldac_number(channel
),
576 coarse_offset_channel(channel
), coarse_offset
);
577 cb_pcidda_write_caldac(dev
, caldac_number(channel
),
578 fine_offset_channel(channel
), fine_offset
);
579 cb_pcidda_write_caldac(dev
, caldac_number(channel
),
580 coarse_gain_channel(channel
), coarse_gain
);
581 cb_pcidda_write_caldac(dev
, caldac_number(channel
),
582 fine_gain_channel(channel
), fine_gain
);
585 static int cb_pcidda_ao_winsn(struct comedi_device
*dev
,
586 struct comedi_subdevice
*s
,
587 struct comedi_insn
*insn
, unsigned int *data
)
589 struct cb_pcidda_private
*devpriv
= dev
->private;
590 unsigned int command
;
591 unsigned int channel
, range
;
593 channel
= CR_CHAN(insn
->chanspec
);
594 range
= CR_RANGE(insn
->chanspec
);
596 /* adjust calibration dacs if range has changed */
597 if (range
!= devpriv
->ao_range
[channel
])
598 cb_pcidda_calibrate(dev
, channel
, range
);
600 /* output channel configuration */
601 command
= NOSU
| ENABLEDAC
;
603 /* output channel range */
606 command
|= BIP
| RANGE10V
;
609 command
|= BIP
| RANGE5V
;
612 command
|= BIP
| RANGE2V5
;
615 command
|= UNIP
| RANGE10V
;
618 command
|= UNIP
| RANGE5V
;
621 command
|= UNIP
| RANGE2V5
;
625 /* output channel specification */
626 command
|= channel
<< 2;
627 outw(command
, devpriv
->dac
+ DACONTROL
);
630 outw(data
[0], devpriv
->dac
+ DADATA
+ channel
* 2);
632 /* return the number of samples read/written */
636 static const void *cb_pcidda_find_boardinfo(struct comedi_device
*dev
,
637 struct pci_dev
*pcidev
)
639 const struct cb_pcidda_board
*thisboard
;
642 for (i
= 0; i
< ARRAY_SIZE(cb_pcidda_boards
); i
++) {
643 thisboard
= &cb_pcidda_boards
[i
];
644 if (thisboard
->device_id
!= pcidev
->device
)
650 static int cb_pcidda_attach_pci(struct comedi_device
*dev
,
651 struct pci_dev
*pcidev
)
653 const struct cb_pcidda_board
*thisboard
;
654 struct cb_pcidda_private
*devpriv
;
655 struct comedi_subdevice
*s
;
659 comedi_set_hw_dev(dev
, &pcidev
->dev
);
661 thisboard
= cb_pcidda_find_boardinfo(dev
, pcidev
);
664 dev
->board_ptr
= thisboard
;
665 dev
->board_name
= thisboard
->name
;
667 ret
= alloc_private(dev
, sizeof(*devpriv
));
670 devpriv
= dev
->private;
672 ret
= comedi_pci_enable(pcidev
, dev
->board_name
);
676 devpriv
->digitalio
= pci_resource_start(pcidev
, 2);
677 devpriv
->dac
= pci_resource_start(pcidev
, 3);
678 dev
->iobase
= devpriv
->dac
;
680 if (thisboard
->status
== 2)
682 ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
683 "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
684 "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
686 ret
= comedi_alloc_subdevices(dev
, 3);
690 s
= &dev
->subdevices
[0];
691 /* analog output subdevice */
692 s
->type
= COMEDI_SUBD_AO
;
693 s
->subdev_flags
= SDF_WRITABLE
;
694 s
->n_chan
= thisboard
->ao_chans
;
695 s
->maxdata
= (1 << thisboard
->ao_bits
) - 1;
696 s
->range_table
= thisboard
->ranges
;
697 s
->insn_write
= cb_pcidda_ao_winsn
;
699 /* s->subdev_flags |= SDF_CMD_READ; */
700 /* s->do_cmd = cb_pcidda_ai_cmd; */
701 /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
703 /* two 8255 digital io subdevices */
704 s
= &dev
->subdevices
[1];
705 subdev_8255_init(dev
, s
, NULL
, devpriv
->digitalio
);
706 s
= &dev
->subdevices
[2];
707 subdev_8255_init(dev
, s
, NULL
, devpriv
->digitalio
+ PORT2A
);
709 dev_dbg(dev
->class_dev
, "eeprom:\n");
710 for (index
= 0; index
< EEPROM_SIZE
; index
++) {
711 devpriv
->eeprom_data
[index
] = cb_pcidda_read_eeprom(dev
, index
);
712 dev_dbg(dev
->class_dev
, "%i:0x%x\n", index
,
713 devpriv
->eeprom_data
[index
]);
716 /* set calibrations dacs */
717 for (index
= 0; index
< thisboard
->ao_chans
; index
++)
718 cb_pcidda_calibrate(dev
, index
, devpriv
->ao_range
[index
]);
720 dev_info(dev
->class_dev
, "%s attached\n", dev
->board_name
);
725 static void cb_pcidda_detach(struct comedi_device
*dev
)
727 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
729 if (dev
->subdevices
) {
730 subdev_8255_cleanup(dev
, &dev
->subdevices
[1]);
731 subdev_8255_cleanup(dev
, &dev
->subdevices
[2]);
735 comedi_pci_disable(pcidev
);
739 static struct comedi_driver cb_pcidda_driver
= {
740 .driver_name
= "cb_pcidda",
741 .module
= THIS_MODULE
,
742 .attach_pci
= cb_pcidda_attach_pci
,
743 .detach
= cb_pcidda_detach
,
746 static int __devinit
cb_pcidda_pci_probe(struct pci_dev
*dev
,
747 const struct pci_device_id
*ent
)
749 return comedi_pci_auto_config(dev
, &cb_pcidda_driver
);
752 static void __devexit
cb_pcidda_pci_remove(struct pci_dev
*dev
)
754 comedi_pci_auto_unconfig(dev
);
757 static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table
) = {
758 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0020) },
759 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0021) },
760 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0022) },
761 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0023) },
762 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0024) },
763 { PCI_DEVICE(PCI_VENDOR_ID_CB
, 0x0025) },
766 MODULE_DEVICE_TABLE(pci
, cb_pcidda_pci_table
);
768 static struct pci_driver cb_pcidda_pci_driver
= {
770 .id_table
= cb_pcidda_pci_table
,
771 .probe
= cb_pcidda_pci_probe
,
772 .remove
= __devexit_p(cb_pcidda_pci_remove
),
774 module_comedi_pci_driver(cb_pcidda_driver
, cb_pcidda_pci_driver
);
776 MODULE_AUTHOR("Comedi http://www.comedi.org");
777 MODULE_DESCRIPTION("Comedi low-level driver");
778 MODULE_LICENSE("GPL");