Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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