Staging: fix assorted typos all over the place
[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
78 static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
79                                                               RANGE(-10, 10),
80                                                               RANGE(-1, 1),
81                                                               RANGE(-0.1, 0.1),
82                                                               RANGE(-0.02, 0.02)
83                                                               }
84 };
85
86 struct dt3k_boardtype {
87
88         const char *name;
89         unsigned int device_id;
90         int adchan;
91         int adbits;
92         int ai_speed;
93         const struct comedi_lrange *adrange;
94         int dachan;
95         int dabits;
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         {
169         PCI_VENDOR_ID_DT, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
170         PCI_VENDOR_ID_DT, 0x0027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
171         PCI_VENDOR_ID_DT, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
172         PCI_VENDOR_ID_DT, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
173         PCI_VENDOR_ID_DT, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
174         PCI_VENDOR_ID_DT, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
175         PCI_VENDOR_ID_DT, 0x0026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
176         0}
177 };
178
179 MODULE_DEVICE_TABLE(pci, dt3k_pci_table);
180
181 #define DT3000_SIZE             (4*0x1000)
182
183 /* dual-ported RAM location definitions */
184
185 #define DPR_DAC_buffer          (4*0x000)
186 #define DPR_ADC_buffer          (4*0x800)
187 #define DPR_Command             (4*0xfd3)
188 #define DPR_SubSys              (4*0xfd3)
189 #define DPR_Encode              (4*0xfd4)
190 #define DPR_Params(a)           (4*(0xfd5+(a)))
191 #define DPR_Tick_Reg_Lo         (4*0xff5)
192 #define DPR_Tick_Reg_Hi         (4*0xff6)
193 #define DPR_DA_Buf_Front        (4*0xff7)
194 #define DPR_DA_Buf_Rear         (4*0xff8)
195 #define DPR_AD_Buf_Front        (4*0xff9)
196 #define DPR_AD_Buf_Rear         (4*0xffa)
197 #define DPR_Int_Mask            (4*0xffb)
198 #define DPR_Intr_Flag           (4*0xffc)
199 #define DPR_Response_Mbx        (4*0xffe)
200 #define DPR_Command_Mbx         (4*0xfff)
201
202 #define AI_FIFO_DEPTH   2003
203 #define AO_FIFO_DEPTH   2048
204
205 /* command list */
206
207 #define CMD_GETBRDINFO          0
208 #define CMD_CONFIG              1
209 #define CMD_GETCONFIG           2
210 #define CMD_START               3
211 #define CMD_STOP                4
212 #define CMD_READSINGLE          5
213 #define CMD_WRITESINGLE         6
214 #define CMD_CALCCLOCK           7
215 #define CMD_READEVENTS          8
216 #define CMD_WRITECTCTRL         16
217 #define CMD_READCTCTRL          17
218 #define CMD_WRITECT             18
219 #define CMD_READCT              19
220 #define CMD_WRITEDATA           32
221 #define CMD_READDATA            33
222 #define CMD_WRITEIO             34
223 #define CMD_READIO              35
224 #define CMD_WRITECODE           36
225 #define CMD_READCODE            37
226 #define CMD_EXECUTE             38
227 #define CMD_HALT                48
228
229 #define SUBS_AI         0
230 #define SUBS_AO         1
231 #define SUBS_DIN        2
232 #define SUBS_DOUT       3
233 #define SUBS_MEM        4
234 #define SUBS_CT         5
235
236 /* interrupt flags */
237 #define DT3000_CMDONE           0x80
238 #define DT3000_CTDONE           0x40
239 #define DT3000_DAHWERR          0x20
240 #define DT3000_DASWERR          0x10
241 #define DT3000_DAEMPTY          0x08
242 #define DT3000_ADHWERR          0x04
243 #define DT3000_ADSWERR          0x02
244 #define DT3000_ADFULL           0x01
245
246 #define DT3000_COMPLETION_MASK  0xff00
247 #define DT3000_COMMAND_MASK     0x00ff
248 #define DT3000_NOTPROCESSED     0x0000
249 #define DT3000_NOERROR          0x5500
250 #define DT3000_ERROR            0xaa00
251 #define DT3000_NOTSUPPORTED     0xff00
252
253 #define DT3000_EXTERNAL_CLOCK   1
254 #define DT3000_RISING_EDGE      2
255
256 #define TMODE_MASK              0x1c
257
258 #define DT3000_AD_TRIG_INTERNAL         (0<<2)
259 #define DT3000_AD_TRIG_EXTERNAL         (1<<2)
260 #define DT3000_AD_RETRIG_INTERNAL       (2<<2)
261 #define DT3000_AD_RETRIG_EXTERNAL       (3<<2)
262 #define DT3000_AD_EXTRETRIG             (4<<2)
263
264 #define DT3000_CHANNEL_MODE_SE          0
265 #define DT3000_CHANNEL_MODE_DI          1
266
267 struct dt3k_private {
268
269         struct pci_dev *pci_dev;
270         resource_size_t phys_addr;
271         void *io_addr;
272         unsigned int lock;
273         unsigned int ao_readback[2];
274         unsigned int ai_front;
275         unsigned int ai_rear;
276 };
277
278 #define devpriv ((struct dt3k_private *)dev->private)
279
280 static int dt3000_attach(struct comedi_device *dev,
281                          struct comedi_devconfig *it);
282 static int dt3000_detach(struct comedi_device *dev);
283 static struct comedi_driver driver_dt3000 = {
284         .driver_name = "dt3000",
285         .module = THIS_MODULE,
286         .attach = dt3000_attach,
287         .detach = dt3000_detach,
288 };
289
290 COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
291
292 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
293                                struct comedi_subdevice *s);
294 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
295                             unsigned int round_mode);
296 static int dt3k_ai_cancel(struct comedi_device *dev,
297                           struct comedi_subdevice *s);
298 #ifdef DEBUG
299 static void debug_intr_flags(unsigned int flags);
300 #endif
301
302 #define TIMEOUT 100
303
304 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
305 {
306         int i;
307         unsigned int status = 0;
308
309         writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
310
311         for (i = 0; i < TIMEOUT; i++) {
312                 status = readw(devpriv->io_addr + DPR_Command_Mbx);
313                 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
314                         break;
315                 udelay(1);
316         }
317         if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) {
318                 return 0;
319         }
320
321         printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
322
323         return -ETIME;
324 }
325
326 static unsigned int dt3k_readsingle(struct comedi_device *dev,
327                                     unsigned int subsys, unsigned int chan,
328                                     unsigned int gain)
329 {
330         writew(subsys, devpriv->io_addr + DPR_SubSys);
331
332         writew(chan, devpriv->io_addr + DPR_Params(0));
333         writew(gain, devpriv->io_addr + DPR_Params(1));
334
335         dt3k_send_cmd(dev, CMD_READSINGLE);
336
337         return readw(devpriv->io_addr + DPR_Params(2));
338 }
339
340 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
341                              unsigned int chan, unsigned int data)
342 {
343         writew(subsys, devpriv->io_addr + DPR_SubSys);
344
345         writew(chan, devpriv->io_addr + DPR_Params(0));
346         writew(0, devpriv->io_addr + DPR_Params(1));
347         writew(data, devpriv->io_addr + DPR_Params(2));
348
349         dt3k_send_cmd(dev, CMD_WRITESINGLE);
350 }
351
352 static int debug_n_ints = 0;
353
354 /* FIXME! Assumes shared interrupt is for this card. */
355 /* What's this debug_n_ints stuff? Obviously needs some work... */
356 static irqreturn_t dt3k_interrupt(int irq, void *d)
357 {
358         struct comedi_device *dev = d;
359         struct comedi_subdevice *s;
360         unsigned int status;
361
362         if (!dev->attached) {
363                 return IRQ_NONE;
364         }
365
366         s = dev->subdevices + 0;
367         status = readw(devpriv->io_addr + DPR_Intr_Flag);
368 #ifdef DEBUG
369         debug_intr_flags(status);
370 #endif
371
372         if (status & DT3000_ADFULL) {
373                 dt3k_ai_empty_fifo(dev, s);
374                 s->async->events |= COMEDI_CB_BLOCK;
375         }
376
377         if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) {
378                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
379         }
380
381         debug_n_ints++;
382         if (debug_n_ints >= 10) {
383                 dt3k_ai_cancel(dev, s);
384                 s->async->events |= COMEDI_CB_EOA;
385         }
386
387         comedi_event(dev, s);
388         return IRQ_HANDLED;
389 }
390
391 #ifdef DEBUG
392 static char *intr_flags[] = {
393         "AdFull", "AdSwError", "AdHwError", "DaEmpty",
394         "DaSwError", "DaHwError", "CtDone", "CmDone",
395 };
396
397 static void debug_intr_flags(unsigned int flags)
398 {
399         int i;
400         printk("dt3k: intr_flags:");
401         for (i = 0; i < 8; i++) {
402                 if (flags & (1 << i)) {
403                         printk(" %s", intr_flags[i]);
404                 }
405         }
406         printk("\n");
407 }
408 #endif
409
410 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
411                                struct comedi_subdevice *s)
412 {
413         int front;
414         int rear;
415         int count;
416         int i;
417         short data;
418
419         front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
420         count = front - devpriv->ai_front;
421         if (count < 0)
422                 count += AI_FIFO_DEPTH;
423
424         printk("reading %d samples\n", count);
425
426         rear = devpriv->ai_rear;
427
428         for (i = 0; i < count; i++) {
429                 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
430                 comedi_buf_put(s->async, data);
431                 rear++;
432                 if (rear >= AI_FIFO_DEPTH)
433                         rear = 0;
434         }
435
436         devpriv->ai_rear = rear;
437         writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
438 }
439
440 static int dt3k_ai_cmdtest(struct comedi_device *dev,
441                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
442 {
443         int err = 0;
444         int tmp;
445
446         /* step 1: make sure trigger sources are trivially valid */
447
448         tmp = cmd->start_src;
449         cmd->start_src &= TRIG_NOW;
450         if (!cmd->start_src || tmp != cmd->start_src)
451                 err++;
452
453         tmp = cmd->scan_begin_src;
454         cmd->scan_begin_src &= TRIG_TIMER;
455         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
456                 err++;
457
458         tmp = cmd->convert_src;
459         cmd->convert_src &= TRIG_TIMER;
460         if (!cmd->convert_src || tmp != cmd->convert_src)
461                 err++;
462
463         tmp = cmd->scan_end_src;
464         cmd->scan_end_src &= TRIG_COUNT;
465         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
466                 err++;
467
468         tmp = cmd->stop_src;
469         cmd->stop_src &= TRIG_COUNT;
470         if (!cmd->stop_src || tmp != cmd->stop_src)
471                 err++;
472
473         if (err)
474                 return 1;
475
476         /* step 2: make sure trigger sources are unique and mutually compatible */
477
478         if (err)
479                 return 2;
480
481         /* step 3: make sure arguments are trivially compatible */
482
483         if (cmd->start_arg != 0) {
484                 cmd->start_arg = 0;
485                 err++;
486         }
487
488         if (cmd->scan_begin_src == TRIG_TIMER) {
489                 if (cmd->scan_begin_arg < this_board->ai_speed) {
490                         cmd->scan_begin_arg = this_board->ai_speed;
491                         err++;
492                 }
493                 if (cmd->scan_begin_arg > 100 * 16 * 65535) {
494                         cmd->scan_begin_arg = 100 * 16 * 65535;
495                         err++;
496                 }
497         } else {
498                 /* not supported */
499         }
500         if (cmd->convert_src == TRIG_TIMER) {
501                 if (cmd->convert_arg < this_board->ai_speed) {
502                         cmd->convert_arg = this_board->ai_speed;
503                         err++;
504                 }
505                 if (cmd->convert_arg > 50 * 16 * 65535) {
506                         cmd->convert_arg = 50 * 16 * 65535;
507                         err++;
508                 }
509         } else {
510                 /* not supported */
511         }
512
513         if (cmd->scan_end_arg != cmd->chanlist_len) {
514                 cmd->scan_end_arg = cmd->chanlist_len;
515                 err++;
516         }
517         if (cmd->stop_src == TRIG_COUNT) {
518                 if (cmd->stop_arg > 0x00ffffff) {
519                         cmd->stop_arg = 0x00ffffff;
520                         err++;
521                 }
522         } else {
523                 /* TRIG_NONE */
524                 if (cmd->stop_arg != 0) {
525                         cmd->stop_arg = 0;
526                         err++;
527                 }
528         }
529
530         if (err)
531                 return 3;
532
533         /* step 4: fix up any arguments */
534
535         if (cmd->scan_begin_src == TRIG_TIMER) {
536                 tmp = cmd->scan_begin_arg;
537                 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
538                                  cmd->flags & TRIG_ROUND_MASK);
539                 if (tmp != cmd->scan_begin_arg)
540                         err++;
541         } else {
542                 /* not supported */
543         }
544         if (cmd->convert_src == TRIG_TIMER) {
545                 tmp = cmd->convert_arg;
546                 dt3k_ns_to_timer(50, &cmd->convert_arg,
547                                  cmd->flags & TRIG_ROUND_MASK);
548                 if (tmp != cmd->convert_arg)
549                         err++;
550                 if (cmd->scan_begin_src == TRIG_TIMER &&
551                     cmd->scan_begin_arg <
552                     cmd->convert_arg * cmd->scan_end_arg) {
553                         cmd->scan_begin_arg =
554                             cmd->convert_arg * cmd->scan_end_arg;
555                         err++;
556                 }
557         } else {
558                 /* not supported */
559         }
560
561         if (err)
562                 return 4;
563
564         return 0;
565 }
566
567 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
568                             unsigned int round_mode)
569 {
570         int divider, base, prescale;
571
572         /* This function needs improvment */
573         /* Don't know if divider==0 works. */
574
575         for (prescale = 0; prescale < 16; prescale++) {
576                 base = timer_base * (prescale + 1);
577                 switch (round_mode) {
578                 case TRIG_ROUND_NEAREST:
579                 default:
580                         divider = (*nanosec + base / 2) / base;
581                         break;
582                 case TRIG_ROUND_DOWN:
583                         divider = (*nanosec) / base;
584                         break;
585                 case TRIG_ROUND_UP:
586                         divider = (*nanosec) / base;
587                         break;
588                 }
589                 if (divider < 65536) {
590                         *nanosec = divider * base;
591                         return (prescale << 16) | (divider);
592                 }
593         }
594
595         prescale = 15;
596         base = timer_base * (1 << prescale);
597         divider = 65535;
598         *nanosec = divider * base;
599         return (prescale << 16) | (divider);
600 }
601
602 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
603 {
604         struct comedi_cmd *cmd = &s->async->cmd;
605         int i;
606         unsigned int chan, range, aref;
607         unsigned int divider;
608         unsigned int tscandiv;
609         int ret;
610         unsigned int mode;
611
612         printk("dt3k_ai_cmd:\n");
613         for (i = 0; i < cmd->chanlist_len; i++) {
614                 chan = CR_CHAN(cmd->chanlist[i]);
615                 range = CR_RANGE(cmd->chanlist[i]);
616
617                 writew((range << 6) | chan,
618                        devpriv->io_addr + DPR_ADC_buffer + i);
619         }
620         aref = CR_AREF(cmd->chanlist[0]);
621
622         writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
623         printk("param[0]=0x%04x\n", cmd->scan_end_arg);
624
625         if (cmd->convert_src == TRIG_TIMER) {
626                 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
627                                            cmd->flags & TRIG_ROUND_MASK);
628                 writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
629                 printk("param[1]=0x%04x\n", divider >> 16);
630                 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
631                 printk("param[2]=0x%04x\n", divider & 0xffff);
632         } else {
633                 /* not supported */
634         }
635
636         if (cmd->scan_begin_src == TRIG_TIMER) {
637                 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
638                                             cmd->flags & TRIG_ROUND_MASK);
639                 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
640                 printk("param[3]=0x%04x\n", tscandiv >> 16);
641                 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
642                 printk("param[4]=0x%04x\n", tscandiv & 0xffff);
643         } else {
644                 /* not supported */
645         }
646
647         mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
648         writew(mode, devpriv->io_addr + DPR_Params(5));
649         printk("param[5]=0x%04x\n", mode);
650         writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
651         printk("param[6]=0x%04x\n", aref == AREF_DIFF);
652
653         writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
654         printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
655
656         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
657         ret = dt3k_send_cmd(dev, CMD_CONFIG);
658
659         writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
660                devpriv->io_addr + DPR_Int_Mask);
661
662         debug_n_ints = 0;
663
664         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
665         ret = dt3k_send_cmd(dev, CMD_START);
666
667         return 0;
668 }
669
670 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
671 {
672         int ret;
673
674         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
675         ret = dt3k_send_cmd(dev, CMD_STOP);
676
677         writew(0, devpriv->io_addr + DPR_Int_Mask);
678
679         return 0;
680 }
681
682 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
683                         struct comedi_insn *insn, unsigned int *data)
684 {
685         int i;
686         unsigned int chan, gain, aref;
687
688         chan = CR_CHAN(insn->chanspec);
689         gain = CR_RANGE(insn->chanspec);
690         /* XXX docs don't explain how to select aref */
691         aref = CR_AREF(insn->chanspec);
692
693         for (i = 0; i < insn->n; i++) {
694                 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
695         }
696
697         return i;
698 }
699
700 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
701                         struct comedi_insn *insn, unsigned int *data)
702 {
703         int i;
704         unsigned int chan;
705
706         chan = CR_CHAN(insn->chanspec);
707         for (i = 0; i < insn->n; i++) {
708                 dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
709                 devpriv->ao_readback[chan] = data[i];
710         }
711
712         return i;
713 }
714
715 static int dt3k_ao_insn_read(struct comedi_device *dev,
716                              struct comedi_subdevice *s,
717                              struct comedi_insn *insn, unsigned int *data)
718 {
719         int i;
720         unsigned int chan;
721
722         chan = CR_CHAN(insn->chanspec);
723         for (i = 0; i < insn->n; i++) {
724                 data[i] = devpriv->ao_readback[chan];
725         }
726
727         return i;
728 }
729
730 static void dt3k_dio_config(struct comedi_device *dev, int bits)
731 {
732         /* XXX */
733         writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
734
735         writew(bits, devpriv->io_addr + DPR_Params(0));
736 #if 0
737         /* don't know */
738         writew(0, devpriv->io_addr + DPR_Params(1));
739         writew(0, devpriv->io_addr + DPR_Params(2));
740 #endif
741
742         dt3k_send_cmd(dev, CMD_CONFIG);
743 }
744
745 static int dt3k_dio_insn_config(struct comedi_device *dev,
746                                 struct comedi_subdevice *s,
747                                 struct comedi_insn *insn, unsigned int *data)
748 {
749         int mask;
750
751         mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
752
753         switch (data[0]) {
754         case INSN_CONFIG_DIO_OUTPUT:
755                 s->io_bits |= mask;
756                 break;
757         case INSN_CONFIG_DIO_INPUT:
758                 s->io_bits &= ~mask;
759                 break;
760         case INSN_CONFIG_DIO_QUERY:
761                 data[1] =
762                     (s->
763                      io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
764                     COMEDI_INPUT;
765                 return insn->n;
766                 break;
767         default:
768                 return -EINVAL;
769                 break;
770         }
771         mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
772         dt3k_dio_config(dev, mask);
773
774         return insn->n;
775 }
776
777 static int dt3k_dio_insn_bits(struct comedi_device *dev,
778                               struct comedi_subdevice *s,
779                               struct comedi_insn *insn, unsigned int *data)
780 {
781         if (insn->n != 2)
782                 return -EINVAL;
783
784         if (data[0]) {
785                 s->state &= ~data[0];
786                 s->state |= data[1] & data[0];
787                 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
788         }
789         data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
790
791         return 2;
792 }
793
794 static int dt3k_mem_insn_read(struct comedi_device *dev,
795                               struct comedi_subdevice *s,
796                               struct comedi_insn *insn, unsigned int *data)
797 {
798         unsigned int addr = CR_CHAN(insn->chanspec);
799         int i;
800
801         for (i = 0; i < insn->n; i++) {
802                 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
803                 writew(addr, devpriv->io_addr + DPR_Params(0));
804                 writew(1, devpriv->io_addr + DPR_Params(1));
805
806                 dt3k_send_cmd(dev, CMD_READCODE);
807
808                 data[i] = readw(devpriv->io_addr + DPR_Params(2));
809         }
810
811         return i;
812 }
813
814 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
815
816 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
817 {
818         struct comedi_subdevice *s;
819         int bus, slot;
820         int ret = 0;
821
822         printk("dt3000:");
823         bus = it->options[0];
824         slot = it->options[1];
825
826         ret = alloc_private(dev, sizeof(struct dt3k_private));
827         if (ret < 0)
828                 return ret;
829
830         ret = dt_pci_probe(dev, bus, slot);
831         if (ret < 0)
832                 return ret;
833         if (ret == 0) {
834                 printk(" no DT board found\n");
835                 return -ENODEV;
836         }
837
838         dev->board_name = this_board->name;
839
840         if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
841                         "dt3000", dev)) {
842                 printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
843                 return -EINVAL;
844         }
845         dev->irq = devpriv->pci_dev->irq;
846
847         ret = alloc_subdevices(dev, 4);
848         if (ret < 0)
849                 return ret;
850
851         s = dev->subdevices;
852         dev->read_subdev = s;
853
854         /* ai subdevice */
855         s->type = COMEDI_SUBD_AI;
856         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
857         s->n_chan = this_board->adchan;
858         s->insn_read = dt3k_ai_insn;
859         s->maxdata = (1 << this_board->adbits) - 1;
860         s->len_chanlist = 512;
861         s->range_table = &range_dt3000_ai;      /* XXX */
862         s->do_cmd = dt3k_ai_cmd;
863         s->do_cmdtest = dt3k_ai_cmdtest;
864         s->cancel = dt3k_ai_cancel;
865
866         s++;
867         /* ao subsystem */
868         s->type = COMEDI_SUBD_AO;
869         s->subdev_flags = SDF_WRITABLE;
870         s->n_chan = 2;
871         s->insn_read = dt3k_ao_insn_read;
872         s->insn_write = dt3k_ao_insn;
873         s->maxdata = (1 << this_board->dabits) - 1;
874         s->len_chanlist = 1;
875         s->range_table = &range_bipolar10;
876
877         s++;
878         /* dio subsystem */
879         s->type = COMEDI_SUBD_DIO;
880         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
881         s->n_chan = 8;
882         s->insn_config = dt3k_dio_insn_config;
883         s->insn_bits = dt3k_dio_insn_bits;
884         s->maxdata = 1;
885         s->len_chanlist = 8;
886         s->range_table = &range_digital;
887
888         s++;
889         /* mem subsystem */
890         s->type = COMEDI_SUBD_MEMORY;
891         s->subdev_flags = SDF_READABLE;
892         s->n_chan = 0x1000;
893         s->insn_read = dt3k_mem_insn_read;
894         s->maxdata = 0xff;
895         s->len_chanlist = 1;
896         s->range_table = &range_unknown;
897
898 #if 0
899         s++;
900         /* proc subsystem */
901         s->type = COMEDI_SUBD_PROC;
902 #endif
903
904         return 0;
905 }
906
907 static int dt3000_detach(struct comedi_device *dev)
908 {
909         if (dev->irq)
910                 free_irq(dev->irq, dev);
911
912         if (devpriv) {
913                 if (devpriv->pci_dev) {
914                         if (devpriv->phys_addr) {
915                                 comedi_pci_disable(devpriv->pci_dev);
916                         }
917                         pci_dev_put(devpriv->pci_dev);
918                 }
919                 if (devpriv->io_addr)
920                         iounmap(devpriv->io_addr);
921         }
922         /* XXX */
923
924         return 0;
925 }
926
927 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
928 static int setup_pci(struct comedi_device *dev);
929
930 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
931 {
932         int board;
933         int ret;
934         struct pci_dev *pcidev;
935
936         pcidev = NULL;
937         while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
938                 if ((bus == 0 && slot == 0) ||
939                     (pcidev->bus->number == bus &&
940                      PCI_SLOT(pcidev->devfn) == slot)) {
941                         break;
942                 }
943         }
944         devpriv->pci_dev = pcidev;
945
946         if (board >= 0)
947                 dev->board_ptr = dt3k_boardtypes + board;
948
949         if (!devpriv->pci_dev)
950                 return 0;
951
952         ret = setup_pci(dev);
953         if (ret < 0)
954                 return ret;
955
956         return 1;
957 }
958
959 static int setup_pci(struct comedi_device *dev)
960 {
961         resource_size_t addr;
962         int ret;
963
964         ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
965         if (ret < 0)
966                 return ret;
967
968         addr = pci_resource_start(devpriv->pci_dev, 0);
969         devpriv->phys_addr = addr;
970         devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE);
971         if (!devpriv->io_addr)
972                 return -ENOMEM;
973 #if DEBUG
974         printk("0x%08llx mapped to %p, ",
975                (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
976 #endif
977
978         return 0;
979 }
980
981 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
982 {
983         int i;
984
985         for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
986              from != NULL;
987              from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
988                 for (i = 0; i < n_dt3k_boards; i++) {
989                         if (from->device == dt3k_boardtypes[i].device_id) {
990                                 *board = i;
991                                 return from;
992                         }
993                 }
994                 printk
995                     ("unknown Data Translation PCI device found with device_id=0x%04x\n",
996                      from->device);
997         }
998         *board = -1;
999         return from;
1000 }