Version:  2.0.40 2.2.26 2.4.37 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19

Linux/drivers/staging/comedi/drivers/quatech_daqp_cs.c

  1 /*======================================================================
  2 
  3     comedi/drivers/quatech_daqp_cs.c
  4 
  5     Quatech DAQP PCMCIA data capture cards COMEDI client driver
  6     Copyright (C) 2000, 2003 Brent Baccala <baccala@freesoft.org>
  7     The DAQP interface code in this file is released into the public domain.
  8 
  9     COMEDI - Linux Control and Measurement Device Interface
 10     Copyright (C) 1998 David A. Schleef <ds@schleef.org>
 11     http://www.comedi.org/
 12 
 13     quatech_daqp_cs.c 1.10
 14 
 15     Documentation for the DAQP PCMCIA cards can be found on Quatech's site:
 16 
 17                 ftp://ftp.quatech.com/Manuals/daqp-208.pdf
 18 
 19     This manual is for both the DAQP-208 and the DAQP-308.
 20 
 21     What works:
 22 
 23         - A/D conversion
 24             - 8 channels
 25             - 4 gain ranges
 26             - ground ref or differential
 27             - single-shot and timed both supported
 28         - D/A conversion, single-shot
 29         - digital I/O
 30 
 31     What doesn't:
 32 
 33         - any kind of triggering - external or D/A channel 1
 34         - the card's optional expansion board
 35         - the card's timer (for anything other than A/D conversion)
 36         - D/A update modes other than immediate (i.e, timed)
 37         - fancier timing modes
 38         - setting card's FIFO buffer thresholds to anything but default
 39 
 40 ======================================================================*/
 41 
 42 /*
 43 Driver: quatech_daqp_cs
 44 Description: Quatech DAQP PCMCIA data capture cards
 45 Author: Brent Baccala <baccala@freesoft.org>
 46 Status: works
 47 Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 48 */
 49 
 50 #include <linux/module.h>
 51 #include "../comedidev.h"
 52 #include <linux/semaphore.h>
 53 
 54 #include <pcmcia/cistpl.h>
 55 #include <pcmcia/cisreg.h>
 56 #include <pcmcia/ds.h>
 57 
 58 #include <linux/completion.h>
 59 
 60 #include "comedi_fc.h"
 61 
 62 struct daqp_private {
 63         int stop;
 64 
 65         enum { semaphore, buffer } interrupt_mode;
 66 
 67         struct completion eos;
 68 };
 69 
 70 /* The DAQP communicates with the system through a 16 byte I/O window. */
 71 
 72 #define DAQP_FIFO_SIZE          4096
 73 
 74 #define DAQP_FIFO               0
 75 #define DAQP_SCANLIST           1
 76 #define DAQP_CONTROL            2
 77 #define DAQP_STATUS             2
 78 #define DAQP_DIGITAL_IO         3
 79 #define DAQP_PACER_LOW          4
 80 #define DAQP_PACER_MID          5
 81 #define DAQP_PACER_HIGH         6
 82 #define DAQP_COMMAND            7
 83 #define DAQP_DA                 8
 84 #define DAQP_TIMER              10
 85 #define DAQP_AUX                15
 86 
 87 #define DAQP_SCANLIST_DIFFERENTIAL      0x4000
 88 #define DAQP_SCANLIST_GAIN(x)           ((x)<<12)
 89 #define DAQP_SCANLIST_CHANNEL(x)        ((x)<<8)
 90 #define DAQP_SCANLIST_START             0x0080
 91 #define DAQP_SCANLIST_EXT_GAIN(x)       ((x)<<4)
 92 #define DAQP_SCANLIST_EXT_CHANNEL(x)    (x)
 93 
 94 #define DAQP_CONTROL_PACER_100kHz       0xc0
 95 #define DAQP_CONTROL_PACER_1MHz         0x80
 96 #define DAQP_CONTROL_PACER_5MHz         0x40
 97 #define DAQP_CONTROL_PACER_EXTERNAL     0x00
 98 #define DAQP_CONTORL_EXPANSION          0x20
 99 #define DAQP_CONTROL_EOS_INT_ENABLE     0x10
100 #define DAQP_CONTROL_FIFO_INT_ENABLE    0x08
101 #define DAQP_CONTROL_TRIGGER_ONESHOT    0x00
102 #define DAQP_CONTROL_TRIGGER_CONTINUOUS 0x04
103 #define DAQP_CONTROL_TRIGGER_INTERNAL   0x00
104 #define DAQP_CONTROL_TRIGGER_EXTERNAL   0x02
105 #define DAQP_CONTROL_TRIGGER_RISING     0x00
106 #define DAQP_CONTROL_TRIGGER_FALLING    0x01
107 
108 #define DAQP_STATUS_IDLE                0x80
109 #define DAQP_STATUS_RUNNING             0x40
110 #define DAQP_STATUS_EVENTS              0x38
111 #define DAQP_STATUS_DATA_LOST           0x20
112 #define DAQP_STATUS_END_OF_SCAN         0x10
113 #define DAQP_STATUS_FIFO_THRESHOLD      0x08
114 #define DAQP_STATUS_FIFO_FULL           0x04
115 #define DAQP_STATUS_FIFO_NEARFULL       0x02
116 #define DAQP_STATUS_FIFO_EMPTY          0x01
117 
118 #define DAQP_COMMAND_ARM                0x80
119 #define DAQP_COMMAND_RSTF               0x40
120 #define DAQP_COMMAND_RSTQ               0x20
121 #define DAQP_COMMAND_STOP               0x10
122 #define DAQP_COMMAND_LATCH              0x08
123 #define DAQP_COMMAND_100kHz             0x00
124 #define DAQP_COMMAND_50kHz              0x02
125 #define DAQP_COMMAND_25kHz              0x04
126 #define DAQP_COMMAND_FIFO_DATA          0x01
127 #define DAQP_COMMAND_FIFO_PROGRAM       0x00
128 
129 #define DAQP_AUX_TRIGGER_TTL            0x00
130 #define DAQP_AUX_TRIGGER_ANALOG         0x80
131 #define DAQP_AUX_TRIGGER_PRETRIGGER     0x40
132 #define DAQP_AUX_TIMER_INT_ENABLE       0x20
133 #define DAQP_AUX_TIMER_RELOAD           0x00
134 #define DAQP_AUX_TIMER_PAUSE            0x08
135 #define DAQP_AUX_TIMER_GO               0x10
136 #define DAQP_AUX_TIMER_GO_EXTERNAL      0x18
137 #define DAQP_AUX_TIMER_EXTERNAL_SRC     0x04
138 #define DAQP_AUX_TIMER_INTERNAL_SRC     0x00
139 #define DAQP_AUX_DA_DIRECT              0x00
140 #define DAQP_AUX_DA_OVERFLOW            0x01
141 #define DAQP_AUX_DA_EXTERNAL            0x02
142 #define DAQP_AUX_DA_PACER               0x03
143 
144 #define DAQP_AUX_RUNNING                0x80
145 #define DAQP_AUX_TRIGGERED              0x40
146 #define DAQP_AUX_DA_BUFFER              0x20
147 #define DAQP_AUX_TIMER_OVERFLOW         0x10
148 #define DAQP_AUX_CONVERSION             0x08
149 #define DAQP_AUX_DATA_LOST              0x04
150 #define DAQP_AUX_FIFO_NEARFULL          0x02
151 #define DAQP_AUX_FIFO_EMPTY             0x01
152 
153 static const struct comedi_lrange range_daqp_ai = {
154         4, {
155                 BIP_RANGE(10),
156                 BIP_RANGE(5),
157                 BIP_RANGE(2.5),
158                 BIP_RANGE(1.25)
159         }
160 };
161 
162 /* Cancel a running acquisition */
163 
164 static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
165 {
166         struct daqp_private *devpriv = dev->private;
167 
168         if (devpriv->stop)
169                 return -EIO;
170 
171         outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND);
172 
173         /* flush any linguring data in FIFO - superfluous here */
174         /* outb(DAQP_COMMAND_RSTF, dev->iobase+DAQP_COMMAND); */
175 
176         devpriv->interrupt_mode = semaphore;
177 
178         return 0;
179 }
180 
181 /* Interrupt handler
182  *
183  * Operates in one of two modes.  If devpriv->interrupt_mode is
184  * 'semaphore', just signal the devpriv->eos completion and return
185  * (one-shot mode).  Otherwise (continuous mode), read data in from
186  * the card, transfer it to the buffer provided by the higher-level
187  * comedi kernel module, and signal various comedi callback routines,
188  * which run pretty quick.
189  */
190 static enum irqreturn daqp_interrupt(int irq, void *dev_id)
191 {
192         struct comedi_device *dev = dev_id;
193         struct daqp_private *devpriv = dev->private;
194         struct comedi_subdevice *s = dev->read_subdev;
195         struct comedi_cmd *cmd = &s->async->cmd;
196         int loop_limit = 10000;
197         int status;
198 
199         if (!dev->attached)
200                 return IRQ_NONE;
201 
202         switch (devpriv->interrupt_mode) {
203         case semaphore:
204                 complete(&devpriv->eos);
205                 break;
206 
207         case buffer:
208                 while (!((status = inb(dev->iobase + DAQP_STATUS))
209                          & DAQP_STATUS_FIFO_EMPTY)) {
210                         unsigned short data;
211 
212                         if (status & DAQP_STATUS_DATA_LOST) {
213                                 s->async->events |=
214                                     COMEDI_CB_EOA | COMEDI_CB_OVERFLOW;
215                                 dev_warn(dev->class_dev, "data lost\n");
216                                 break;
217                         }
218 
219                         data = inb(dev->iobase + DAQP_FIFO);
220                         data |= inb(dev->iobase + DAQP_FIFO) << 8;
221                         data ^= 0x8000;
222 
223                         comedi_buf_write_samples(s, &data, 1);
224 
225                         /* If there's a limit, decrement it
226                          * and stop conversion if zero
227                          */
228 
229                         if (cmd->stop_src == TRIG_COUNT &&
230                             s->async->scans_done >= cmd->stop_arg) {
231                                 s->async->events |= COMEDI_CB_EOA;
232                                 break;
233                         }
234 
235                         if ((loop_limit--) <= 0)
236                                 break;
237                 }
238 
239                 if (loop_limit <= 0) {
240                         dev_warn(dev->class_dev,
241                                  "loop_limit reached in daqp_interrupt()\n");
242                         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
243                 }
244 
245                 comedi_handle_events(dev, s);
246         }
247         return IRQ_HANDLED;
248 }
249 
250 static void daqp_ai_set_one_scanlist_entry(struct comedi_device *dev,
251                                            unsigned int chanspec,
252                                            int start)
253 {
254         unsigned int chan = CR_CHAN(chanspec);
255         unsigned int range = CR_RANGE(chanspec);
256         unsigned int aref = CR_AREF(chanspec);
257         unsigned int val;
258 
259         val = DAQP_SCANLIST_CHANNEL(chan) | DAQP_SCANLIST_GAIN(range);
260 
261         if (aref == AREF_DIFF)
262                 val |= DAQP_SCANLIST_DIFFERENTIAL;
263 
264         if (start)
265                 val |= DAQP_SCANLIST_START;
266 
267         outb(val & 0xff, dev->iobase + DAQP_SCANLIST);
268         outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST);
269 }
270 
271 /* One-shot analog data acquisition routine */
272 
273 static int daqp_ai_insn_read(struct comedi_device *dev,
274                              struct comedi_subdevice *s,
275                              struct comedi_insn *insn, unsigned int *data)
276 {
277         struct daqp_private *devpriv = dev->private;
278         int i;
279         int v;
280         int counter = 10000;
281 
282         if (devpriv->stop)
283                 return -EIO;
284 
285         /* Stop any running conversion */
286         daqp_ai_cancel(dev, s);
287 
288         outb(0, dev->iobase + DAQP_AUX);
289 
290         /* Reset scan list queue */
291         outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND);
292 
293         /* Program one scan list entry */
294         daqp_ai_set_one_scanlist_entry(dev, insn->chanspec, 1);
295 
296         /* Reset data FIFO (see page 28 of DAQP User's Manual) */
297 
298         outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND);
299 
300         /* Set trigger */
301 
302         v = DAQP_CONTROL_TRIGGER_ONESHOT | DAQP_CONTROL_TRIGGER_INTERNAL
303             | DAQP_CONTROL_PACER_100kHz | DAQP_CONTROL_EOS_INT_ENABLE;
304 
305         outb(v, dev->iobase + DAQP_CONTROL);
306 
307         /* Reset any pending interrupts (my card has a tendency to require
308          * require multiple reads on the status register to achieve this)
309          */
310 
311         while (--counter
312                && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS))
313                 ;
314         if (!counter) {
315                 dev_err(dev->class_dev,
316                         "couldn't clear interrupts in status register\n");
317                 return -1;
318         }
319 
320         init_completion(&devpriv->eos);
321         devpriv->interrupt_mode = semaphore;
322 
323         for (i = 0; i < insn->n; i++) {
324 
325                 /* Start conversion */
326                 outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA,
327                      dev->iobase + DAQP_COMMAND);
328 
329                 /* Wait for interrupt service routine to unblock completion */
330                 /* Maybe could use a timeout here, but it's interruptible */
331                 if (wait_for_completion_interruptible(&devpriv->eos))
332                         return -EINTR;
333 
334                 data[i] = inb(dev->iobase + DAQP_FIFO);
335                 data[i] |= inb(dev->iobase + DAQP_FIFO) << 8;
336                 data[i] ^= 0x8000;
337         }
338 
339         return insn->n;
340 }
341 
342 /* This function converts ns nanoseconds to a counter value suitable
343  * for programming the device.  We always use the DAQP's 5 MHz clock,
344  * which with its 24-bit counter, allows values up to 84 seconds.
345  * Also, the function adjusts ns so that it cooresponds to the actual
346  * time that the device will use.
347  */
348 
349 static int daqp_ns_to_timer(unsigned int *ns, unsigned int flags)
350 {
351         int timer;
352 
353         timer = *ns / 200;
354         *ns = timer * 200;
355 
356         return timer;
357 }
358 
359 /* cmdtest tests a particular command to see if it is valid.
360  * Using the cmdtest ioctl, a user can create a valid cmd
361  * and then have it executed by the cmd ioctl.
362  *
363  * cmdtest returns 1,2,3,4 or 0, depending on which tests
364  * the command passes.
365  */
366 
367 static int daqp_ai_cmdtest(struct comedi_device *dev,
368                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
369 {
370         int err = 0;
371         unsigned int arg;
372 
373         /* Step 1 : check if triggers are trivially valid */
374 
375         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
376         err |= cfc_check_trigger_src(&cmd->scan_begin_src,
377                                         TRIG_TIMER | TRIG_FOLLOW);
378         err |= cfc_check_trigger_src(&cmd->convert_src,
379                                         TRIG_TIMER | TRIG_NOW);
380         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
381         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
382 
383         if (err)
384                 return 1;
385 
386         /* Step 2a : make sure trigger sources are unique */
387 
388         err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
389         err |= cfc_check_trigger_is_unique(cmd->convert_src);
390         err |= cfc_check_trigger_is_unique(cmd->stop_src);
391 
392         /* Step 2b : and mutually compatible */
393 
394         if (err)
395                 return 2;
396 
397         /* Step 3: check if arguments are trivially valid */
398 
399         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
400 
401 #define MAX_SPEED       10000   /* 100 kHz - in nanoseconds */
402 
403         if (cmd->scan_begin_src == TRIG_TIMER)
404                 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
405                                                  MAX_SPEED);
406 
407         /* If both scan_begin and convert are both timer values, the only
408          * way that can make sense is if the scan time is the number of
409          * conversions times the convert time
410          */
411 
412         if (cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER
413             && cmd->scan_begin_arg != cmd->convert_arg * cmd->scan_end_arg) {
414                 err |= -EINVAL;
415         }
416 
417         if (cmd->convert_src == TRIG_TIMER)
418                 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
419 
420         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
421 
422         if (cmd->stop_src == TRIG_COUNT)
423                 err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
424         else    /* TRIG_NONE */
425                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
426 
427         if (err)
428                 return 3;
429 
430         /* step 4: fix up any arguments */
431 
432         if (cmd->scan_begin_src == TRIG_TIMER) {
433                 arg = cmd->scan_begin_arg;
434                 daqp_ns_to_timer(&arg, cmd->flags);
435                 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
436         }
437 
438         if (cmd->convert_src == TRIG_TIMER) {
439                 arg = cmd->convert_arg;
440                 daqp_ns_to_timer(&arg, cmd->flags);
441                 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
442         }
443 
444         if (err)
445                 return 4;
446 
447         return 0;
448 }
449 
450 static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
451 {
452         struct daqp_private *devpriv = dev->private;
453         struct comedi_cmd *cmd = &s->async->cmd;
454         int counter;
455         int scanlist_start_on_every_entry;
456         int threshold;
457 
458         int i;
459         int v;
460 
461         if (devpriv->stop)
462                 return -EIO;
463 
464         /* Stop any running conversion */
465         daqp_ai_cancel(dev, s);
466 
467         outb(0, dev->iobase + DAQP_AUX);
468 
469         /* Reset scan list queue */
470         outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND);
471 
472         /* Program pacer clock
473          *
474          * There's two modes we can operate in.  If convert_src is
475          * TRIG_TIMER, then convert_arg specifies the time between
476          * each conversion, so we program the pacer clock to that
477          * frequency and set the SCANLIST_START bit on every scanlist
478          * entry.  Otherwise, convert_src is TRIG_NOW, which means
479          * we want the fastest possible conversions, scan_begin_src
480          * is TRIG_TIMER, and scan_begin_arg specifies the time between
481          * each scan, so we program the pacer clock to this frequency
482          * and only set the SCANLIST_START bit on the first entry.
483          */
484 
485         if (cmd->convert_src == TRIG_TIMER) {
486                 counter = daqp_ns_to_timer(&cmd->convert_arg, cmd->flags);
487                 outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW);
488                 outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID);
489                 outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH);
490                 scanlist_start_on_every_entry = 1;
491         } else {
492                 counter = daqp_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
493                 outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW);
494                 outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID);
495                 outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH);
496                 scanlist_start_on_every_entry = 0;
497         }
498 
499         /* Program scan list */
500         for (i = 0; i < cmd->chanlist_len; i++) {
501                 int start = (i == 0 || scanlist_start_on_every_entry);
502 
503                 daqp_ai_set_one_scanlist_entry(dev, cmd->chanlist[i], start);
504         }
505 
506         /* Now it's time to program the FIFO threshold, basically the
507          * number of samples the card will buffer before it interrupts
508          * the CPU.
509          *
510          * If we don't have a stop count, then use half the size of
511          * the FIFO (the manufacturer's recommendation).  Consider
512          * that the FIFO can hold 2K samples (4K bytes).  With the
513          * threshold set at half the FIFO size, we have a margin of
514          * error of 1024 samples.  At the chip's maximum sample rate
515          * of 100,000 Hz, the CPU would have to delay interrupt
516          * service for a full 10 milliseconds in order to lose data
517          * here (as opposed to higher up in the kernel).  I've never
518          * seen it happen.  However, for slow sample rates it may
519          * buffer too much data and introduce too much delay for the
520          * user application.
521          *
522          * If we have a stop count, then things get more interesting.
523          * If the stop count is less than the FIFO size (actually
524          * three-quarters of the FIFO size - see below), we just use
525          * the stop count itself as the threshold, the card interrupts
526          * us when that many samples have been taken, and we kill the
527          * acquisition at that point and are done.  If the stop count
528          * is larger than that, then we divide it by 2 until it's less
529          * than three quarters of the FIFO size (we always leave the
530          * top quarter of the FIFO as protection against sluggish CPU
531          * interrupt response) and use that as the threshold.  So, if
532          * the stop count is 4000 samples, we divide by two twice to
533          * get 1000 samples, use that as the threshold, take four
534          * interrupts to get our 4000 samples and are done.
535          *
536          * The algorithm could be more clever.  For example, if 81000
537          * samples are requested, we could set the threshold to 1500
538          * samples and take 54 interrupts to get 81000.  But 54 isn't
539          * a power of two, so this algorithm won't find that option.
540          * Instead, it'll set the threshold at 1266 and take 64
541          * interrupts to get 81024 samples, of which the last 24 will
542          * be discarded... but we won't get the last interrupt until
543          * they've been collected.  To find the first option, the
544          * computer could look at the prime decomposition of the
545          * sample count (81000 = 3^4 * 5^3 * 2^3) and factor it into a
546          * threshold (1500 = 3 * 5^3 * 2^2) and an interrupt count (54
547          * = 3^3 * 2).  Hmmm... a one-line while loop or prime
548          * decomposition of integers... I'll leave it the way it is.
549          *
550          * I'll also note a mini-race condition before ignoring it in
551          * the code.  Let's say we're taking 4000 samples, as before.
552          * After 1000 samples, we get an interrupt.  But before that
553          * interrupt is completely serviced, another sample is taken
554          * and loaded into the FIFO.  Since the interrupt handler
555          * empties the FIFO before returning, it will read 1001 samples.
556          * If that happens four times, we'll end up taking 4004 samples,
557          * not 4000.  The interrupt handler will discard the extra four
558          * samples (by halting the acquisition with four samples still
559          * in the FIFO), but we will have to wait for them.
560          *
561          * In short, this code works pretty well, but for either of
562          * the two reasons noted, might end up waiting for a few more
563          * samples than actually requested.  Shouldn't make too much
564          * of a difference.
565          */
566 
567         /* Save away the number of conversions we should perform, and
568          * compute the FIFO threshold (in bytes, not samples - that's
569          * why we multiple devpriv->count by 2 = sizeof(sample))
570          */
571 
572         if (cmd->stop_src == TRIG_COUNT) {
573                 unsigned long long nsamples;
574                 unsigned long long nbytes;
575 
576                 nsamples = (unsigned long long)cmd->stop_arg *
577                            cmd->scan_end_arg;
578                 nbytes = nsamples * comedi_bytes_per_sample(s);
579                 while (nbytes > DAQP_FIFO_SIZE * 3 / 4)
580                         nbytes /= 2;
581                 threshold = nbytes;
582         } else {
583                 threshold = DAQP_FIFO_SIZE / 2;
584         }
585 
586         /* Reset data FIFO (see page 28 of DAQP User's Manual) */
587 
588         outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND);
589 
590         /* Set FIFO threshold.  First two bytes are near-empty
591          * threshold, which is unused; next two bytes are near-full
592          * threshold.  We computed the number of bytes we want in the
593          * FIFO when the interrupt is generated, what the card wants
594          * is actually the number of available bytes left in the FIFO
595          * when the interrupt is to happen.
596          */
597 
598         outb(0x00, dev->iobase + DAQP_FIFO);
599         outb(0x00, dev->iobase + DAQP_FIFO);
600 
601         outb((DAQP_FIFO_SIZE - threshold) & 0xff, dev->iobase + DAQP_FIFO);
602         outb((DAQP_FIFO_SIZE - threshold) >> 8, dev->iobase + DAQP_FIFO);
603 
604         /* Set trigger */
605 
606         v = DAQP_CONTROL_TRIGGER_CONTINUOUS | DAQP_CONTROL_TRIGGER_INTERNAL
607             | DAQP_CONTROL_PACER_5MHz | DAQP_CONTROL_FIFO_INT_ENABLE;
608 
609         outb(v, dev->iobase + DAQP_CONTROL);
610 
611         /* Reset any pending interrupts (my card has a tendency to require
612          * require multiple reads on the status register to achieve this)
613          */
614         counter = 100;
615         while (--counter
616                && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS))
617                 ;
618         if (!counter) {
619                 dev_err(dev->class_dev,
620                         "couldn't clear interrupts in status register\n");
621                 return -1;
622         }
623 
624         devpriv->interrupt_mode = buffer;
625 
626         /* Start conversion */
627         outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA,
628              dev->iobase + DAQP_COMMAND);
629 
630         return 0;
631 }
632 
633 static int daqp_ao_insn_write(struct comedi_device *dev,
634                               struct comedi_subdevice *s,
635                               struct comedi_insn *insn,
636                               unsigned int *data)
637 {
638         struct daqp_private *devpriv = dev->private;
639         unsigned int chan = CR_CHAN(insn->chanspec);
640         int i;
641 
642         if (devpriv->stop)
643                 return -EIO;
644 
645         /* Make sure D/A update mode is direct update */
646         outb(0, dev->iobase + DAQP_AUX);
647 
648         for (i = 0; i > insn->n; i++) {
649                 unsigned val = data[i];
650 
651                 s->readback[chan] = val;
652 
653                 val &= 0x0fff;
654                 val ^= 0x0800;          /* Flip the sign */
655                 val |= (chan << 12);
656 
657                 outw(val, dev->iobase + DAQP_DA);
658         }
659 
660         return insn->n;
661 }
662 
663 static int daqp_di_insn_bits(struct comedi_device *dev,
664                              struct comedi_subdevice *s,
665                              struct comedi_insn *insn,
666                              unsigned int *data)
667 {
668         struct daqp_private *devpriv = dev->private;
669 
670         if (devpriv->stop)
671                 return -EIO;
672 
673         data[0] = inb(dev->iobase + DAQP_DIGITAL_IO);
674 
675         return insn->n;
676 }
677 
678 static int daqp_do_insn_bits(struct comedi_device *dev,
679                              struct comedi_subdevice *s,
680                              struct comedi_insn *insn,
681                              unsigned int *data)
682 {
683         struct daqp_private *devpriv = dev->private;
684 
685         if (devpriv->stop)
686                 return -EIO;
687 
688         if (comedi_dio_update_state(s, data))
689                 outb(s->state, dev->iobase + DAQP_DIGITAL_IO);
690 
691         data[1] = s->state;
692 
693         return insn->n;
694 }
695 
696 static int daqp_auto_attach(struct comedi_device *dev,
697                             unsigned long context)
698 {
699         struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
700         struct daqp_private *devpriv;
701         struct comedi_subdevice *s;
702         int ret;
703 
704         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
705         if (!devpriv)
706                 return -ENOMEM;
707 
708         link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
709         ret = comedi_pcmcia_enable(dev, NULL);
710         if (ret)
711                 return ret;
712         dev->iobase = link->resource[0]->start;
713 
714         link->priv = dev;
715         ret = pcmcia_request_irq(link, daqp_interrupt);
716         if (ret)
717                 return ret;
718 
719         ret = comedi_alloc_subdevices(dev, 4);
720         if (ret)
721                 return ret;
722 
723         s = &dev->subdevices[0];
724         dev->read_subdev = s;
725         s->type         = COMEDI_SUBD_AI;
726         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
727         s->n_chan       = 8;
728         s->len_chanlist = 2048;
729         s->maxdata      = 0xffff;
730         s->range_table  = &range_daqp_ai;
731         s->insn_read    = daqp_ai_insn_read;
732         s->do_cmdtest   = daqp_ai_cmdtest;
733         s->do_cmd       = daqp_ai_cmd;
734         s->cancel       = daqp_ai_cancel;
735 
736         s = &dev->subdevices[1];
737         s->type         = COMEDI_SUBD_AO;
738         s->subdev_flags = SDF_WRITABLE;
739         s->n_chan       = 2;
740         s->maxdata      = 0x0fff;
741         s->range_table  = &range_bipolar5;
742         s->insn_write   = daqp_ao_insn_write;
743 
744         ret = comedi_alloc_subdev_readback(s);
745         if (ret)
746                 return ret;
747 
748         s = &dev->subdevices[2];
749         s->type         = COMEDI_SUBD_DI;
750         s->subdev_flags = SDF_READABLE;
751         s->n_chan       = 1;
752         s->maxdata      = 1;
753         s->insn_bits    = daqp_di_insn_bits;
754 
755         s = &dev->subdevices[3];
756         s->type         = COMEDI_SUBD_DO;
757         s->subdev_flags = SDF_WRITABLE;
758         s->n_chan       = 1;
759         s->maxdata      = 1;
760         s->insn_bits    = daqp_do_insn_bits;
761 
762         return 0;
763 }
764 
765 static struct comedi_driver driver_daqp = {
766         .driver_name    = "quatech_daqp_cs",
767         .module         = THIS_MODULE,
768         .auto_attach    = daqp_auto_attach,
769         .detach         = comedi_pcmcia_disable,
770 };
771 
772 static int daqp_cs_suspend(struct pcmcia_device *link)
773 {
774         struct comedi_device *dev = link->priv;
775         struct daqp_private *devpriv = dev ? dev->private : NULL;
776 
777         /* Mark the device as stopped, to block IO until later */
778         if (devpriv)
779                 devpriv->stop = 1;
780 
781         return 0;
782 }
783 
784 static int daqp_cs_resume(struct pcmcia_device *link)
785 {
786         struct comedi_device *dev = link->priv;
787         struct daqp_private *devpriv = dev ? dev->private : NULL;
788 
789         if (devpriv)
790                 devpriv->stop = 0;
791 
792         return 0;
793 }
794 
795 static int daqp_cs_attach(struct pcmcia_device *link)
796 {
797         return comedi_pcmcia_auto_config(link, &driver_daqp);
798 }
799 
800 static const struct pcmcia_device_id daqp_cs_id_table[] = {
801         PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0027),
802         PCMCIA_DEVICE_NULL
803 };
804 MODULE_DEVICE_TABLE(pcmcia, daqp_cs_id_table);
805 
806 static struct pcmcia_driver daqp_cs_driver = {
807         .name           = "quatech_daqp_cs",
808         .owner          = THIS_MODULE,
809         .id_table       = daqp_cs_id_table,
810         .probe          = daqp_cs_attach,
811         .remove         = comedi_pcmcia_auto_unconfig,
812         .suspend        = daqp_cs_suspend,
813         .resume         = daqp_cs_resume,
814 };
815 module_comedi_pcmcia_driver(driver_daqp, daqp_cs_driver);
816 
817 MODULE_DESCRIPTION("Comedi driver for Quatech DAQP PCMCIA data capture cards");
818 MODULE_AUTHOR("Brent Baccala <baccala@freesoft.org>");
819 MODULE_LICENSE("GPL");
820 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us