]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/comedi/drivers/cb_pcidda.c
Staging: otus: Drop an unnecessary NULL test
[net-next-2.6.git] / drivers / staging / comedi / drivers / cb_pcidda.c
CommitLineData
086df5b5
IM
1/*
2 comedi/drivers/cb_pcidda.c
3 This intends to be a driver for the ComputerBoards / MeasurementComputing
4 PCI-DDA series.
5
6 Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
7 Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
8
9 COMEDI - Linux Control and Measurement Device Interface
10 Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
11
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.
16
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.
21
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.
25
26*/
27/*
28Driver: cb_pcidda
29Description: MeasurementComputing PCI-DDA series
30Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
31Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
32Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
33 PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
34
35Configuration 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
39 device will be used.
40
41Only simple analog output writing is supported.
42
43So far it has only been tested with:
44 - PCI-DDA08/12
45Please report success/failure with other different cards to
46<comedi@comedi.org>.
47*/
48
49#include "../comedidev.h"
50
51#include "comedi_pci.h"
52#include "8255.h"
53
2696fb57
BP
54#define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */
55#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */
56#define EEPROM_SIZE 128 /* number of entries in eeprom */
57#define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */
086df5b5
IM
58
59/* PCI-DDA base addresses */
60#define DIGITALIO_BADRINDEX 2
2696fb57 61 /* DIGITAL I/O is pci_dev->resource[2] */
086df5b5 62#define DIGITALIO_SIZE 8
2696fb57 63 /* DIGITAL I/O uses 8 I/O port addresses */
086df5b5 64#define DAC_BADRINDEX 3
2696fb57 65 /* DAC is pci_dev->resource[3] */
086df5b5
IM
66
67/* Digital I/O registers */
2696fb57 68#define PORT1A 0 /* PORT 1A DATA */
086df5b5 69
2696fb57 70#define PORT1B 1 /* PORT 1B DATA */
086df5b5 71
2696fb57 72#define PORT1C 2 /* PORT 1C DATA */
086df5b5 73
2696fb57 74#define CONTROL1 3 /* CONTROL REGISTER 1 */
086df5b5 75
2696fb57 76#define PORT2A 4 /* PORT 2A DATA */
086df5b5 77
2696fb57 78#define PORT2B 5 /* PORT 2B DATA */
086df5b5 79
2696fb57 80#define PORT2C 6 /* PORT 2C DATA */
086df5b5 81
2696fb57 82#define CONTROL2 7 /* CONTROL REGISTER 2 */
086df5b5
IM
83
84/* DAC registers */
2696fb57
BP
85#define DACONTROL 0 /* D/A CONTROL REGISTER */
86#define SU 0000001 /* Simultaneous update enabled */
87#define NOSU 0000000 /* Simultaneous update disabled */
88#define ENABLEDAC 0000002 /* Enable specified DAC */
89#define DISABLEDAC 0000000 /* Disable specified DAC */
90#define RANGE2V5 0000000 /* 2.5V */
91#define RANGE5V 0000200 /* 5V */
92#define RANGE10V 0000300 /* 10V */
93#define UNIP 0000400 /* Unipolar outputs */
94#define BIP 0000000 /* Bipolar outputs */
95
96#define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */
97/* write bits */
98#define SERIAL_IN_BIT 0x1 /* serial data input for eeprom, caldacs, reference dac */
086df5b5
IM
99#define CAL_CHANNEL_MASK (0x7 << 1)
100#define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK)
2696fb57 101/* read bits */
086df5b5 102#define CAL_COUNTER_MASK 0x1f
2696fb57
BP
103#define CAL_COUNTER_OVERFLOW_BIT 0x20 /* calibration counter overflow status bit */
104#define AO_BELOW_REF_BIT 0x40 /* analog output is less than reference dac voltage */
105#define SERIAL_OUT_BIT 0x80 /* serial data out, for reading from eeprom */
086df5b5 106
2696fb57
BP
107#define DACALIBRATION2 6 /* D/A CALIBRATION REGISTER 2 */
108#define SELECT_EEPROM_BIT 0x1 /* send serial data in to eeprom */
109#define DESELECT_REF_DAC_BIT 0x2 /* don't send serial data to MAX542 reference dac */
110#define DESELECT_CALDAC_BIT(n) (0x4 << (n)) /* don't send serial data to caldac n */
111#define DUMMY_BIT 0x40 /* manual says to set this bit with no explanation */
086df5b5 112
2696fb57 113#define DADATA 8 /* FIRST D/A DATA REGISTER (0) */
086df5b5 114
9ced1de6 115static const struct comedi_lrange cb_pcidda_ranges = {
086df5b5
IM
116 6,
117 {
118 BIP_RANGE(10),
119 BIP_RANGE(5),
120 BIP_RANGE(2.5),
121 UNI_RANGE(10),
122 UNI_RANGE(5),
123 UNI_RANGE(2.5),
124 }
125};
126
127/*
128 * Board descriptions for two imaginary boards. Describing the
129 * boards in this way is optional, and completely driver-dependent.
130 * Some drivers use arrays such as this, other do not.
131 */
1657e325 132struct cb_pcidda_board {
086df5b5 133 const char *name;
2696fb57
BP
134 char status; /* Driver status: */
135
136 /*
137 * 0 - tested
138 * 1 - manual read, not tested
139 * 2 - manual not read
140 */
141
086df5b5
IM
142 unsigned short device_id;
143 int ao_chans;
144 int ao_bits;
9ced1de6 145 const struct comedi_lrange *ranges;
1657e325 146};
2696fb57 147
1657e325 148static const struct cb_pcidda_board cb_pcidda_boards[] = {
086df5b5 149 {
68c3dbff
BP
150 .name = "pci-dda02/12",
151 .status = 1,
152 .device_id = 0x20,
153 .ao_chans = 2,
154 .ao_bits = 12,
155 .ranges = &cb_pcidda_ranges,
086df5b5
IM
156 },
157 {
68c3dbff
BP
158 .name = "pci-dda04/12",
159 .status = 1,
160 .device_id = 0x21,
161 .ao_chans = 4,
162 .ao_bits = 12,
163 .ranges = &cb_pcidda_ranges,
086df5b5
IM
164 },
165 {
68c3dbff
BP
166 .name = "pci-dda08/12",
167 .status = 0,
168 .device_id = 0x22,
169 .ao_chans = 8,
170 .ao_bits = 12,
171 .ranges = &cb_pcidda_ranges,
086df5b5
IM
172 },
173 {
68c3dbff
BP
174 .name = "pci-dda02/16",
175 .status = 2,
176 .device_id = 0x23,
177 .ao_chans = 2,
178 .ao_bits = 16,
179 .ranges = &cb_pcidda_ranges,
086df5b5
IM
180 },
181 {
68c3dbff
BP
182 .name = "pci-dda04/16",
183 .status = 2,
184 .device_id = 0x24,
185 .ao_chans = 4,
186 .ao_bits = 16,
187 .ranges = &cb_pcidda_ranges,
086df5b5
IM
188 },
189 {
68c3dbff
BP
190 .name = "pci-dda08/16",
191 .status = 0,
192 .device_id = 0x25,
193 .ao_chans = 8,
194 .ao_bits = 16,
195 .ranges = &cb_pcidda_ranges,
086df5b5
IM
196 },
197};
198
199static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
200 {PCI_VENDOR_ID_CB, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
201 {PCI_VENDOR_ID_CB, 0x0021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
202 {PCI_VENDOR_ID_CB, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
203 {PCI_VENDOR_ID_CB, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
204 {PCI_VENDOR_ID_CB, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
205 {PCI_VENDOR_ID_CB, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
206 {0}
207};
208
209MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
210
211/*
212 * Useful for shorthand access to the particular board structure
213 */
1657e325 214#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
086df5b5
IM
215
216/* this structure is for data unique to this hardware driver. If
217 several hardware drivers keep similar information in this structure,
71b5f4f1 218 feel free to suggest moving the variable to the struct comedi_device struct. */
cc7bb61e 219struct cb_pcidda_private {
086df5b5
IM
220 int data;
221
222 /* would be useful for a PCI device */
223 struct pci_dev *pci_dev;
224
225 unsigned long digitalio;
226 unsigned long dac;
2696fb57
BP
227
228 /* unsigned long control_status; */
229 /* unsigned long adc_fifo; */
230
231 unsigned int dac_cal1_bits; /* bits last written to da calibration register 1 */
232 unsigned int ao_range[MAX_AO_CHANNELS]; /* current range settings for output channels */
233 u16 eeprom_data[EEPROM_SIZE]; /* software copy of board's eeprom */
cc7bb61e 234};
086df5b5
IM
235
236/*
237 * most drivers define the following macro to make it easy to
238 * access the private structure.
239 */
cc7bb61e 240#define devpriv ((struct cb_pcidda_private *)dev->private)
086df5b5 241
da91b269
BP
242static int cb_pcidda_attach(struct comedi_device *dev, struct comedi_devconfig *it);
243static int cb_pcidda_detach(struct comedi_device *dev);
2696fb57 244/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
da91b269
BP
245static int cb_pcidda_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
246 struct comedi_insn *insn, unsigned int *data);
2696fb57
BP
247
248/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
249/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
250/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
251
da91b269
BP
252static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
253static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
086df5b5 254 unsigned int num_bits);
da91b269 255static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
086df5b5 256 unsigned int address);
da91b269 257static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
086df5b5
IM
258 unsigned int range);
259
260/*
139dfbdf 261 * The struct comedi_driver structure tells the Comedi core module
086df5b5
IM
262 * which functions to call to configure/deconfigure (attach/detach)
263 * the board, and also about the kernel module that contains
264 * the device code.
265 */
139dfbdf 266static struct comedi_driver driver_cb_pcidda = {
68c3dbff
BP
267 .driver_name = "cb_pcidda",
268 .module = THIS_MODULE,
269 .attach = cb_pcidda_attach,
270 .detach = cb_pcidda_detach,
086df5b5
IM
271};
272
273/*
274 * Attach is called by the Comedi core to configure the driver
275 * for a particular board.
276 */
da91b269 277static int cb_pcidda_attach(struct comedi_device *dev, struct comedi_devconfig *it)
086df5b5 278{
34c43922 279 struct comedi_subdevice *s;
086df5b5
IM
280 struct pci_dev *pcidev;
281 int index;
282
283 printk("comedi%d: cb_pcidda: ", dev->minor);
284
285/*
286 * Allocate the private structure area.
287 */
cc7bb61e 288 if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
086df5b5
IM
289 return -ENOMEM;
290
291/*
292 * Probe the device to determine what device in the series it is.
293 */
294 printk("\n");
295
296 for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
297 pcidev != NULL;
298 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
299 if (pcidev->vendor == PCI_VENDOR_ID_CB) {
300 if (it->options[0] || it->options[1]) {
301 if (pcidev->bus->number != it->options[0] ||
302 PCI_SLOT(pcidev->devfn) !=
303 it->options[1]) {
304 continue;
305 }
306 }
307 for (index = 0; index < N_BOARDS; index++) {
308 if (cb_pcidda_boards[index].device_id ==
309 pcidev->device) {
310 goto found;
311 }
312 }
313 }
314 }
315 if (!pcidev) {
316 printk("Not a ComputerBoards/MeasurementComputing card on requested position\n");
317 return -EIO;
318 }
319 found:
320 devpriv->pci_dev = pcidev;
321 dev->board_ptr = cb_pcidda_boards + index;
2696fb57 322 /* "thisboard" macro can be used from here. */
086df5b5
IM
323 printk("Found %s at requested position\n", thisboard->name);
324
325 /*
326 * Enable PCI device and request regions.
327 */
328 if (comedi_pci_enable(pcidev, thisboard->name)) {
329 printk("cb_pcidda: failed to enable PCI device and request regions\n");
330 return -EIO;
331 }
332
333/*
334 * Allocate the I/O ports.
335 */
336 devpriv->digitalio =
337 pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX);
338 devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX);
339
340/*
341 * Warn about the status of the driver.
342 */
343 if (thisboard->status == 2)
344 printk("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. " "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. " "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
345
346/*
347 * Initialize dev->board_name.
348 */
349 dev->board_name = thisboard->name;
350
351/*
352 * Allocate the subdevice structures.
353 */
354 if (alloc_subdevices(dev, 3) < 0)
355 return -ENOMEM;
356
357 s = dev->subdevices + 0;
358 /* analog output subdevice */
359 s->type = COMEDI_SUBD_AO;
360 s->subdev_flags = SDF_WRITABLE;
361 s->n_chan = thisboard->ao_chans;
362 s->maxdata = (1 << thisboard->ao_bits) - 1;
363 s->range_table = thisboard->ranges;
364 s->insn_write = cb_pcidda_ao_winsn;
086df5b5 365
2696fb57
BP
366 /* s->subdev_flags |= SDF_CMD_READ; */
367 /* s->do_cmd = cb_pcidda_ai_cmd; */
368 /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
369
370 /* two 8255 digital io subdevices */
086df5b5
IM
371 s = dev->subdevices + 1;
372 subdev_8255_init(dev, s, NULL, devpriv->digitalio);
373 s = dev->subdevices + 2;
374 subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
375
376 printk(" eeprom:");
377 for (index = 0; index < EEPROM_SIZE; index++) {
378 devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
379 printk(" %i:0x%x ", index, devpriv->eeprom_data[index]);
380 }
381 printk("\n");
382
2696fb57 383 /* set calibrations dacs */
086df5b5
IM
384 for (index = 0; index < thisboard->ao_chans; index++)
385 cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
386
387 return 1;
388}
389
390/*
391 * _detach is called to deconfigure a device. It should deallocate
392 * resources.
393 * This function is also called when _attach() fails, so it should be
394 * careful not to release resources that were not necessarily
395 * allocated by _attach(). dev->private and dev->subdevices are
396 * deallocated automatically by the core.
397 */
da91b269 398static int cb_pcidda_detach(struct comedi_device *dev)
086df5b5
IM
399{
400/*
401 * Deallocate the I/O ports.
402 */
403 if (devpriv) {
404 if (devpriv->pci_dev) {
405 if (devpriv->dac) {
406 comedi_pci_disable(devpriv->pci_dev);
407 }
408 pci_dev_put(devpriv->pci_dev);
409 }
410 }
2696fb57 411 /* cleanup 8255 */
086df5b5
IM
412 if (dev->subdevices) {
413 subdev_8255_cleanup(dev, dev->subdevices + 1);
414 subdev_8255_cleanup(dev, dev->subdevices + 2);
415 }
416
417 printk("comedi%d: cb_pcidda: remove\n", dev->minor);
418
419 return 0;
420}
421
422/*
423 * I will program this later... ;-)
424 */
425#if 0
da91b269 426static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
086df5b5
IM
427{
428 printk("cb_pcidda_ai_cmd\n");
429 printk("subdev: %d\n", cmd->subdev);
430 printk("flags: %d\n", cmd->flags);
431 printk("start_src: %d\n", cmd->start_src);
432 printk("start_arg: %d\n", cmd->start_arg);
433 printk("scan_begin_src: %d\n", cmd->scan_begin_src);
434 printk("convert_src: %d\n", cmd->convert_src);
435 printk("convert_arg: %d\n", cmd->convert_arg);
436 printk("scan_end_src: %d\n", cmd->scan_end_src);
437 printk("scan_end_arg: %d\n", cmd->scan_end_arg);
438 printk("stop_src: %d\n", cmd->stop_src);
439 printk("stop_arg: %d\n", cmd->stop_arg);
440 printk("chanlist_len: %d\n", cmd->chanlist_len);
441}
442#endif
443
444#if 0
da91b269
BP
445static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
446 struct comedi_cmd *cmd)
086df5b5
IM
447{
448 int err = 0;
449 int tmp;
450
451 /* cmdtest tests a particular command to see if it is valid.
452 * Using the cmdtest ioctl, a user can create a valid cmd
453 * and then have it executes by the cmd ioctl.
454 *
455 * cmdtest returns 1,2,3,4 or 0, depending on which tests
456 * the command passes. */
457
458 /* step 1: make sure trigger sources are trivially valid */
459
460 tmp = cmd->start_src;
461 cmd->start_src &= TRIG_NOW;
462 if (!cmd->start_src || tmp != cmd->start_src)
463 err++;
464
465 tmp = cmd->scan_begin_src;
466 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
467 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
468 err++;
469
470 tmp = cmd->convert_src;
471 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
472 if (!cmd->convert_src || tmp != cmd->convert_src)
473 err++;
474
475 tmp = cmd->scan_end_src;
476 cmd->scan_end_src &= TRIG_COUNT;
477 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
478 err++;
479
480 tmp = cmd->stop_src;
481 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
482 if (!cmd->stop_src || tmp != cmd->stop_src)
483 err++;
484
485 if (err)
486 return 1;
487
488 /* step 2: make sure trigger sources are unique and mutually compatible */
489
490 /* note that mutual compatiblity is not an issue here */
491 if (cmd->scan_begin_src != TRIG_TIMER
492 && cmd->scan_begin_src != TRIG_EXT)
493 err++;
494 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
495 err++;
496 if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
497 err++;
498
499 if (err)
500 return 2;
501
502 /* step 3: make sure arguments are trivially compatible */
503
504 if (cmd->start_arg != 0) {
505 cmd->start_arg = 0;
506 err++;
507 }
508#define MAX_SPEED 10000 /* in nanoseconds */
509#define MIN_SPEED 1000000000 /* in nanoseconds */
510
511 if (cmd->scan_begin_src == TRIG_TIMER) {
512 if (cmd->scan_begin_arg < MAX_SPEED) {
513 cmd->scan_begin_arg = MAX_SPEED;
514 err++;
515 }
516 if (cmd->scan_begin_arg > MIN_SPEED) {
517 cmd->scan_begin_arg = MIN_SPEED;
518 err++;
519 }
520 } else {
521 /* external trigger */
522 /* should be level/edge, hi/lo specification here */
523 /* should specify multiple external triggers */
524 if (cmd->scan_begin_arg > 9) {
525 cmd->scan_begin_arg = 9;
526 err++;
527 }
528 }
529 if (cmd->convert_src == TRIG_TIMER) {
530 if (cmd->convert_arg < MAX_SPEED) {
531 cmd->convert_arg = MAX_SPEED;
532 err++;
533 }
534 if (cmd->convert_arg > MIN_SPEED) {
535 cmd->convert_arg = MIN_SPEED;
536 err++;
537 }
538 } else {
539 /* external trigger */
540 /* see above */
541 if (cmd->convert_arg > 9) {
542 cmd->convert_arg = 9;
543 err++;
544 }
545 }
546
547 if (cmd->scan_end_arg != cmd->chanlist_len) {
548 cmd->scan_end_arg = cmd->chanlist_len;
549 err++;
550 }
551 if (cmd->stop_src == TRIG_COUNT) {
552 if (cmd->stop_arg > 0x00ffffff) {
553 cmd->stop_arg = 0x00ffffff;
554 err++;
555 }
556 } else {
557 /* TRIG_NONE */
558 if (cmd->stop_arg != 0) {
559 cmd->stop_arg = 0;
560 err++;
561 }
562 }
563
564 if (err)
565 return 3;
566
567 /* step 4: fix up any arguments */
568
569 if (cmd->scan_begin_src == TRIG_TIMER) {
570 tmp = cmd->scan_begin_arg;
571 cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
572 cmd->flags & TRIG_ROUND_MASK);
573 if (tmp != cmd->scan_begin_arg)
574 err++;
575 }
576 if (cmd->convert_src == TRIG_TIMER) {
577 tmp = cmd->convert_arg;
578 cb_pcidda_ns_to_timer(&cmd->convert_arg,
579 cmd->flags & TRIG_ROUND_MASK);
580 if (tmp != cmd->convert_arg)
581 err++;
582 if (cmd->scan_begin_src == TRIG_TIMER &&
583 cmd->scan_begin_arg <
584 cmd->convert_arg * cmd->scan_end_arg) {
585 cmd->scan_begin_arg =
586 cmd->convert_arg * cmd->scan_end_arg;
587 err++;
588 }
589 }
590
591 if (err)
592 return 4;
593
594 return 0;
595}
596#endif
597
598/* This function doesn't require a particular form, this is just
599 * what happens to be used in some of the drivers. It should
600 * convert ns nanoseconds to a counter value suitable for programming
601 * the device. Also, it should adjust ns so that it cooresponds to
602 * the actual time that the device will use. */
603#if 0
604static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
605{
606 /* trivial timer */
607 return *ns;
608}
609#endif
610
da91b269
BP
611static int cb_pcidda_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
612 struct comedi_insn *insn, unsigned int *data)
086df5b5
IM
613{
614 unsigned int command;
615 unsigned int channel, range;
616
617 channel = CR_CHAN(insn->chanspec);
618 range = CR_RANGE(insn->chanspec);
619
2696fb57 620 /* adjust calibration dacs if range has changed */
086df5b5
IM
621 if (range != devpriv->ao_range[channel])
622 cb_pcidda_calibrate(dev, channel, range);
623
624 /* output channel configuration */
625 command = NOSU | ENABLEDAC;
626
627 /* output channel range */
628 switch (range) {
629 case 0:
630 command |= BIP | RANGE10V;
631 break;
632 case 1:
633 command |= BIP | RANGE5V;
634 break;
635 case 2:
636 command |= BIP | RANGE2V5;
637 break;
638 case 3:
639 command |= UNIP | RANGE10V;
640 break;
641 case 4:
642 command |= UNIP | RANGE5V;
643 break;
644 case 5:
645 command |= UNIP | RANGE2V5;
646 break;
647 };
648
649 /* output channel specification */
650 command |= channel << 2;
651 outw(command, devpriv->dac + DACONTROL);
652
653 /* write data */
654 outw(data[0], devpriv->dac + DADATA + channel * 2);
655
656 /* return the number of samples read/written */
657 return 1;
658}
659
2696fb57 660/* lowlevel read from eeprom */
da91b269 661static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
086df5b5
IM
662{
663 unsigned int value = 0;
664 int i;
2696fb57 665 const int value_width = 16; /* number of bits wide values are */
086df5b5
IM
666
667 for (i = 1; i <= value_width; i++) {
2696fb57 668 /* read bits most significant bit first */
086df5b5
IM
669 if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
670 value |= 1 << (value_width - i);
671 }
672 }
673
674 return value;
675}
676
2696fb57 677/* lowlevel write to eeprom/dac */
da91b269 678static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
086df5b5
IM
679 unsigned int num_bits)
680{
681 int i;
682
683 for (i = 1; i <= num_bits; i++) {
2696fb57 684 /* send bits most significant bit first */
086df5b5
IM
685 if (value & (1 << (num_bits - i)))
686 devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
687 else
688 devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
689 outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
690 }
691}
692
2696fb57 693/* reads a 16 bit value from board's eeprom */
da91b269 694static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
086df5b5
IM
695 unsigned int address)
696{
697 unsigned int i;
698 unsigned int cal2_bits;
699 unsigned int value;
2696fb57
BP
700 const int max_num_caldacs = 4; /* one caldac for every two dac channels */
701 const int read_instruction = 0x6; /* bits to send to tell eeprom we want to read */
086df5b5
IM
702 const int instruction_length = 3;
703 const int address_length = 8;
704
2696fb57 705 /* send serial output stream to eeprom */
086df5b5 706 cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
2696fb57 707 /* deactivate caldacs (one caldac for every two channels) */
086df5b5
IM
708 for (i = 0; i < max_num_caldacs; i++) {
709 cal2_bits |= DESELECT_CALDAC_BIT(i);
710 }
711 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
712
2696fb57 713 /* tell eeprom we want to read */
086df5b5 714 cb_pcidda_serial_out(dev, read_instruction, instruction_length);
2696fb57 715 /* send address we want to read from */
086df5b5
IM
716 cb_pcidda_serial_out(dev, address, address_length);
717
718 value = cb_pcidda_serial_in(dev);
719
2696fb57 720 /* deactivate eeprom */
086df5b5
IM
721 cal2_bits &= ~SELECT_EEPROM_BIT;
722 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
723
724 return value;
725}
726
2696fb57 727/* writes to 8 bit calibration dacs */
da91b269 728static void cb_pcidda_write_caldac(struct comedi_device *dev, unsigned int caldac,
086df5b5
IM
729 unsigned int channel, unsigned int value)
730{
731 unsigned int cal2_bits;
732 unsigned int i;
2696fb57
BP
733 const int num_channel_bits = 3; /* caldacs use 3 bit channel specification */
734 const int num_caldac_bits = 8; /* 8 bit calibration dacs */
735 const int max_num_caldacs = 4; /* one caldac for every two dac channels */
086df5b5
IM
736
737 /* write 3 bit channel */
738 cb_pcidda_serial_out(dev, channel, num_channel_bits);
2696fb57 739 /* write 8 bit caldac value */
086df5b5
IM
740 cb_pcidda_serial_out(dev, value, num_caldac_bits);
741
2696fb57
BP
742/*
743* latch stream into appropriate caldac deselect reference dac
744*/
086df5b5 745 cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
2696fb57 746 /* deactivate caldacs (one caldac for every two channels) */
086df5b5
IM
747 for (i = 0; i < max_num_caldacs; i++) {
748 cal2_bits |= DESELECT_CALDAC_BIT(i);
749 }
2696fb57 750 /* activate the caldac we want */
086df5b5
IM
751 cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
752 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
2696fb57 753 /* deactivate caldac */
086df5b5
IM
754 cal2_bits |= DESELECT_CALDAC_BIT(caldac);
755 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
756}
757
2696fb57 758/* returns caldac that calibrates given analog out channel */
086df5b5
IM
759static unsigned int caldac_number(unsigned int channel)
760{
761 return channel / 2;
762}
763
2696fb57 764/* returns caldac channel that provides fine gain for given ao channel */
086df5b5
IM
765static unsigned int fine_gain_channel(unsigned int ao_channel)
766{
767 return 4 * (ao_channel % 2);
768}
769
2696fb57 770/* returns caldac channel that provides coarse gain for given ao channel */
086df5b5
IM
771static unsigned int coarse_gain_channel(unsigned int ao_channel)
772{
773 return 1 + 4 * (ao_channel % 2);
774}
775
2696fb57 776/* returns caldac channel that provides coarse offset for given ao channel */
086df5b5
IM
777static unsigned int coarse_offset_channel(unsigned int ao_channel)
778{
779 return 2 + 4 * (ao_channel % 2);
780}
781
2696fb57 782/* returns caldac channel that provides fine offset for given ao channel */
086df5b5
IM
783static unsigned int fine_offset_channel(unsigned int ao_channel)
784{
785 return 3 + 4 * (ao_channel % 2);
786}
787
2696fb57 788/* returns eeprom address that provides offset for given ao channel and range */
086df5b5
IM
789static unsigned int offset_eeprom_address(unsigned int ao_channel,
790 unsigned int range)
791{
792 return 0x7 + 2 * range + 12 * ao_channel;
793}
794
2696fb57 795/* returns eeprom address that provides gain calibration for given ao channel and range */
086df5b5
IM
796static unsigned int gain_eeprom_address(unsigned int ao_channel,
797 unsigned int range)
798{
799 return 0x8 + 2 * range + 12 * ao_channel;
800}
801
2696fb57 802/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
086df5b5
IM
803static unsigned int eeprom_coarse_byte(unsigned int word)
804{
805 return (word >> 8) & 0xff;
806}
807
2696fb57 808/* returns lower byte of eeprom entry, which gives the fine adjustment values */
086df5b5
IM
809static unsigned int eeprom_fine_byte(unsigned int word)
810{
811 return word & 0xff;
812}
813
2696fb57 814/* set caldacs to eeprom values for given channel and range */
da91b269 815static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
086df5b5
IM
816 unsigned int range)
817{
818 unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
819
2696fb57 820 /* remember range so we can tell when we need to readjust calibration */
086df5b5
IM
821 devpriv->ao_range[channel] = range;
822
2696fb57 823 /* get values from eeprom data */
086df5b5
IM
824 coarse_offset =
825 eeprom_coarse_byte(devpriv->
826 eeprom_data[offset_eeprom_address(channel, range)]);
827 fine_offset =
828 eeprom_fine_byte(devpriv->
829 eeprom_data[offset_eeprom_address(channel, range)]);
830 coarse_gain =
831 eeprom_coarse_byte(devpriv->
832 eeprom_data[gain_eeprom_address(channel, range)]);
833 fine_gain =
834 eeprom_fine_byte(devpriv->
835 eeprom_data[gain_eeprom_address(channel, range)]);
836
2696fb57 837 /* set caldacs */
086df5b5
IM
838 cb_pcidda_write_caldac(dev, caldac_number(channel),
839 coarse_offset_channel(channel), coarse_offset);
840 cb_pcidda_write_caldac(dev, caldac_number(channel),
841 fine_offset_channel(channel), fine_offset);
842 cb_pcidda_write_caldac(dev, caldac_number(channel),
843 coarse_gain_channel(channel), coarse_gain);
844 cb_pcidda_write_caldac(dev, caldac_number(channel),
845 fine_gain_channel(channel), fine_gain);
846}
847
848/*
849 * A convenient macro that defines init_module() and cleanup_module(),
850 * as necessary.
851 */
852COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table);