Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dt3000.c
Go to the documentation of this file.
1 /*
2  comedi/drivers/dt3000.c
3  Data Translation DT3000 series driver
4 
5  COMEDI - Linux Control and Measurement Device Interface
6  Copyright (C) 1999 David A. Schleef <[email protected]>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22 */
23 /*
24 Driver: dt3000
25 Description: Data Translation DT3000 series
26 Author: ds
27 Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
28  DT3003-PGL, DT3004, DT3005, DT3004-200
29 Updated: Mon, 14 Apr 2008 15:41:24 +0100
30 Status: works
31 
32 Configuration Options:
33  [0] - PCI bus of device (optional)
34  [1] - PCI slot of device (optional)
35  If bus/slot is not specified, the first supported
36  PCI device found will be used.
37 
38 There is code to support AI commands, but it may not work.
39 
40 AO commands are not supported.
41 */
42 
43 /*
44  The DT3000 series is Data Translation's attempt to make a PCI
45  data acquisition board. The design of this series is very nice,
46  since each board has an on-board DSP (Texas Instruments TMS320C52).
47  However, a few details are a little annoying. The boards lack
48  bus-mastering DMA, which eliminates them from serious work.
49  They also are not capable of autocalibration, which is a common
50  feature in modern hardware. The default firmware is pretty bad,
51  making it nearly impossible to write an RT compatible driver.
52  It would make an interesting project to write a decent firmware
53  for these boards.
54 
55  Data Translation originally wanted an NDA for the documentation
56  for the 3k series. However, if you ask nicely, they might send
57  you the docs without one, also.
58 */
59 
60 #define DEBUG 1
61 
62 #include <linux/interrupt.h>
63 #include "../comedidev.h"
64 #include <linux/delay.h>
65 
66 #include "comedi_fc.h"
67 
68 #define PCI_VENDOR_ID_DT 0x1116
69 
70 static const struct comedi_lrange range_dt3000_ai = { 4, {
71  RANGE(-10, 10),
72  RANGE(-5, 5),
73  RANGE(-2.5, 2.5),
74  RANGE(-1.25, 1.25)
75  }
76 };
77 
78 static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
79  RANGE(-10, 10),
80  RANGE(-1, 1),
81  RANGE(-0.1, 0.1),
82  RANGE(-0.02, 0.02)
83  }
84 };
85 
87 
88  const char *name;
89  unsigned int device_id;
90  int adchan;
91  int adbits;
92  int ai_speed;
93  const struct comedi_lrange *adrange;
94  int dachan;
95  int dabits;
96 };
97 
98 static const struct dt3k_boardtype dt3k_boardtypes[] = {
99  {.name = "dt3001",
100  .device_id = 0x22,
101  .adchan = 16,
102  .adbits = 12,
103  .adrange = &range_dt3000_ai,
104  .ai_speed = 3000,
105  .dachan = 2,
106  .dabits = 12,
107  },
108  {.name = "dt3001-pgl",
109  .device_id = 0x27,
110  .adchan = 16,
111  .adbits = 12,
112  .adrange = &range_dt3000_ai_pgl,
113  .ai_speed = 3000,
114  .dachan = 2,
115  .dabits = 12,
116  },
117  {.name = "dt3002",
118  .device_id = 0x23,
119  .adchan = 32,
120  .adbits = 12,
121  .adrange = &range_dt3000_ai,
122  .ai_speed = 3000,
123  .dachan = 0,
124  .dabits = 0,
125  },
126  {.name = "dt3003",
127  .device_id = 0x24,
128  .adchan = 64,
129  .adbits = 12,
130  .adrange = &range_dt3000_ai,
131  .ai_speed = 3000,
132  .dachan = 2,
133  .dabits = 12,
134  },
135  {.name = "dt3003-pgl",
136  .device_id = 0x28,
137  .adchan = 64,
138  .adbits = 12,
139  .adrange = &range_dt3000_ai_pgl,
140  .ai_speed = 3000,
141  .dachan = 2,
142  .dabits = 12,
143  },
144  {.name = "dt3004",
145  .device_id = 0x25,
146  .adchan = 16,
147  .adbits = 16,
148  .adrange = &range_dt3000_ai,
149  .ai_speed = 10000,
150  .dachan = 2,
151  .dabits = 12,
152  },
153  {.name = "dt3005", /* a.k.a. 3004-200 */
154  .device_id = 0x26,
155  .adchan = 16,
156  .adbits = 16,
157  .adrange = &range_dt3000_ai,
158  .ai_speed = 5000,
159  .dachan = 2,
160  .dabits = 12,
161  },
162 };
163 
164 #define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
165 
166 #define DT3000_SIZE (4*0x1000)
167 
168 /* dual-ported RAM location definitions */
169 
170 #define DPR_DAC_buffer (4*0x000)
171 #define DPR_ADC_buffer (4*0x800)
172 #define DPR_Command (4*0xfd3)
173 #define DPR_SubSys (4*0xfd3)
174 #define DPR_Encode (4*0xfd4)
175 #define DPR_Params(a) (4*(0xfd5+(a)))
176 #define DPR_Tick_Reg_Lo (4*0xff5)
177 #define DPR_Tick_Reg_Hi (4*0xff6)
178 #define DPR_DA_Buf_Front (4*0xff7)
179 #define DPR_DA_Buf_Rear (4*0xff8)
180 #define DPR_AD_Buf_Front (4*0xff9)
181 #define DPR_AD_Buf_Rear (4*0xffa)
182 #define DPR_Int_Mask (4*0xffb)
183 #define DPR_Intr_Flag (4*0xffc)
184 #define DPR_Response_Mbx (4*0xffe)
185 #define DPR_Command_Mbx (4*0xfff)
186 
187 #define AI_FIFO_DEPTH 2003
188 #define AO_FIFO_DEPTH 2048
189 
190 /* command list */
191 
192 #define CMD_GETBRDINFO 0
193 #define CMD_CONFIG 1
194 #define CMD_GETCONFIG 2
195 #define CMD_START 3
196 #define CMD_STOP 4
197 #define CMD_READSINGLE 5
198 #define CMD_WRITESINGLE 6
199 #define CMD_CALCCLOCK 7
200 #define CMD_READEVENTS 8
201 #define CMD_WRITECTCTRL 16
202 #define CMD_READCTCTRL 17
203 #define CMD_WRITECT 18
204 #define CMD_READCT 19
205 #define CMD_WRITEDATA 32
206 #define CMD_READDATA 33
207 #define CMD_WRITEIO 34
208 #define CMD_READIO 35
209 #define CMD_WRITECODE 36
210 #define CMD_READCODE 37
211 #define CMD_EXECUTE 38
212 #define CMD_HALT 48
213 
214 #define SUBS_AI 0
215 #define SUBS_AO 1
216 #define SUBS_DIN 2
217 #define SUBS_DOUT 3
218 #define SUBS_MEM 4
219 #define SUBS_CT 5
220 
221 /* interrupt flags */
222 #define DT3000_CMDONE 0x80
223 #define DT3000_CTDONE 0x40
224 #define DT3000_DAHWERR 0x20
225 #define DT3000_DASWERR 0x10
226 #define DT3000_DAEMPTY 0x08
227 #define DT3000_ADHWERR 0x04
228 #define DT3000_ADSWERR 0x02
229 #define DT3000_ADFULL 0x01
230 
231 #define DT3000_COMPLETION_MASK 0xff00
232 #define DT3000_COMMAND_MASK 0x00ff
233 #define DT3000_NOTPROCESSED 0x0000
234 #define DT3000_NOERROR 0x5500
235 #define DT3000_ERROR 0xaa00
236 #define DT3000_NOTSUPPORTED 0xff00
237 
238 #define DT3000_EXTERNAL_CLOCK 1
239 #define DT3000_RISING_EDGE 2
240 
241 #define TMODE_MASK 0x1c
242 
243 #define DT3000_AD_TRIG_INTERNAL (0<<2)
244 #define DT3000_AD_TRIG_EXTERNAL (1<<2)
245 #define DT3000_AD_RETRIG_INTERNAL (2<<2)
246 #define DT3000_AD_RETRIG_EXTERNAL (3<<2)
247 #define DT3000_AD_EXTRETRIG (4<<2)
248 
249 #define DT3000_CHANNEL_MODE_SE 0
250 #define DT3000_CHANNEL_MODE_DI 1
251 
252 struct dt3k_private {
254  unsigned int lock;
255  unsigned int ao_readback[2];
256  unsigned int ai_front;
257  unsigned int ai_rear;
258 };
259 
260 #define devpriv ((struct dt3k_private *)dev->private)
261 
262 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
263  struct comedi_subdevice *s);
264 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
265  unsigned int round_mode);
266 static int dt3k_ai_cancel(struct comedi_device *dev,
267  struct comedi_subdevice *s);
268 #ifdef DEBUG
269 static void debug_intr_flags(unsigned int flags);
270 #endif
271 
272 #define TIMEOUT 100
273 
274 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
275 {
276  int i;
277  unsigned int status = 0;
278 
279  writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
280 
281  for (i = 0; i < TIMEOUT; i++) {
282  status = readw(devpriv->io_addr + DPR_Command_Mbx);
284  break;
285  udelay(1);
286  }
287  if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
288  return 0;
289 
290  dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n",
291  status);
292 
293  return -ETIME;
294 }
295 
296 static unsigned int dt3k_readsingle(struct comedi_device *dev,
297  unsigned int subsys, unsigned int chan,
298  unsigned int gain)
299 {
300  writew(subsys, devpriv->io_addr + DPR_SubSys);
301 
302  writew(chan, devpriv->io_addr + DPR_Params(0));
303  writew(gain, devpriv->io_addr + DPR_Params(1));
304 
305  dt3k_send_cmd(dev, CMD_READSINGLE);
306 
307  return readw(devpriv->io_addr + DPR_Params(2));
308 }
309 
310 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
311  unsigned int chan, unsigned int data)
312 {
313  writew(subsys, devpriv->io_addr + DPR_SubSys);
314 
315  writew(chan, devpriv->io_addr + DPR_Params(0));
316  writew(0, devpriv->io_addr + DPR_Params(1));
317  writew(data, devpriv->io_addr + DPR_Params(2));
318 
319  dt3k_send_cmd(dev, CMD_WRITESINGLE);
320 }
321 
322 static int debug_n_ints;
323 
324 /* FIXME! Assumes shared interrupt is for this card. */
325 /* What's this debug_n_ints stuff? Obviously needs some work... */
326 static irqreturn_t dt3k_interrupt(int irq, void *d)
327 {
328  struct comedi_device *dev = d;
329  struct comedi_subdevice *s;
330  unsigned int status;
331 
332  if (!dev->attached)
333  return IRQ_NONE;
334 
335  s = &dev->subdevices[0];
336  status = readw(devpriv->io_addr + DPR_Intr_Flag);
337 #ifdef DEBUG
338  debug_intr_flags(status);
339 #endif
340 
341  if (status & DT3000_ADFULL) {
342  dt3k_ai_empty_fifo(dev, s);
343  s->async->events |= COMEDI_CB_BLOCK;
344  }
345 
346  if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
347  s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
348 
349  debug_n_ints++;
350  if (debug_n_ints >= 10) {
351  dt3k_ai_cancel(dev, s);
352  s->async->events |= COMEDI_CB_EOA;
353  }
354 
355  comedi_event(dev, s);
356  return IRQ_HANDLED;
357 }
358 
359 #ifdef DEBUG
360 static char *intr_flags[] = {
361  "AdFull", "AdSwError", "AdHwError", "DaEmpty",
362  "DaSwError", "DaHwError", "CtDone", "CmDone",
363 };
364 
365 static void debug_intr_flags(unsigned int flags)
366 {
367  int i;
368  printk(KERN_DEBUG "dt3k: intr_flags:");
369  for (i = 0; i < 8; i++) {
370  if (flags & (1 << i))
371  printk(KERN_CONT " %s", intr_flags[i]);
372  }
373  printk(KERN_CONT "\n");
374 }
375 #endif
376 
377 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
378  struct comedi_subdevice *s)
379 {
380  int front;
381  int rear;
382  int count;
383  int i;
384  short data;
385 
386  front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
387  count = front - devpriv->ai_front;
388  if (count < 0)
389  count += AI_FIFO_DEPTH;
390 
391  dev_dbg(dev->class_dev, "reading %d samples\n", count);
392 
393  rear = devpriv->ai_rear;
394 
395  for (i = 0; i < count; i++) {
396  data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
397  comedi_buf_put(s->async, data);
398  rear++;
399  if (rear >= AI_FIFO_DEPTH)
400  rear = 0;
401  }
402 
403  devpriv->ai_rear = rear;
404  writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
405 }
406 
407 static int dt3k_ai_cmdtest(struct comedi_device *dev,
408  struct comedi_subdevice *s, struct comedi_cmd *cmd)
409 {
410  int err = 0;
411  int tmp;
412 
413  /* Step 1 : check if triggers are trivially valid */
414 
415  err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
416  err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
417  err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
418  err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
419  err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
420 
421  if (err)
422  return 1;
423 
424  /* Step 2a : make sure trigger sources are unique */
425  /* Step 2b : and mutually compatible */
426 
427  if (err)
428  return 2;
429 
430  /* step 3: make sure arguments are trivially compatible */
431 
432  if (cmd->start_arg != 0) {
433  cmd->start_arg = 0;
434  err++;
435  }
436 
437  if (cmd->scan_begin_src == TRIG_TIMER) {
438  if (cmd->scan_begin_arg < this_board->ai_speed) {
439  cmd->scan_begin_arg = this_board->ai_speed;
440  err++;
441  }
442  if (cmd->scan_begin_arg > 100 * 16 * 65535) {
443  cmd->scan_begin_arg = 100 * 16 * 65535;
444  err++;
445  }
446  } else {
447  /* not supported */
448  }
449  if (cmd->convert_src == TRIG_TIMER) {
450  if (cmd->convert_arg < this_board->ai_speed) {
451  cmd->convert_arg = this_board->ai_speed;
452  err++;
453  }
454  if (cmd->convert_arg > 50 * 16 * 65535) {
455  cmd->convert_arg = 50 * 16 * 65535;
456  err++;
457  }
458  } else {
459  /* not supported */
460  }
461 
462  if (cmd->scan_end_arg != cmd->chanlist_len) {
463  cmd->scan_end_arg = cmd->chanlist_len;
464  err++;
465  }
466  if (cmd->stop_src == TRIG_COUNT) {
467  if (cmd->stop_arg > 0x00ffffff) {
468  cmd->stop_arg = 0x00ffffff;
469  err++;
470  }
471  } else {
472  /* TRIG_NONE */
473  if (cmd->stop_arg != 0) {
474  cmd->stop_arg = 0;
475  err++;
476  }
477  }
478 
479  if (err)
480  return 3;
481 
482  /* step 4: fix up any arguments */
483 
484  if (cmd->scan_begin_src == TRIG_TIMER) {
485  tmp = cmd->scan_begin_arg;
486  dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
487  cmd->flags & TRIG_ROUND_MASK);
488  if (tmp != cmd->scan_begin_arg)
489  err++;
490  } else {
491  /* not supported */
492  }
493  if (cmd->convert_src == TRIG_TIMER) {
494  tmp = cmd->convert_arg;
495  dt3k_ns_to_timer(50, &cmd->convert_arg,
496  cmd->flags & TRIG_ROUND_MASK);
497  if (tmp != cmd->convert_arg)
498  err++;
499  if (cmd->scan_begin_src == TRIG_TIMER &&
500  cmd->scan_begin_arg <
501  cmd->convert_arg * cmd->scan_end_arg) {
502  cmd->scan_begin_arg =
503  cmd->convert_arg * cmd->scan_end_arg;
504  err++;
505  }
506  } else {
507  /* not supported */
508  }
509 
510  if (err)
511  return 4;
512 
513  return 0;
514 }
515 
516 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
517  unsigned int round_mode)
518 {
519  int divider, base, prescale;
520 
521  /* This function needs improvment */
522  /* Don't know if divider==0 works. */
523 
524  for (prescale = 0; prescale < 16; prescale++) {
525  base = timer_base * (prescale + 1);
526  switch (round_mode) {
527  case TRIG_ROUND_NEAREST:
528  default:
529  divider = (*nanosec + base / 2) / base;
530  break;
531  case TRIG_ROUND_DOWN:
532  divider = (*nanosec) / base;
533  break;
534  case TRIG_ROUND_UP:
535  divider = (*nanosec) / base;
536  break;
537  }
538  if (divider < 65536) {
539  *nanosec = divider * base;
540  return (prescale << 16) | (divider);
541  }
542  }
543 
544  prescale = 15;
545  base = timer_base * (1 << prescale);
546  divider = 65535;
547  *nanosec = divider * base;
548  return (prescale << 16) | (divider);
549 }
550 
551 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
552 {
553  struct comedi_cmd *cmd = &s->async->cmd;
554  int i;
555  unsigned int chan, range, aref;
556  unsigned int divider;
557  unsigned int tscandiv;
558  int ret;
559  unsigned int mode;
560 
561  dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n");
562  for (i = 0; i < cmd->chanlist_len; i++) {
563  chan = CR_CHAN(cmd->chanlist[i]);
564  range = CR_RANGE(cmd->chanlist[i]);
565 
566  writew((range << 6) | chan,
567  devpriv->io_addr + DPR_ADC_buffer + i);
568  }
569  aref = CR_AREF(cmd->chanlist[0]);
570 
571  writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
572  dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
573 
574  if (cmd->convert_src == TRIG_TIMER) {
575  divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
576  cmd->flags & TRIG_ROUND_MASK);
577  writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
578  dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16);
579  writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
580  dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff);
581  } else {
582  /* not supported */
583  }
584 
585  if (cmd->scan_begin_src == TRIG_TIMER) {
586  tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
587  cmd->flags & TRIG_ROUND_MASK);
588  writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
589  dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16);
590  writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
591  dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff);
592  } else {
593  /* not supported */
594  }
595 
596  mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
597  writew(mode, devpriv->io_addr + DPR_Params(5));
598  dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode);
599  writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
600  dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF);
601 
602  writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
603  dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
604 
605  writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
606  ret = dt3k_send_cmd(dev, CMD_CONFIG);
607 
608  writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
609  devpriv->io_addr + DPR_Int_Mask);
610 
611  debug_n_ints = 0;
612 
613  writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
614  ret = dt3k_send_cmd(dev, CMD_START);
615 
616  return 0;
617 }
618 
619 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
620 {
621  int ret;
622 
623  writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
624  ret = dt3k_send_cmd(dev, CMD_STOP);
625 
626  writew(0, devpriv->io_addr + DPR_Int_Mask);
627 
628  return 0;
629 }
630 
631 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
632  struct comedi_insn *insn, unsigned int *data)
633 {
634  int i;
635  unsigned int chan, gain, aref;
636 
637  chan = CR_CHAN(insn->chanspec);
638  gain = CR_RANGE(insn->chanspec);
639  /* XXX docs don't explain how to select aref */
640  aref = CR_AREF(insn->chanspec);
641 
642  for (i = 0; i < insn->n; i++)
643  data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
644 
645  return i;
646 }
647 
648 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
649  struct comedi_insn *insn, unsigned int *data)
650 {
651  int i;
652  unsigned int chan;
653 
654  chan = CR_CHAN(insn->chanspec);
655  for (i = 0; i < insn->n; i++) {
656  dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
657  devpriv->ao_readback[chan] = data[i];
658  }
659 
660  return i;
661 }
662 
663 static int dt3k_ao_insn_read(struct comedi_device *dev,
664  struct comedi_subdevice *s,
665  struct comedi_insn *insn, unsigned int *data)
666 {
667  int i;
668  unsigned int chan;
669 
670  chan = CR_CHAN(insn->chanspec);
671  for (i = 0; i < insn->n; i++)
672  data[i] = devpriv->ao_readback[chan];
673 
674  return i;
675 }
676 
677 static void dt3k_dio_config(struct comedi_device *dev, int bits)
678 {
679  /* XXX */
680  writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
681 
682  writew(bits, devpriv->io_addr + DPR_Params(0));
683 #if 0
684  /* don't know */
685  writew(0, devpriv->io_addr + DPR_Params(1));
686  writew(0, devpriv->io_addr + DPR_Params(2));
687 #endif
688 
689  dt3k_send_cmd(dev, CMD_CONFIG);
690 }
691 
692 static int dt3k_dio_insn_config(struct comedi_device *dev,
693  struct comedi_subdevice *s,
694  struct comedi_insn *insn, unsigned int *data)
695 {
696  int mask;
697 
698  mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
699 
700  switch (data[0]) {
702  s->io_bits |= mask;
703  break;
705  s->io_bits &= ~mask;
706  break;
708  data[1] =
709  (s->
710  io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
711  COMEDI_INPUT;
712  return insn->n;
713  break;
714  default:
715  return -EINVAL;
716  break;
717  }
718  mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
719  dt3k_dio_config(dev, mask);
720 
721  return insn->n;
722 }
723 
724 static int dt3k_dio_insn_bits(struct comedi_device *dev,
725  struct comedi_subdevice *s,
726  struct comedi_insn *insn, unsigned int *data)
727 {
728  if (data[0]) {
729  s->state &= ~data[0];
730  s->state |= data[1] & data[0];
731  dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
732  }
733  data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
734 
735  return insn->n;
736 }
737 
738 static int dt3k_mem_insn_read(struct comedi_device *dev,
739  struct comedi_subdevice *s,
740  struct comedi_insn *insn, unsigned int *data)
741 {
742  unsigned int addr = CR_CHAN(insn->chanspec);
743  int i;
744 
745  for (i = 0; i < insn->n; i++) {
746  writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
747  writew(addr, devpriv->io_addr + DPR_Params(0));
748  writew(1, devpriv->io_addr + DPR_Params(1));
749 
750  dt3k_send_cmd(dev, CMD_READCODE);
751 
752  data[i] = readw(devpriv->io_addr + DPR_Params(2));
753  }
754 
755  return i;
756 }
757 
758 static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev,
759  struct comedi_devconfig *it)
760 {
761  struct pci_dev *pcidev = NULL;
762  int bus = it->options[0];
763  int slot = it->options[1];
764  int i;
765 
766  for_each_pci_dev(pcidev) {
767  if (bus || slot) {
768  if (bus != pcidev->bus->number ||
769  slot != PCI_SLOT(pcidev->devfn))
770  continue;
771  }
772  if (pcidev->vendor != PCI_VENDOR_ID_DT)
773  continue;
774  for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
775  if (dt3k_boardtypes[i].device_id != pcidev->device)
776  continue;
777  dev->board_ptr = dt3k_boardtypes + i;
778  return pcidev;
779  }
780  }
781  dev_err(dev->class_dev,
782  "No supported board found! (req. bus %d, slot %d)\n",
783  bus, slot);
784  return NULL;
785 }
786 
787 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
788 {
789  struct pci_dev *pcidev;
790  struct comedi_subdevice *s;
791  resource_size_t pci_base;
792  int ret = 0;
793 
794  dev_dbg(dev->class_dev, "dt3000:\n");
795 
796  ret = alloc_private(dev, sizeof(struct dt3k_private));
797  if (ret < 0)
798  return ret;
799 
800  pcidev = dt3000_find_pci_dev(dev, it);
801  if (!pcidev)
802  return -EIO;
803  comedi_set_hw_dev(dev, &pcidev->dev);
804 
805  ret = comedi_pci_enable(pcidev, "dt3000");
806  if (ret < 0)
807  return ret;
808  dev->iobase = 1; /* the "detach" needs this */
809 
810  pci_base = pci_resource_start(pcidev, 0);
811  devpriv->io_addr = ioremap(pci_base, DT3000_SIZE);
812  if (!devpriv->io_addr)
813  return -ENOMEM;
814 
815  dev->board_name = this_board->name;
816 
817  if (request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
818  "dt3000", dev)) {
819  dev_err(dev->class_dev, "unable to allocate IRQ %u\n",
820  pcidev->irq);
821  return -EINVAL;
822  }
823  dev->irq = pcidev->irq;
824 
825  ret = comedi_alloc_subdevices(dev, 4);
826  if (ret)
827  return ret;
828 
829  s = &dev->subdevices[0];
830  dev->read_subdev = s;
831 
832  /* ai subdevice */
833  s->type = COMEDI_SUBD_AI;
835  s->n_chan = this_board->adchan;
836  s->insn_read = dt3k_ai_insn;
837  s->maxdata = (1 << this_board->adbits) - 1;
838  s->len_chanlist = 512;
839  s->range_table = &range_dt3000_ai; /* XXX */
840  s->do_cmd = dt3k_ai_cmd;
841  s->do_cmdtest = dt3k_ai_cmdtest;
842  s->cancel = dt3k_ai_cancel;
843 
844  s = &dev->subdevices[1];
845  /* ao subsystem */
846  s->type = COMEDI_SUBD_AO;
848  s->n_chan = 2;
849  s->insn_read = dt3k_ao_insn_read;
850  s->insn_write = dt3k_ao_insn;
851  s->maxdata = (1 << this_board->dabits) - 1;
852  s->len_chanlist = 1;
854 
855  s = &dev->subdevices[2];
856  /* dio subsystem */
857  s->type = COMEDI_SUBD_DIO;
859  s->n_chan = 8;
860  s->insn_config = dt3k_dio_insn_config;
861  s->insn_bits = dt3k_dio_insn_bits;
862  s->maxdata = 1;
863  s->len_chanlist = 8;
865 
866  s = &dev->subdevices[3];
867  /* mem subsystem */
870  s->n_chan = 0x1000;
871  s->insn_read = dt3k_mem_insn_read;
872  s->maxdata = 0xff;
873  s->len_chanlist = 1;
875 
876 #if 0
877  s = &dev->subdevices[4];
878  /* proc subsystem */
879  s->type = COMEDI_SUBD_PROC;
880 #endif
881 
882  return 0;
883 }
884 
885 static void dt3000_detach(struct comedi_device *dev)
886 {
887  struct pci_dev *pcidev = comedi_to_pci_dev(dev);
888 
889  if (dev->irq)
890  free_irq(dev->irq, dev);
891  if (devpriv) {
892  if (devpriv->io_addr)
893  iounmap(devpriv->io_addr);
894  }
895  if (pcidev) {
896  if (dev->iobase)
897  comedi_pci_disable(pcidev);
898  pci_dev_put(pcidev);
899  }
900 }
901 
902 static struct comedi_driver dt3000_driver = {
903  .driver_name = "dt3000",
904  .module = THIS_MODULE,
905  .attach = dt3000_attach,
906  .detach = dt3000_detach,
907 };
908 
909 static int __devinit dt3000_pci_probe(struct pci_dev *dev,
910  const struct pci_device_id *ent)
911 {
912  return comedi_pci_auto_config(dev, &dt3000_driver);
913 }
914 
915 static void __devexit dt3000_pci_remove(struct pci_dev *dev)
916 {
918 }
919 
920 static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
921  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
922  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
923  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
924  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
925  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
926  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
927  { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
928  { 0 }
929 };
930 MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
931 
932 static struct pci_driver dt3000_pci_driver = {
933  .name = "dt3000",
934  .id_table = dt3000_pci_table,
935  .probe = dt3000_pci_probe,
936  .remove = __devexit_p(dt3000_pci_remove),
937 };
938 module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
939 
940 MODULE_AUTHOR("Comedi http://www.comedi.org");
941 MODULE_DESCRIPTION("Comedi low-level driver");
942 MODULE_LICENSE("GPL");