Version:  2.0.40 2.2.26 2.4.37 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 4.0 4.1

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

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