Staging: comedi: jr3_pci.c: add required includes
[safe/jmp/linux-2.6] / drivers / staging / comedi / drivers / dt3000.c
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 }