Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
das16.c
Go to the documentation of this file.
1 /*
2  comedi/drivers/das16.c
3  DAS16 driver
4 
5  COMEDI - Linux Control and Measurement Device Interface
6  Copyright (C) 2000 David A. Schleef <[email protected]>
7  Copyright (C) 2000 Chris R. Baugher <[email protected]>
8  Copyright (C) 2001,2002 Frank Mori Hess <[email protected]>
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 
24 ************************************************************************
25 */
26 /*
27 Driver: das16
28 Description: DAS16 compatible boards
29 Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
30 Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
31  DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
32  DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
33  DAS-1602 (das-1602),
34  [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
35  PC104-DAS16JR/16 (pc104-das16jr/16),
36  CIO-DAS16JR/16 (cio-das16jr/16),
37  CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
38  CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
39  CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
40  CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
41 Status: works
42 Updated: 2003-10-12
43 
44 A rewrite of the das16 and das1600 drivers.
45 Options:
46  [0] - base io address
47  [1] - irq (does nothing, irq is not used anymore)
48  [2] - dma (optional, required for comedi_command support)
49  [3] - master clock speed in MHz (optional, 1 or 10, ignored if
50  board can probe clock, defaults to 1)
51  [4] - analog input range lowest voltage in microvolts (optional,
52  only useful if your board does not have software
53  programmable gain)
54  [5] - analog input range highest voltage in microvolts (optional,
55  only useful if board does not have software programmable
56  gain)
57  [6] - analog output range lowest voltage in microvolts (optional)
58  [7] - analog output range highest voltage in microvolts (optional)
59  [8] - use timer mode for DMA. Timer mode is needed e.g. for
60  buggy DMA controllers in NS CS5530A (Geode Companion), and for
61  'jr' cards that lack a hardware fifo. This option is no
62  longer needed, since timer mode is _always_ used.
63 
64 Passing a zero for an option is the same as leaving it unspecified.
65 
66 */
67 /*
68 
69 Testing and debugging help provided by Daniel Koch.
70 
71 Keithley Manuals:
72  2309.PDF (das16)
73  4919.PDF (das1400, 1600)
74  4922.PDF (das-1400)
75  4923.PDF (das1200, 1400, 1600)
76 
77 Computer boards manuals also available from their website
78 www.measurementcomputing.com
79 
80 */
81 
82 #include <linux/pci.h>
83 #include <linux/slab.h>
84 #include <linux/interrupt.h>
85 #include <asm/dma.h>
86 #include "../comedidev.h"
87 
88 #include "8253.h"
89 #include "8255.h"
90 #include "comedi_fc.h"
91 
92 #undef DEBUG
93 /* #define DEBUG */
94 
95 #ifdef DEBUG
96 #define DEBUG_PRINT(format, args...) \
97  printk(KERN_DEBUG "das16: " format, ## args)
98 #else
99 #define DEBUG_PRINT(format, args...)
100 #endif
101 
102 #define DAS16_SIZE 20 /* number of ioports */
103 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
104 
105 /*
106  cio-das16.pdf
107 
108  "das16"
109  "das16/f"
110 
111  0 a/d bits 0-3 start 12 bit
112  1 a/d bits 4-11 unused
113  2 mux read mux set
114  3 di 4 bit do 4 bit
115  4 unused ao0_lsb
116  5 unused ao0_msb
117  6 unused ao1_lsb
118  7 unused ao1_msb
119  8 status eoc uni/bip interrupt reset
120  9 dma, int, trig ctrl set dma, int
121  a pacer control unused
122  b reserved reserved
123  cdef 8254
124  0123 8255
125 
126 */
127 
128 /*
129  cio-das16jr.pdf
130 
131  "das16jr"
132 
133  0 a/d bits 0-3 start 12 bit
134  1 a/d bits 4-11 unused
135  2 mux read mux set
136  3 di 4 bit do 4 bit
137  4567 unused unused
138  8 status eoc uni/bip interrupt reset
139  9 dma, int, trig ctrl set dma, int
140  a pacer control unused
141  b gain status gain control
142  cdef 8254
143 
144 */
145 
146 /*
147  cio-das16jr_16.pdf
148 
149  "das16jr_16"
150 
151  0 a/d bits 0-7 start 16 bit
152  1 a/d bits 8-15 unused
153  2 mux read mux set
154  3 di 4 bit do 4 bit
155  4567 unused unused
156  8 status eoc uni/bip interrupt reset
157  9 dma, int, trig ctrl set dma, int
158  a pacer control unused
159  b gain status gain control
160  cdef 8254
161 
162 */
163 /*
164  cio-das160x-1x.pdf
165 
166  "das1601/12"
167  "das1602/12"
168  "das1602/16"
169 
170  0 a/d bits 0-3 start 12 bit
171  1 a/d bits 4-11 unused
172  2 mux read mux set
173  3 di 4 bit do 4 bit
174  4 unused ao0_lsb
175  5 unused ao0_msb
176  6 unused ao1_lsb
177  7 unused ao1_msb
178  8 status eoc uni/bip interrupt reset
179  9 dma, int, trig ctrl set dma, int
180  a pacer control unused
181  b gain status gain control
182  cdef 8254
183  400 8255
184  404 unused conversion enable
185  405 unused burst enable
186  406 unused das1600 enable
187  407 status
188 
189 */
190 
191 /* size in bytes of a sample from board */
192 static const int sample_size = 2;
193 
194 #define DAS16_TRIG 0
195 #define DAS16_AI_LSB 0
196 #define DAS16_AI_MSB 1
197 #define DAS16_MUX 2
198 #define DAS16_DIO 3
199 #define DAS16_AO_LSB(x) ((x) ? 6 : 4)
200 #define DAS16_AO_MSB(x) ((x) ? 7 : 5)
201 #define DAS16_STATUS 8
202 #define BUSY (1<<7)
203 #define UNIPOLAR (1<<6)
204 #define DAS16_MUXBIT (1<<5)
205 #define DAS16_INT (1<<4)
206 #define DAS16_CONTROL 9
207 #define DAS16_INTE (1<<7)
208 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
209 #define DMA_ENABLE (1<<2)
210 #define PACING_MASK 0x3
211 #define INT_PACER 0x03
212 #define EXT_PACER 0x02
213 #define DAS16_SOFT 0x00
214 #define DAS16_PACER 0x0A
215 #define DAS16_CTR0 (1<<1)
216 #define DAS16_TRIG0 (1<<0)
217 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
218 #define DAS16_GAIN 0x0B
219 #define DAS16_CNTR0_DATA 0x0C
220 #define DAS16_CNTR1_DATA 0x0D
221 #define DAS16_CNTR2_DATA 0x0E
222 #define DAS16_CNTR_CONTROL 0x0F
223 #define DAS16_TERM_CNT 0x00
224 #define DAS16_ONE_SHOT 0x02
225 #define DAS16_RATE_GEN 0x04
226 #define DAS16_CNTR_LSB_MSB 0x30
227 #define DAS16_CNTR0 0x00
228 #define DAS16_CNTR1 0x40
229 #define DAS16_CNTR2 0x80
230 
231 #define DAS1600_CONV 0x404
232 #define DAS1600_CONV_DISABLE 0x40
233 #define DAS1600_BURST 0x405
234 #define DAS1600_BURST_VAL 0x40
235 #define DAS1600_ENABLE 0x406
236 #define DAS1600_ENABLE_VAL 0x40
237 #define DAS1600_STATUS_B 0x407
238 #define DAS1600_BME 0x40
239 #define DAS1600_ME 0x20
240 #define DAS1600_CD 0x10
241 #define DAS1600_WS 0x02
242 #define DAS1600_CLK_10MHZ 0x01
243 
244 static const struct comedi_lrange range_das1x01_bip = { 4, {
245  BIP_RANGE(10),
246  BIP_RANGE(1),
247  BIP_RANGE(0.1),
248  BIP_RANGE(0.01),
249  }
250 };
251 
252 static const struct comedi_lrange range_das1x01_unip = { 4, {
253  UNI_RANGE(10),
254  UNI_RANGE(1),
255  UNI_RANGE(0.1),
256  UNI_RANGE(0.01),
257  }
258 };
259 
260 static const struct comedi_lrange range_das1x02_bip = { 4, {
261  BIP_RANGE(10),
262  BIP_RANGE(5),
263  BIP_RANGE(2.5),
264  BIP_RANGE(1.25),
265  }
266 };
267 
268 static const struct comedi_lrange range_das1x02_unip = { 4, {
269  UNI_RANGE(10),
270  UNI_RANGE(5),
271  UNI_RANGE(2.5),
272  UNI_RANGE(1.25),
273  }
274 };
275 
276 static const struct comedi_lrange range_das16jr = { 9, {
277  /* also used by 16/330 */
278  BIP_RANGE(10),
279  BIP_RANGE(5),
280  BIP_RANGE(2.5),
281  BIP_RANGE(1.25),
282  BIP_RANGE(0.625),
283  UNI_RANGE(10),
284  UNI_RANGE(5),
285  UNI_RANGE(2.5),
286  UNI_RANGE(1.25),
287  }
288 };
289 
290 static const struct comedi_lrange range_das16jr_16 = { 8, {
291  BIP_RANGE(10),
292  BIP_RANGE(5),
293  BIP_RANGE(2.5),
294  BIP_RANGE(1.25),
295  UNI_RANGE(10),
296  UNI_RANGE(5),
297  UNI_RANGE(2.5),
298  UNI_RANGE(1.25),
299  }
300 };
301 
302 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
303 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
304 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
305 
306 enum {
312 };
313 static const int *const das16_gainlists[] = {
314  NULL,
315  das16jr_gainlist,
316  das16jr_16_gainlist,
317  das1600_gainlist,
318  das1600_gainlist,
319 };
320 
321 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
322  &range_unknown,
323  &range_das16jr,
324  &range_das16jr_16,
325  &range_das1x01_unip,
326  &range_das1x02_unip,
327 };
328 
329 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
330  &range_unknown,
331  &range_das16jr,
332  &range_das16jr_16,
333  &range_das1x01_bip,
334  &range_das1x02_bip,
335 };
336 
337 struct munge_info {
339  unsigned have_byte:1;
340 };
341 
342 struct das16_board {
343  const char *name;
344  void *ai;
345  unsigned int ai_nbits;
346  unsigned int ai_speed; /* max conversion speed in nanosec */
347  unsigned int ai_pg;
348  void *ao;
349  unsigned int ao_nbits;
350  void *di;
351  void *do_;
352 
353  unsigned int i8255_offset;
354  unsigned int i8254_offset;
355 
356  unsigned int size;
357  unsigned int id;
358 };
359 
360 #define DAS16_TIMEOUT 1000
361 
362 /* Period for timer interrupt in jiffies. It's a function
363  * to deal with possibility of dynamic HZ patches */
364 static inline int timer_period(void)
365 {
366  return HZ / 20;
367 }
368 
370  unsigned int ai_unipolar; /* unipolar flag */
371  unsigned int ai_singleended; /* single ended flag */
372  unsigned int clockbase; /* master clock speed in ns */
373  volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
374  volatile unsigned long adc_byte_count; /* number of bytes remaining */
375  /* divisor dividing master clock to get conversion frequency */
376  unsigned int divisor1;
377  /* divisor dividing master clock to get conversion frequency */
378  unsigned int divisor2;
379  unsigned int dma_chan; /* dma channel */
382  unsigned int current_buffer;
383  volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
390 
391  struct timer_list timer; /* for timed interrupt */
392  volatile short timer_running;
393  volatile short timer_mode; /* true if using timer mode */
394 };
395 #define devpriv ((struct das16_private_struct *)(dev->private))
396 
397 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
398  struct comedi_cmd *cmd)
399 {
400  const struct das16_board *board = comedi_board(dev);
401  int err = 0, tmp;
402  int gain, start_chan, i;
403  int mask;
404 
405  /* Step 1 : check if triggers are trivially valid */
406 
407  err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
408 
409  mask = TRIG_FOLLOW;
410  /* if board supports burst mode */
411  if (board->size > 0x400)
412  mask |= TRIG_TIMER | TRIG_EXT;
413  err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
414 
415  tmp = cmd->convert_src;
416  mask = TRIG_TIMER | TRIG_EXT;
417  /* if board supports burst mode */
418  if (board->size > 0x400)
419  mask |= TRIG_NOW;
420  err |= cfc_check_trigger_src(&cmd->convert_src, mask);
421 
422  err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
423  err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
424 
425  if (err)
426  return 1;
427 
428  /* Step 2a : make sure trigger sources are unique */
429 
430  err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
431  err |= cfc_check_trigger_is_unique(cmd->convert_src);
432  err |= cfc_check_trigger_is_unique(cmd->stop_src);
433 
434  /* Step 2b : and mutually compatible */
435 
436  /* make sure scan_begin_src and convert_src dont conflict */
437  if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
438  err |= -EINVAL;
439  if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
440  err |= -EINVAL;
441 
442  if (err)
443  return 2;
444 
445  /* step 3: make sure arguments are trivially compatible */
446  if (cmd->start_arg != 0) {
447  cmd->start_arg = 0;
448  err++;
449  }
450 
451  if (cmd->scan_begin_src == TRIG_FOLLOW) {
452  /* internal trigger */
453  if (cmd->scan_begin_arg != 0) {
454  cmd->scan_begin_arg = 0;
455  err++;
456  }
457  }
458 
459  if (cmd->scan_end_arg != cmd->chanlist_len) {
460  cmd->scan_end_arg = cmd->chanlist_len;
461  err++;
462  }
463  /* check against maximum frequency */
464  if (cmd->scan_begin_src == TRIG_TIMER) {
465  if (cmd->scan_begin_arg <
466  board->ai_speed * cmd->chanlist_len) {
467  cmd->scan_begin_arg =
468  board->ai_speed * cmd->chanlist_len;
469  err++;
470  }
471  }
472  if (cmd->convert_src == TRIG_TIMER) {
473  if (cmd->convert_arg < board->ai_speed) {
474  cmd->convert_arg = board->ai_speed;
475  err++;
476  }
477  }
478 
479  if (cmd->stop_src == TRIG_NONE) {
480  if (cmd->stop_arg != 0) {
481  cmd->stop_arg = 0;
482  err++;
483  }
484  }
485  if (err)
486  return 3;
487 
488  /* step 4: fix up arguments */
489  if (cmd->scan_begin_src == TRIG_TIMER) {
490  unsigned int tmp = cmd->scan_begin_arg;
491  /* set divisors, correct timing arguments */
492  i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
493  &(devpriv->divisor1),
494  &(devpriv->divisor2),
495  &(cmd->scan_begin_arg),
496  cmd->flags & TRIG_ROUND_MASK);
497  err += (tmp != cmd->scan_begin_arg);
498  }
499  if (cmd->convert_src == TRIG_TIMER) {
500  unsigned int tmp = cmd->convert_arg;
501  /* set divisors, correct timing arguments */
502  i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
503  &(devpriv->divisor1),
504  &(devpriv->divisor2),
505  &(cmd->convert_arg),
506  cmd->flags & TRIG_ROUND_MASK);
507  err += (tmp != cmd->convert_arg);
508  }
509  if (err)
510  return 4;
511 
512  /* check channel/gain list against card's limitations */
513  if (cmd->chanlist) {
514  gain = CR_RANGE(cmd->chanlist[0]);
515  start_chan = CR_CHAN(cmd->chanlist[0]);
516  for (i = 1; i < cmd->chanlist_len; i++) {
517  if (CR_CHAN(cmd->chanlist[i]) !=
518  (start_chan + i) % s->n_chan) {
519  comedi_error(dev,
520  "entries in chanlist must be "
521  "consecutive channels, "
522  "counting upwards\n");
523  err++;
524  }
525  if (CR_RANGE(cmd->chanlist[i]) != gain) {
526  comedi_error(dev,
527  "entries in chanlist must all "
528  "have the same gain\n");
529  err++;
530  }
531  }
532  }
533  if (err)
534  return 5;
535 
536  return 0;
537 }
538 
539 /* utility function that suggests a dma transfer size in bytes */
540 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
541  const struct comedi_cmd *cmd)
542 {
543  unsigned int size;
544  unsigned int freq;
545 
546  /* if we are using timer interrupt, we don't care how long it
547  * will take to complete transfer since it will be interrupted
548  * by timer interrupt */
549  if (devpriv->timer_mode)
550  return DAS16_DMA_SIZE;
551 
552  /* otherwise, we are relying on dma terminal count interrupt,
553  * so pick a reasonable size */
554  if (cmd->convert_src == TRIG_TIMER)
555  freq = 1000000000 / cmd->convert_arg;
556  else if (cmd->scan_begin_src == TRIG_TIMER)
557  freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len;
558  /* return some default value */
559  else
560  freq = 0xffffffff;
561 
562  if (cmd->flags & TRIG_WAKE_EOS) {
563  size = sample_size * cmd->chanlist_len;
564  } else {
565  /* make buffer fill in no more than 1/3 second */
566  size = (freq / 3) * sample_size;
567  }
568 
569  /* set a minimum and maximum size allowed */
570  if (size > DAS16_DMA_SIZE)
572  else if (size < sample_size)
573  size = sample_size;
574 
575  if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
576  size = devpriv->adc_byte_count;
577 
578  return size;
579 }
580 
581 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
582  int rounding_flags)
583 {
584  i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
585  &(devpriv->divisor2), &ns,
586  rounding_flags & TRIG_ROUND_MASK);
587 
588  /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
589  i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
590  i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
591 
592  return ns;
593 }
594 
595 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
596 {
597  const struct das16_board *board = comedi_board(dev);
598  struct comedi_async *async = s->async;
599  struct comedi_cmd *cmd = &async->cmd;
600  unsigned int byte;
601  unsigned long flags;
602  int range;
603 
604  if (devpriv->dma_chan == 0 || (dev->irq == 0
605  && devpriv->timer_mode == 0)) {
606  comedi_error(dev,
607  "irq (or use of 'timer mode') dma required to "
608  "execute comedi_cmd");
609  return -1;
610  }
611  if (cmd->flags & TRIG_RT) {
612  comedi_error(dev, "isa dma transfers cannot be performed with "
613  "TRIG_RT, aborting");
614  return -1;
615  }
616 
617  devpriv->adc_byte_count =
618  cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
619 
620  /* disable conversions for das1600 mode */
621  if (board->size > 0x400)
623 
624  /* set scan limits */
625  byte = CR_CHAN(cmd->chanlist[0]);
626  byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
627  outb(byte, dev->iobase + DAS16_MUX);
628 
629  /* set gain (this is also burst rate register but according to
630  * computer boards manual, burst rate does nothing, even on
631  * keithley cards) */
632  if (board->ai_pg != das16_pg_none) {
633  range = CR_RANGE(cmd->chanlist[0]);
634  outb((das16_gainlists[board->ai_pg])[range],
635  dev->iobase + DAS16_GAIN);
636  }
637 
638  /* set counter mode and counts */
639  cmd->convert_arg =
640  das16_set_pacer(dev, cmd->convert_arg,
641  cmd->flags & TRIG_ROUND_MASK);
642  DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
643 
644  /* enable counters */
645  byte = 0;
646  /* Enable burst mode if appropriate. */
647  if (board->size > 0x400) {
648  if (cmd->convert_src == TRIG_NOW) {
650  /* set burst length */
651  byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
652  } else {
653  outb(0, dev->iobase + DAS1600_BURST);
654  }
655  }
656  outb(byte, dev->iobase + DAS16_PACER);
657 
658  /* set up dma transfer */
659  flags = claim_dma_lock();
660  disable_dma(devpriv->dma_chan);
661  /* clear flip-flop to make sure 2-byte registers for
662  * count and address get set correctly */
663  clear_dma_ff(devpriv->dma_chan);
664  devpriv->current_buffer = 0;
665  set_dma_addr(devpriv->dma_chan,
666  devpriv->dma_buffer_addr[devpriv->current_buffer]);
667  /* set appropriate size of transfer */
668  devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd);
669  set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
670  enable_dma(devpriv->dma_chan);
671  release_dma_lock(flags);
672 
673  /* set up interrupt */
674  if (devpriv->timer_mode) {
675  devpriv->timer_running = 1;
676  devpriv->timer.expires = jiffies + timer_period();
677  add_timer(&devpriv->timer);
678  devpriv->control_state &= ~DAS16_INTE;
679  } else {
680  /* clear interrupt bit */
681  outb(0x00, dev->iobase + DAS16_STATUS);
682  /* enable interrupts */
683  devpriv->control_state |= DAS16_INTE;
684  }
685  devpriv->control_state |= DMA_ENABLE;
686  devpriv->control_state &= ~PACING_MASK;
687  if (cmd->convert_src == TRIG_EXT)
688  devpriv->control_state |= EXT_PACER;
689  else
690  devpriv->control_state |= INT_PACER;
691  outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
692 
693  /* Enable conversions if using das1600 mode */
694  if (board->size > 0x400)
695  outb(0, dev->iobase + DAS1600_CONV);
696 
697 
698  return 0;
699 }
700 
701 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
702 {
703  const struct das16_board *board = comedi_board(dev);
704  unsigned long flags;
705 
706  spin_lock_irqsave(&dev->spinlock, flags);
707  /* disable interrupts, dma and pacer clocked conversions */
708  devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
709  outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
710  if (devpriv->dma_chan)
711  disable_dma(devpriv->dma_chan);
712 
713  /* disable SW timer */
714  if (devpriv->timer_mode && devpriv->timer_running) {
715  devpriv->timer_running = 0;
716  del_timer(&devpriv->timer);
717  }
718 
719  /* disable burst mode */
720  if (board->size > 0x400)
721  outb(0, dev->iobase + DAS1600_BURST);
722 
723 
724  spin_unlock_irqrestore(&dev->spinlock, flags);
725 
726  return 0;
727 }
728 
729 static void das16_reset(struct comedi_device *dev)
730 {
731  outb(0, dev->iobase + DAS16_STATUS);
732  outb(0, dev->iobase + DAS16_CONTROL);
733  outb(0, dev->iobase + DAS16_PACER);
734  outb(0, dev->iobase + DAS16_CNTR_CONTROL);
735 }
736 
737 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
738  struct comedi_insn *insn, unsigned int *data)
739 {
740  const struct das16_board *board = comedi_board(dev);
741  int i, n;
742  int range;
743  int chan;
744  int msb, lsb;
745 
746  /* disable interrupts and pacing */
747  devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
748  outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
749 
750  /* set multiplexer */
751  chan = CR_CHAN(insn->chanspec);
752  chan |= CR_CHAN(insn->chanspec) << 4;
753  outb(chan, dev->iobase + DAS16_MUX);
754 
755  /* set gain */
756  if (board->ai_pg != das16_pg_none) {
757  range = CR_RANGE(insn->chanspec);
758  outb((das16_gainlists[board->ai_pg])[range],
759  dev->iobase + DAS16_GAIN);
760  }
761 
762  for (n = 0; n < insn->n; n++) {
763  /* trigger conversion */
764  outb_p(0, dev->iobase + DAS16_TRIG);
765 
766  for (i = 0; i < DAS16_TIMEOUT; i++) {
767  if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
768  break;
769  }
770  if (i == DAS16_TIMEOUT) {
771  printk("das16: timeout\n");
772  return -ETIME;
773  }
774  msb = inb(dev->iobase + DAS16_AI_MSB);
775  lsb = inb(dev->iobase + DAS16_AI_LSB);
776  if (board->ai_nbits == 12)
777  data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
778  else
779  data[n] = lsb | (msb << 8);
780 
781  }
782 
783  return n;
784 }
785 
786 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
787  struct comedi_insn *insn, unsigned int *data)
788 {
789  unsigned int bits;
790 
791  bits = inb(dev->iobase + DAS16_DIO) & 0xf;
792  data[1] = bits;
793  data[0] = 0;
794 
795  return insn->n;
796 }
797 
798 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
799  struct comedi_insn *insn, unsigned int *data)
800 {
801  unsigned int wbits;
802 
803  /* only set bits that have been masked */
804  data[0] &= 0xf;
805  wbits = s->state;
806  /* zero bits that have been masked */
807  wbits &= ~data[0];
808  /* set masked bits */
809  wbits |= data[0] & data[1];
810  s->state = wbits;
811  data[1] = wbits;
812 
813  outb(s->state, dev->iobase + DAS16_DIO);
814 
815  return insn->n;
816 }
817 
818 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
819  struct comedi_insn *insn, unsigned int *data)
820 {
821  const struct das16_board *board = comedi_board(dev);
822  int i;
823  int lsb, msb;
824  int chan;
825 
826  chan = CR_CHAN(insn->chanspec);
827 
828  for (i = 0; i < insn->n; i++) {
829  if (board->ao_nbits == 12) {
830  lsb = (data[i] << 4) & 0xff;
831  msb = (data[i] >> 4) & 0xff;
832  } else {
833  lsb = data[i] & 0xff;
834  msb = (data[i] >> 8) & 0xff;
835  }
836  outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
837  outb(msb, dev->iobase + DAS16_AO_MSB(chan));
838  }
839 
840  return i;
841 }
842 
843 /* the pc104-das16jr (at least) has problems if the dma
844  transfer is interrupted in the middle of transferring
845  a 16 bit sample, so this function takes care to get
846  an even transfer count after disabling dma
847  channel.
848 */
849 static int disable_dma_on_even(struct comedi_device *dev)
850 {
851  int residue;
852  int i;
853  static const int disable_limit = 100;
854  static const int enable_timeout = 100;
855  disable_dma(devpriv->dma_chan);
856  residue = get_dma_residue(devpriv->dma_chan);
857  for (i = 0; i < disable_limit && (residue % 2); ++i) {
858  int j;
859  enable_dma(devpriv->dma_chan);
860  for (j = 0; j < enable_timeout; ++j) {
861  int new_residue;
862  udelay(2);
863  new_residue = get_dma_residue(devpriv->dma_chan);
864  if (new_residue != residue)
865  break;
866  }
867  disable_dma(devpriv->dma_chan);
868  residue = get_dma_residue(devpriv->dma_chan);
869  }
870  if (i == disable_limit) {
871  comedi_error(dev, "failed to get an even dma transfer, "
872  "could be trouble.");
873  }
874  return residue;
875 }
876 
877 static void das16_interrupt(struct comedi_device *dev)
878 {
879  const struct das16_board *board = comedi_board(dev);
880  unsigned long dma_flags, spin_flags;
881  struct comedi_subdevice *s = dev->read_subdev;
882  struct comedi_async *async;
883  struct comedi_cmd *cmd;
884  int num_bytes, residue;
885  int buffer_index;
886 
887  if (dev->attached == 0) {
888  comedi_error(dev, "premature interrupt");
889  return;
890  }
891  /* initialize async here to make sure it is not NULL */
892  async = s->async;
893  cmd = &async->cmd;
894 
895  if (devpriv->dma_chan == 0) {
896  comedi_error(dev, "interrupt with no dma channel?");
897  return;
898  }
899 
900  spin_lock_irqsave(&dev->spinlock, spin_flags);
901  if ((devpriv->control_state & DMA_ENABLE) == 0) {
902  spin_unlock_irqrestore(&dev->spinlock, spin_flags);
903  DEBUG_PRINT("interrupt while dma disabled?\n");
904  return;
905  }
906 
907  dma_flags = claim_dma_lock();
908  clear_dma_ff(devpriv->dma_chan);
909  residue = disable_dma_on_even(dev);
910 
911  /* figure out how many points to read */
912  if (residue > devpriv->dma_transfer_size) {
913  comedi_error(dev, "residue > transfer size!\n");
915  num_bytes = 0;
916  } else
917  num_bytes = devpriv->dma_transfer_size - residue;
918 
919  if (cmd->stop_src == TRIG_COUNT &&
920  num_bytes >= devpriv->adc_byte_count) {
921  num_bytes = devpriv->adc_byte_count;
922  async->events |= COMEDI_CB_EOA;
923  }
924 
925  buffer_index = devpriv->current_buffer;
926  devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
927  devpriv->adc_byte_count -= num_bytes;
928 
929  /* figure out how many bytes for next transfer */
930  if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
931  devpriv->dma_transfer_size > devpriv->adc_byte_count)
932  devpriv->dma_transfer_size = devpriv->adc_byte_count;
933 
934  /* re-enable dma */
935  if ((async->events & COMEDI_CB_EOA) == 0) {
936  set_dma_addr(devpriv->dma_chan,
937  devpriv->dma_buffer_addr[devpriv->current_buffer]);
938  set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
939  enable_dma(devpriv->dma_chan);
940  /* reenable conversions for das1600 mode, (stupid hardware) */
941  if (board->size > 0x400 && devpriv->timer_mode == 0)
942  outb(0x00, dev->iobase + DAS1600_CONV);
943 
944  }
945  release_dma_lock(dma_flags);
946 
947  spin_unlock_irqrestore(&dev->spinlock, spin_flags);
948 
950  devpriv->dma_buffer[buffer_index], num_bytes);
951 
952  cfc_handle_events(dev, s);
953 }
954 
955 static irqreturn_t das16_dma_interrupt(int irq, void *d)
956 {
957  int status;
958  struct comedi_device *dev = d;
959 
960  status = inb(dev->iobase + DAS16_STATUS);
961 
962  if ((status & DAS16_INT) == 0) {
963  DEBUG_PRINT("spurious interrupt\n");
964  return IRQ_NONE;
965  }
966 
967  /* clear interrupt */
968  outb(0x00, dev->iobase + DAS16_STATUS);
969  das16_interrupt(dev);
970  return IRQ_HANDLED;
971 }
972 
973 static void das16_timer_interrupt(unsigned long arg)
974 {
975  struct comedi_device *dev = (struct comedi_device *)arg;
976 
977  das16_interrupt(dev);
978 
979  if (devpriv->timer_running)
980  mod_timer(&devpriv->timer, jiffies + timer_period());
981 }
982 
983 static void reg_dump(struct comedi_device *dev)
984 {
985  DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
986  DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
987  DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
988  DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
989  DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
990  DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
991  DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
992  DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
993  inb(dev->iobase + DAS16_CNTR_CONTROL));
994  DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
995  DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
996  DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
997  DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
998  inb(dev->iobase + DAS1600_STATUS_B));
999 }
1000 
1001 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
1002 {
1003  const struct das16_board *board = comedi_board(dev);
1004  int status;
1005  int diobits;
1006 
1007  /* status is available on all boards */
1008 
1009  status = inb(dev->iobase + DAS16_STATUS);
1010 
1011  if ((status & UNIPOLAR))
1012  devpriv->ai_unipolar = 1;
1013  else
1014  devpriv->ai_unipolar = 0;
1015 
1016 
1017  if ((status & DAS16_MUXBIT))
1018  devpriv->ai_singleended = 1;
1019  else
1020  devpriv->ai_singleended = 0;
1021 
1022 
1023  /* diobits indicates boards */
1024 
1025  diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
1026 
1027  printk(KERN_INFO " id bits are 0x%02x\n", diobits);
1028  if (board->id != diobits) {
1029  printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
1030  board->id);
1031  }
1032 
1033  return 0;
1034 }
1035 
1036 static int das1600_mode_detect(struct comedi_device *dev)
1037 {
1038  int status = 0;
1039 
1040  status = inb(dev->iobase + DAS1600_STATUS_B);
1041 
1042  if (status & DAS1600_CLK_10MHZ) {
1043  devpriv->clockbase = 100;
1044  printk(KERN_INFO " 10MHz pacer clock\n");
1045  } else {
1046  devpriv->clockbase = 1000;
1047  printk(KERN_INFO " 1MHz pacer clock\n");
1048  }
1049 
1050  reg_dump(dev);
1051 
1052  return 0;
1053 }
1054 
1055 static void das16_ai_munge(struct comedi_device *dev,
1056  struct comedi_subdevice *s, void *array,
1057  unsigned int num_bytes,
1058  unsigned int start_chan_index)
1059 {
1060  const struct das16_board *board = comedi_board(dev);
1061  unsigned int i, num_samples = num_bytes / sizeof(short);
1062  short *data = array;
1063 
1064  for (i = 0; i < num_samples; i++) {
1065  data[i] = le16_to_cpu(data[i]);
1066  if (board->ai_nbits == 12)
1067  data[i] = (data[i] >> 4) & 0xfff;
1068 
1069  }
1070 }
1071 
1072 /*
1073  *
1074  * Options list:
1075  * 0 I/O base
1076  * 1 IRQ
1077  * 2 DMA
1078  * 3 Clock speed (in MHz)
1079  */
1080 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1081 {
1082  const struct das16_board *board = comedi_board(dev);
1083  struct comedi_subdevice *s;
1084  int ret;
1085  unsigned int irq;
1086  unsigned long iobase;
1087  unsigned int dma_chan;
1088  int timer_mode;
1089  unsigned long flags;
1090  struct comedi_krange *user_ai_range, *user_ao_range;
1091 
1092  iobase = it->options[0];
1093 #if 0
1094  irq = it->options[1];
1095  timer_mode = it->options[8];
1096 #endif
1097  /* always use time_mode since using irq can drop samples while
1098  * waiting for dma done interrupt (due to hardware limitations) */
1099  irq = 0;
1100  timer_mode = 1;
1101  if (timer_mode)
1102  irq = 0;
1103 
1104  printk(KERN_INFO "comedi%d: das16:", dev->minor);
1105 
1106  /* check that clock setting is valid */
1107  if (it->options[3]) {
1108  if (it->options[3] != 0 &&
1109  it->options[3] != 1 && it->options[3] != 10) {
1110  printk
1111  ("\n Invalid option. Master clock must be set "
1112  "to 1 or 10 (MHz)\n");
1113  return -EINVAL;
1114  }
1115  }
1116 
1117  ret = alloc_private(dev, sizeof(struct das16_private_struct));
1118  if (ret < 0)
1119  return ret;
1120 
1121  if (board->size < 0x400) {
1122  printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size);
1123  if (!request_region(iobase, board->size, "das16")) {
1124  printk(KERN_ERR " I/O port conflict\n");
1125  return -EIO;
1126  }
1127  } else {
1128  printk(KERN_INFO " 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
1129  iobase, iobase + 0x0f,
1130  iobase + 0x400,
1131  iobase + 0x400 + (board->size & 0x3ff));
1132  if (!request_region(iobase, 0x10, "das16")) {
1133  printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n",
1134  iobase, iobase + 0x0f);
1135  return -EIO;
1136  }
1137  if (!request_region(iobase + 0x400, board->size & 0x3ff,
1138  "das16")) {
1139  release_region(iobase, 0x10);
1140  printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n",
1141  iobase + 0x400,
1142  iobase + 0x400 + (board->size & 0x3ff));
1143  return -EIO;
1144  }
1145  }
1146 
1147  dev->iobase = iobase;
1148 
1149  /* probe id bits to make sure they are consistent */
1150  if (das16_probe(dev, it)) {
1151  printk(KERN_ERR " id bits do not match selected board, aborting\n");
1152  return -EINVAL;
1153  }
1154  dev->board_name = board->name;
1155 
1156  /* get master clock speed */
1157  if (board->size < 0x400) {
1158  if (it->options[3])
1159  devpriv->clockbase = 1000 / it->options[3];
1160  else
1161  devpriv->clockbase = 1000; /* 1 MHz default */
1162  } else {
1163  das1600_mode_detect(dev);
1164  }
1165 
1166  /* now for the irq */
1167  if (irq > 1 && irq < 8) {
1168  ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev);
1169 
1170  if (ret < 0)
1171  return ret;
1172  dev->irq = irq;
1173  printk(KERN_INFO " ( irq = %u )", irq);
1174  } else if (irq == 0) {
1175  printk(" ( no irq )");
1176  } else {
1177  printk(" invalid irq\n");
1178  return -EINVAL;
1179  }
1180 
1181  /* initialize dma */
1182  dma_chan = it->options[2];
1183  if (dma_chan == 1 || dma_chan == 3) {
1184  /* allocate dma buffers */
1185  int i;
1186  for (i = 0; i < 2; i++) {
1187  devpriv->dma_buffer[i] = pci_alloc_consistent(
1189  &devpriv->dma_buffer_addr[i]);
1190 
1191  if (devpriv->dma_buffer[i] == NULL)
1192  return -ENOMEM;
1193  }
1194  if (request_dma(dma_chan, "das16")) {
1195  printk(KERN_ERR " failed to allocate dma channel %i\n",
1196  dma_chan);
1197  return -EINVAL;
1198  }
1199  devpriv->dma_chan = dma_chan;
1200  flags = claim_dma_lock();
1201  disable_dma(devpriv->dma_chan);
1202  set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1203  release_dma_lock(flags);
1204  printk(KERN_INFO " ( dma = %u)\n", dma_chan);
1205  } else if (dma_chan == 0) {
1206  printk(KERN_INFO " ( no dma )\n");
1207  } else {
1208  printk(KERN_ERR " invalid dma channel\n");
1209  return -EINVAL;
1210  }
1211 
1212  /* get any user-defined input range */
1213  if (board->ai_pg == das16_pg_none &&
1214  (it->options[4] || it->options[5])) {
1215  /* allocate single-range range table */
1216  devpriv->user_ai_range_table =
1217  kmalloc(sizeof(struct comedi_lrange) +
1218  sizeof(struct comedi_krange), GFP_KERNEL);
1219  /* initialize ai range */
1220  devpriv->user_ai_range_table->length = 1;
1221  user_ai_range = devpriv->user_ai_range_table->range;
1222  user_ai_range->min = it->options[4];
1223  user_ai_range->max = it->options[5];
1224  user_ai_range->flags = UNIT_volt;
1225  }
1226  /* get any user-defined output range */
1227  if (it->options[6] || it->options[7]) {
1228  /* allocate single-range range table */
1229  devpriv->user_ao_range_table =
1230  kmalloc(sizeof(struct comedi_lrange) +
1231  sizeof(struct comedi_krange), GFP_KERNEL);
1232  /* initialize ao range */
1233  devpriv->user_ao_range_table->length = 1;
1234  user_ao_range = devpriv->user_ao_range_table->range;
1235  user_ao_range->min = it->options[6];
1236  user_ao_range->max = it->options[7];
1237  user_ao_range->flags = UNIT_volt;
1238  }
1239 
1240  if (timer_mode) {
1241  init_timer(&(devpriv->timer));
1242  devpriv->timer.function = das16_timer_interrupt;
1243  devpriv->timer.data = (unsigned long)dev;
1244  }
1245  devpriv->timer_mode = timer_mode ? 1 : 0;
1246 
1247  ret = comedi_alloc_subdevices(dev, 5);
1248  if (ret)
1249  return ret;
1250 
1251  s = &dev->subdevices[0];
1252  dev->read_subdev = s;
1253  /* ai */
1254  if (board->ai) {
1255  s->type = COMEDI_SUBD_AI;
1257  if (devpriv->ai_singleended) {
1258  s->n_chan = 16;
1259  s->len_chanlist = 16;
1260  s->subdev_flags |= SDF_GROUND;
1261  } else {
1262  s->n_chan = 8;
1263  s->len_chanlist = 8;
1264  s->subdev_flags |= SDF_DIFF;
1265  }
1266  s->maxdata = (1 << board->ai_nbits) - 1;
1267  if (devpriv->user_ai_range_table) { /* user defined ai range */
1268  s->range_table = devpriv->user_ai_range_table;
1269  } else if (devpriv->ai_unipolar) {
1270  s->range_table = das16_ai_uni_lranges[board->ai_pg];
1271  } else {
1272  s->range_table = das16_ai_bip_lranges[board->ai_pg];
1273  }
1274  s->insn_read = board->ai;
1275  s->do_cmdtest = das16_cmd_test;
1276  s->do_cmd = das16_cmd_exec;
1277  s->cancel = das16_cancel;
1278  s->munge = das16_ai_munge;
1279  } else {
1280  s->type = COMEDI_SUBD_UNUSED;
1281  }
1282 
1283  s = &dev->subdevices[1];
1284  /* ao */
1285  if (board->ao) {
1286  s->type = COMEDI_SUBD_AO;
1288  s->n_chan = 2;
1289  s->maxdata = (1 << board->ao_nbits) - 1;
1290  /* user defined ao range */
1291  if (devpriv->user_ao_range_table)
1292  s->range_table = devpriv->user_ao_range_table;
1293  else
1294  s->range_table = &range_unknown;
1295 
1296  s->insn_write = board->ao;
1297  } else {
1298  s->type = COMEDI_SUBD_UNUSED;
1299  }
1300 
1301  s = &dev->subdevices[2];
1302  /* di */
1303  if (board->di) {
1304  s->type = COMEDI_SUBD_DI;
1306  s->n_chan = 4;
1307  s->maxdata = 1;
1308  s->range_table = &range_digital;
1309  s->insn_bits = board->di;
1310  } else {
1311  s->type = COMEDI_SUBD_UNUSED;
1312  }
1313 
1314  s = &dev->subdevices[3];
1315  /* do */
1316  if (board->do_) {
1317  s->type = COMEDI_SUBD_DO;
1319  s->n_chan = 4;
1320  s->maxdata = 1;
1321  s->range_table = &range_digital;
1322  s->insn_bits = board->do_;
1323  /* initialize digital output lines */
1324  outb(s->state, dev->iobase + DAS16_DIO);
1325  } else {
1326  s->type = COMEDI_SUBD_UNUSED;
1327  }
1328 
1329  s = &dev->subdevices[4];
1330  /* 8255 */
1331  if (board->i8255_offset != 0) {
1332  subdev_8255_init(dev, s, NULL, (dev->iobase +
1333  board->i8255_offset));
1334  } else {
1335  s->type = COMEDI_SUBD_UNUSED;
1336  }
1337 
1338  das16_reset(dev);
1339  /* set the interrupt level */
1340  devpriv->control_state = DAS16_IRQ(dev->irq);
1341  outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1342 
1343  /* turn on das1600 mode if available */
1344  if (board->size > 0x400) {
1346  outb(0, dev->iobase + DAS1600_CONV);
1347  outb(0, dev->iobase + DAS1600_BURST);
1348  }
1349 
1350  return 0;
1351 }
1352 
1353 static void das16_detach(struct comedi_device *dev)
1354 {
1355  const struct das16_board *board = comedi_board(dev);
1356 
1357  das16_reset(dev);
1358  if (dev->subdevices)
1359  subdev_8255_cleanup(dev, &dev->subdevices[4]);
1360  if (devpriv) {
1361  int i;
1362  for (i = 0; i < 2; i++) {
1363  if (devpriv->dma_buffer[i])
1365  devpriv->dma_buffer[i],
1366  devpriv->
1367  dma_buffer_addr[i]);
1368  }
1369  if (devpriv->dma_chan)
1370  free_dma(devpriv->dma_chan);
1371  kfree(devpriv->user_ai_range_table);
1372  kfree(devpriv->user_ao_range_table);
1373  }
1374  if (dev->irq)
1375  free_irq(dev->irq, dev);
1376  if (dev->iobase) {
1377  if (board->size < 0x400) {
1378  release_region(dev->iobase, board->size);
1379  } else {
1380  release_region(dev->iobase, 0x10);
1381  release_region(dev->iobase + 0x400,
1382  board->size & 0x3ff);
1383  }
1384  }
1385 }
1386 
1387 static const struct das16_board das16_boards[] = {
1388  {
1389  .name = "das-16",
1390  .ai = das16_ai_rinsn,
1391  .ai_nbits = 12,
1392  .ai_speed = 15000,
1393  .ai_pg = das16_pg_none,
1394  .ao = das16_ao_winsn,
1395  .ao_nbits = 12,
1396  .di = das16_di_rbits,
1397  .do_ = das16_do_wbits,
1398  .i8255_offset = 0x10,
1399  .i8254_offset = 0x0c,
1400  .size = 0x14,
1401  .id = 0x00,
1402  }, {
1403  .name = "das-16g",
1404  .ai = das16_ai_rinsn,
1405  .ai_nbits = 12,
1406  .ai_speed = 15000,
1407  .ai_pg = das16_pg_none,
1408  .ao = das16_ao_winsn,
1409  .ao_nbits = 12,
1410  .di = das16_di_rbits,
1411  .do_ = das16_do_wbits,
1412  .i8255_offset = 0x10,
1413  .i8254_offset = 0x0c,
1414  .size = 0x14,
1415  .id = 0x00,
1416  }, {
1417  .name = "das-16f",
1418  .ai = das16_ai_rinsn,
1419  .ai_nbits = 12,
1420  .ai_speed = 8500,
1421  .ai_pg = das16_pg_none,
1422  .ao = das16_ao_winsn,
1423  .ao_nbits = 12,
1424  .di = das16_di_rbits,
1425  .do_ = das16_do_wbits,
1426  .i8255_offset = 0x10,
1427  .i8254_offset = 0x0c,
1428  .size = 0x14,
1429  .id = 0x00,
1430  }, {
1431  .name = "cio-das16",
1432  .ai = das16_ai_rinsn,
1433  .ai_nbits = 12,
1434  .ai_speed = 20000,
1435  .ai_pg = das16_pg_none,
1436  .ao = das16_ao_winsn,
1437  .ao_nbits = 12,
1438  .di = das16_di_rbits,
1439  .do_ = das16_do_wbits,
1440  .i8255_offset = 0x10,
1441  .i8254_offset = 0x0c,
1442  .size = 0x14,
1443  .id = 0x80,
1444  }, {
1445  .name = "cio-das16/f",
1446  .ai = das16_ai_rinsn,
1447  .ai_nbits = 12,
1448  .ai_speed = 10000,
1449  .ai_pg = das16_pg_none,
1450  .ao = das16_ao_winsn,
1451  .ao_nbits = 12,
1452  .di = das16_di_rbits,
1453  .do_ = das16_do_wbits,
1454  .i8255_offset = 0x10,
1455  .i8254_offset = 0x0c,
1456  .size = 0x14,
1457  .id = 0x80,
1458  }, {
1459  .name = "cio-das16/jr",
1460  .ai = das16_ai_rinsn,
1461  .ai_nbits = 12,
1462  .ai_speed = 7692,
1463  .ai_pg = das16_pg_16jr,
1464  .ao = NULL,
1465  .di = das16_di_rbits,
1466  .do_ = das16_do_wbits,
1467  .i8255_offset = 0,
1468  .i8254_offset = 0x0c,
1469  .size = 0x10,
1470  .id = 0x00,
1471  }, {
1472  .name = "pc104-das16jr",
1473  .ai = das16_ai_rinsn,
1474  .ai_nbits = 12,
1475  .ai_speed = 3300,
1476  .ai_pg = das16_pg_16jr,
1477  .ao = NULL,
1478  .di = das16_di_rbits,
1479  .do_ = das16_do_wbits,
1480  .i8255_offset = 0,
1481  .i8254_offset = 0x0c,
1482  .size = 0x10,
1483  .id = 0x00,
1484  }, {
1485  .name = "cio-das16jr/16",
1486  .ai = das16_ai_rinsn,
1487  .ai_nbits = 16,
1488  .ai_speed = 10000,
1489  .ai_pg = das16_pg_16jr_16,
1490  .ao = NULL,
1491  .di = das16_di_rbits,
1492  .do_ = das16_do_wbits,
1493  .i8255_offset = 0,
1494  .i8254_offset = 0x0c,
1495  .size = 0x10,
1496  .id = 0x00,
1497  }, {
1498  .name = "pc104-das16jr/16",
1499  .ai = das16_ai_rinsn,
1500  .ai_nbits = 16,
1501  .ai_speed = 10000,
1502  .ai_pg = das16_pg_16jr_16,
1503  .ao = NULL,
1504  .di = das16_di_rbits,
1505  .do_ = das16_do_wbits,
1506  .i8255_offset = 0,
1507  .i8254_offset = 0x0c,
1508  .size = 0x10,
1509  .id = 0x00,
1510  }, {
1511  .name = "das-1201",
1512  .ai = das16_ai_rinsn,
1513  .ai_nbits = 12,
1514  .ai_speed = 20000,
1515  .ai_pg = das16_pg_none,
1516  .ao = NULL,
1517  .di = das16_di_rbits,
1518  .do_ = das16_do_wbits,
1519  .i8255_offset = 0x400,
1520  .i8254_offset = 0x0c,
1521  .size = 0x408,
1522  .id = 0x20,
1523  }, {
1524  .name = "das-1202",
1525  .ai = das16_ai_rinsn,
1526  .ai_nbits = 12,
1527  .ai_speed = 10000,
1528  .ai_pg = das16_pg_none,
1529  .ao = NULL,
1530  .di = das16_di_rbits,
1531  .do_ = das16_do_wbits,
1532  .i8255_offset = 0x400,
1533  .i8254_offset = 0x0c,
1534  .size = 0x408,
1535  .id = 0x20,
1536  }, {
1537  .name = "das-1401",
1538  .ai = das16_ai_rinsn,
1539  .ai_nbits = 12,
1540  .ai_speed = 10000,
1541  .ai_pg = das16_pg_1601,
1542  .ao = NULL,
1543  .di = das16_di_rbits,
1544  .do_ = das16_do_wbits,
1545  .i8255_offset = 0x0,
1546  .i8254_offset = 0x0c,
1547  .size = 0x408,
1548  .id = 0xc0,
1549  }, {
1550  .name = "das-1402",
1551  .ai = das16_ai_rinsn,
1552  .ai_nbits = 12,
1553  .ai_speed = 10000,
1554  .ai_pg = das16_pg_1602,
1555  .ao = NULL,
1556  .di = das16_di_rbits,
1557  .do_ = das16_do_wbits,
1558  .i8255_offset = 0x0,
1559  .i8254_offset = 0x0c,
1560  .size = 0x408,
1561  .id = 0xc0,
1562  }, {
1563  .name = "das-1601",
1564  .ai = das16_ai_rinsn,
1565  .ai_nbits = 12,
1566  .ai_speed = 10000,
1567  .ai_pg = das16_pg_1601,
1568  .ao = das16_ao_winsn,
1569  .ao_nbits = 12,
1570  .di = das16_di_rbits,
1571  .do_ = das16_do_wbits,
1572  .i8255_offset = 0x400,
1573  .i8254_offset = 0x0c,
1574  .size = 0x408,
1575  .id = 0xc0,
1576  }, {
1577  .name = "das-1602",
1578  .ai = das16_ai_rinsn,
1579  .ai_nbits = 12,
1580  .ai_speed = 10000,
1581  .ai_pg = das16_pg_1602,
1582  .ao = das16_ao_winsn,
1583  .ao_nbits = 12,
1584  .di = das16_di_rbits,
1585  .do_ = das16_do_wbits,
1586  .i8255_offset = 0x400,
1587  .i8254_offset = 0x0c,
1588  .size = 0x408,
1589  .id = 0xc0,
1590  }, {
1591  .name = "cio-das1401/12",
1592  .ai = das16_ai_rinsn,
1593  .ai_nbits = 12,
1594  .ai_speed = 6250,
1595  .ai_pg = das16_pg_1601,
1596  .ao = NULL,
1597  .di = das16_di_rbits,
1598  .do_ = das16_do_wbits,
1599  .i8255_offset = 0,
1600  .i8254_offset = 0x0c,
1601  .size = 0x408,
1602  .id = 0xc0,
1603  }, {
1604  .name = "cio-das1402/12",
1605  .ai = das16_ai_rinsn,
1606  .ai_nbits = 12,
1607  .ai_speed = 6250,
1608  .ai_pg = das16_pg_1602,
1609  .ao = NULL,
1610  .di = das16_di_rbits,
1611  .do_ = das16_do_wbits,
1612  .i8255_offset = 0,
1613  .i8254_offset = 0x0c,
1614  .size = 0x408,
1615  .id = 0xc0,
1616  }, {
1617  .name = "cio-das1402/16",
1618  .ai = das16_ai_rinsn,
1619  .ai_nbits = 16,
1620  .ai_speed = 10000,
1621  .ai_pg = das16_pg_1602,
1622  .ao = NULL,
1623  .di = das16_di_rbits,
1624  .do_ = das16_do_wbits,
1625  .i8255_offset = 0,
1626  .i8254_offset = 0x0c,
1627  .size = 0x408,
1628  .id = 0xc0,
1629  }, {
1630  .name = "cio-das1601/12",
1631  .ai = das16_ai_rinsn,
1632  .ai_nbits = 12,
1633  .ai_speed = 6250,
1634  .ai_pg = das16_pg_1601,
1635  .ao = das16_ao_winsn,
1636  .ao_nbits = 12,
1637  .di = das16_di_rbits,
1638  .do_ = das16_do_wbits,
1639  .i8255_offset = 0x400,
1640  .i8254_offset = 0x0c,
1641  .size = 0x408,
1642  .id = 0xc0,
1643  }, {
1644  .name = "cio-das1602/12",
1645  .ai = das16_ai_rinsn,
1646  .ai_nbits = 12,
1647  .ai_speed = 10000,
1648  .ai_pg = das16_pg_1602,
1649  .ao = das16_ao_winsn,
1650  .ao_nbits = 12,
1651  .di = das16_di_rbits,
1652  .do_ = das16_do_wbits,
1653  .i8255_offset = 0x400,
1654  .i8254_offset = 0x0c,
1655  .size = 0x408,
1656  .id = 0xc0,
1657  }, {
1658  .name = "cio-das1602/16",
1659  .ai = das16_ai_rinsn,
1660  .ai_nbits = 16,
1661  .ai_speed = 10000,
1662  .ai_pg = das16_pg_1602,
1663  .ao = das16_ao_winsn,
1664  .ao_nbits = 12,
1665  .di = das16_di_rbits,
1666  .do_ = das16_do_wbits,
1667  .i8255_offset = 0x400,
1668  .i8254_offset = 0x0c,
1669  .size = 0x408,
1670  .id = 0xc0,
1671  }, {
1672  .name = "cio-das16/330",
1673  .ai = das16_ai_rinsn,
1674  .ai_nbits = 12,
1675  .ai_speed = 3030,
1676  .ai_pg = das16_pg_16jr,
1677  .ao = NULL,
1678  .di = das16_di_rbits,
1679  .do_ = das16_do_wbits,
1680  .i8255_offset = 0,
1681  .i8254_offset = 0x0c,
1682  .size = 0x14,
1683  .id = 0xf0,
1684  },
1685 };
1686 
1687 static struct comedi_driver das16_driver = {
1688  .driver_name = "das16",
1689  .module = THIS_MODULE,
1690  .attach = das16_attach,
1691  .detach = das16_detach,
1692  .board_name = &das16_boards[0].name,
1693  .num_names = ARRAY_SIZE(das16_boards),
1694  .offset = sizeof(das16_boards[0]),
1695 };
1696 module_comedi_driver(das16_driver);
1697 
1698 MODULE_AUTHOR("Comedi http://www.comedi.org");
1699 MODULE_DESCRIPTION("Comedi low-level driver");
1700 MODULE_LICENSE("GPL");