Added some ack'ing of b interrupts, and do acks before handling
[comedi.git] / comedi / drivers / cb_pcimdas.c
1 /*
2     comedi/drivers/cb_pcimdas.c
3     Comedi driver for Computer Boards PCIM-DAS1602/16
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2000 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: cb_pcimdas.o
25 Description: Measurement Computing PCI Migration series boards
26 Devices: [Computer Boards] PCIM-DAS1602/16 (cb_pcimdas)
27 Author: Richard Bytheway
28 Updated: Wed, 13 Nov 2002 12:34:56 +0000
29 Status: experimental
30
31 Written to support the PCIM-DAS1602/16 on a 2.4 series kernel.
32
33 Configuration Options:
34     [0] - PCI bus number
35     [1] - PCI slot number
36
37 Developed from cb_pcidas and skel by Richard Bytheway (mocelet@sucs.org). 
38 Only supports DIO, AO and simple AI in it's present form.
39 No interrupts, multi channel or FIFO AI, although the card looks like it could support this.
40 See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more details.
41 */
42
43 #include <linux/comedidev.h>
44
45 #include <linux/pci.h>
46 #include <linux/delay.h>
47
48 #include "plx9052.h"
49 #include "8255.h"
50
51 //#define CBPCIMDAS_DEBUG
52 #undef CBPCIMDAS_DEBUG
53
54 /* Registers for the PCIM-DAS1602/16 */
55
56 // sizes of io regions (bytes)
57 #define BADR0_SIZE 2  //??
58 #define BADR1_SIZE 4
59 #define BADR2_SIZE 6
60 #define BADR3_SIZE 16
61 #define BADR4_SIZE 4
62
63 //DAC Offsets
64 #define ADC_TRIG 0
65 #define DAC0_OFFSET 2
66 #define DAC1_OFFSET 4
67
68 //AI and Counter Constants
69 #define MUX_LIMITS 0
70 #define MAIN_CONN_DIO 1
71 #define ADC_STAT 2
72 #define ADC_CONV_STAT 3
73 #define ADC_INT 4
74 #define ADC_PACER 5
75 #define BURST_MODE 6
76 #define PROG_GAIN 7
77 #define CLK8254_1_DATA 8
78 #define CLK8254_2_DATA 9
79 #define CLK8254_3_DATA 10
80 #define CLK8254_CONTROL 11
81 #define USER_COUNTER 12
82 #define RESID_COUNT_H 13
83 #define RESID_COUNT_L 14
84
85 /* Board description */
86 typedef struct cb_pcimdas_board_struct
87 {
88         char *name;
89         unsigned short device_id;
90         int ai_se_chans;        // Inputs in single-ended mode
91         int ai_diff_chans;      // Inputs in differential mode
92         int ai_bits;    // analog input resolution
93         int ai_speed;   // fastest conversion period in ns
94         int ao_nchan;   // number of analog out channels
95         int ao_bits;    // analogue output resolution
96         int has_ao_fifo;        // analog output has fifo
97         int ao_scan_speed;      // analog output speed for 1602 series (for a scan, not conversion)
98         int fifo_size;  // number of samples fifo can hold
99         int dio_bits;  // number of dio bits
100         int has_dio;    // has DIO
101         comedi_lrange *ranges;
102 } cb_pcimdas_board;
103
104 static cb_pcimdas_board cb_pcimdas_boards[] =
105 {
106         {
107                 name:           "PCIM-DAS1602/16",
108                 device_id:      0x56,
109                 ai_se_chans:    16,
110                 ai_diff_chans:  8,
111                 ai_bits:        16,
112                 ai_speed:       10000, //??
113                 ao_nchan:       2,     
114                 ao_bits:        12,
115                 has_ao_fifo:    0,     //??
116                 ao_scan_speed:  10000, //??
117                 fifo_size:      1024,   
118                 dio_bits:       24,
119                 has_dio:        1,
120 //              ranges:         &cb_pcimdas_ranges,
121         },
122 };
123
124 /* This is used by modprobe to translate PCI IDs to drivers.  Should
125  * only be used for PCI and ISA-PnP devices */
126 static struct pci_device_id cb_pcimdas_pci_table[] __devinitdata = {
127         { PCI_VENDOR_ID_COMPUTERBOARDS, 0x0056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
128         { 0 }
129 };
130 MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
131
132 #define N_BOARDS 1 // Max number of boards supported
133
134 /*
135  * Useful for shorthand access to the particular board structure
136  */
137 #define thisboard ((cb_pcimdas_board *)dev->board_ptr)
138
139 /* this structure is for data unique to this hardware driver.  If
140    several hardware drivers keep similar information in this structure,
141    feel free to suggest moving the variable to the comedi_device struct.  */
142 typedef struct{
143         int data;
144
145         // would be useful for a PCI device 
146         struct pci_dev *pci_dev;
147
148         //base addresses
149         unsigned long BADR0;
150         unsigned long BADR1;
151         unsigned long BADR2;
152         unsigned long BADR3;
153         unsigned long BADR4;
154
155         /* Used for AO readback */
156         lsampl_t ao_readback[2];
157
158         // Used for DIO
159         unsigned short int port_a;   // copy of BADR4+0
160         unsigned short int port_b;   // copy of BADR4+1
161         unsigned short int port_c;   // copy of BADR4+2
162         unsigned short int dio_mode; // copy of BADR4+3
163         
164 }cb_pcimdas_private;
165
166 /*
167  * most drivers define the following macro to make it easy to
168  * access the private structure.
169  */
170 #define devpriv ((cb_pcimdas_private *)dev->private)
171
172 /*
173  * The comedi_driver structure tells the Comedi core module
174  * which functions to call to configure/deconfigure (attach/detach)
175  * the board, and also about the kernel module that contains
176  * the device code.
177  */
178 static int cb_pcimdas_attach(comedi_device *dev,comedi_devconfig *it);
179 static int cb_pcimdas_detach(comedi_device *dev);
180 static comedi_driver driver_cb_pcimdas={
181         driver_name:    "cb_pcimdas",
182         module:         THIS_MODULE,
183         attach:         cb_pcimdas_attach,
184         detach:         cb_pcimdas_detach,
185 };
186
187 static int cb_pcimdas_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
188 static int cb_pcimdas_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
189 static int cb_pcimdas_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
190
191 /*
192  * Attach is called by the Comedi core to configure the driver
193  * for a particular board.  If you specified a board_name array
194  * in the driver structure, dev->board_ptr contains that
195  * address.
196  */
197 static int cb_pcimdas_attach(comedi_device *dev,comedi_devconfig *it)
198 {
199         comedi_subdevice *s;
200         struct pci_dev* pcidev;
201         int index;
202         //int i;
203
204         printk("comedi%d: cb_pcimdas: ",dev->minor);    
205
206 /*
207  * Allocate the private structure area.
208  */
209         if(alloc_private(dev,sizeof(cb_pcimdas_private))<0)
210                 return -ENOMEM;
211
212 /*
213  * Probe the device to determine what device in the series it is.
214  */
215         printk("\n");
216
217         for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ; 
218                 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
219         {
220                 // is it not a computer boards card?
221                 if(pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
222                         continue;
223                 // loop through cards supported by this driver
224                 for(index = 0; index < N_BOARDS; index++)
225                 {
226                         if(cb_pcimdas_boards[index].device_id != pcidev->device)
227                                 continue;
228                         // was a particular bus/slot requested?
229                         if(it->options[0] || it->options[1])
230                         {
231                                 // are we on the wrong bus/slot?
232                                 if(pcidev->bus->number != it->options[0] ||
233                                    PCI_SLOT(pcidev->devfn) != it->options[1])
234                                 {
235                                         continue;
236                                 }
237                         }
238                         devpriv->pci_dev = pcidev;
239                         dev->board_ptr = cb_pcimdas_boards + index;
240                         goto found;
241                 }
242         }
243
244         printk("No supported ComputerBoards/MeasurementComputing card found on "
245                 "requested position\n");
246         return -EIO;
247
248 found:
249
250         printk("Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name,
251                 pcidev->bus->number, PCI_SLOT(pcidev->devfn));
252
253         // Warn about non-tested features
254         switch(thisboard->device_id)
255         {
256                 case 0x56:
257                         break;
258                 default:
259                         printk( "THIS CARD IS UNSUPPORTED.\n"
260                                 "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
261         };
262
263         if(pci_enable_device(pcidev))
264         {
265                 printk(" Failed to enable PCI device\n");
266                 return -EIO;
267         }
268         if(pci_request_regions(pcidev, "cb_pcimdas"))
269         {
270                 printk(" I/O port conflict\n");
271                 return -EIO;
272         }
273
274         devpriv->BADR0 = pci_resource_start(devpriv->pci_dev, 0); 
275         devpriv->BADR1 = pci_resource_start(devpriv->pci_dev, 1); 
276         devpriv->BADR2 = pci_resource_start(devpriv->pci_dev, 2); 
277         devpriv->BADR3 = pci_resource_start(devpriv->pci_dev, 3); 
278         devpriv->BADR4 = pci_resource_start(devpriv->pci_dev, 4); 
279
280 #ifdef CBPCIMDAS_DEBUG
281         printk("devpriv->BADR0 = 0x%lx\n",devpriv->BADR0);
282         printk("devpriv->BADR1 = 0x%lx\n",devpriv->BADR1);
283         printk("devpriv->BADR2 = 0x%lx\n",devpriv->BADR2);
284         printk("devpriv->BADR3 = 0x%lx\n",devpriv->BADR3);
285         printk("devpriv->BADR4 = 0x%lx\n",devpriv->BADR4);
286 #endif
287
288
289 // Dont support IRQ yet
290 //      // get irq
291 //      if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev ))
292 //      {
293 //              printk(" unable to allocate irq %u\n", devpriv->pci_dev->irq);
294 //              return -EINVAL;
295 //      }
296 //      dev->irq = devpriv->pci_dev->irq;
297
298         //Initialize dev->board_name
299         dev->board_name = thisboard->name;
300
301
302 /*
303  * Allocate the subdevice structures.  alloc_subdevice() is a
304  * convenient macro defined in comedidev.h.
305  */
306         if(alloc_subdevices(dev, 3)<0)
307                 return -ENOMEM;
308
309         s=dev->subdevices+0;
310         //dev->read_subdev=s;
311         // analog input subdevice 
312         s->type=COMEDI_SUBD_AI;
313         s->subdev_flags=SDF_READABLE|SDF_GROUND;
314         s->n_chan=thisboard->ai_se_chans;
315         s->maxdata=(1<<thisboard->ai_bits)-1;
316         s->range_table=&range_unknown;
317         s->len_chanlist=1;  // This is the maximum chanlist length that
318                              // the board can handle 
319         s->insn_read = cb_pcimdas_ai_rinsn;
320
321         s=dev->subdevices+1;
322         // analog output subdevice
323         s->type=COMEDI_SUBD_AO;
324         s->subdev_flags=SDF_WRITABLE;
325         s->n_chan=thisboard->ao_nchan;
326         s->maxdata=1<<thisboard->ao_bits;
327         s->range_table=&range_unknown; //ranges are hardware settable, but not software readable.
328         s->insn_write = &cb_pcimdas_ao_winsn;
329         s->insn_read = &cb_pcimdas_ao_rinsn;
330
331         s = dev->subdevices + 2;
332         /* digital i/o subdevice */
333         if(thisboard->has_dio){
334                 subdev_8255_init(dev, s, NULL, devpriv->BADR4);
335         }else{
336                 s->type = COMEDI_SUBD_UNUSED;
337         }
338         
339         printk("attached\n");
340
341         return 1;
342 }
343
344
345 /*
346  * _detach is called to deconfigure a device.  It should deallocate
347  * resources.  
348  * This function is also called when _attach() fails, so it should be
349  * careful not to release resources that were not necessarily
350  * allocated by _attach().  dev->private and dev->subdevices are
351  * deallocated automatically by the core.
352  */
353 static int cb_pcimdas_detach(comedi_device *dev)
354 {
355 #ifdef CBPCIMDAS_DEBUG
356         if(devpriv)
357         {
358                 printk("devpriv->BADR0 = 0x%lx\n",devpriv->BADR0);
359                 printk("devpriv->BADR1 = 0x%lx\n",devpriv->BADR1);
360                 printk("devpriv->BADR2 = 0x%lx\n",devpriv->BADR2);
361                 printk("devpriv->BADR3 = 0x%lx\n",devpriv->BADR3);
362                 printk("devpriv->BADR4 = 0x%lx\n",devpriv->BADR4);
363         }
364 #endif
365         printk("comedi%d: cb_pcimdas: remove\n",dev->minor);
366         if(dev->irq)
367                 comedi_free_irq(dev->irq, dev);
368         if(devpriv)
369         {
370                 if(devpriv->pci_dev)
371                 {
372                         if(devpriv->BADR0)
373                         {
374                                 pci_release_regions(devpriv->pci_dev);
375                                 pci_disable_device(devpriv->pci_dev);
376                         }
377                         pci_dev_put(devpriv->pci_dev);
378                 }
379         }
380
381         return 0;
382 }
383
384 /*
385  * "instructions" read/write data in "one-shot" or "software-triggered"
386  * mode.
387  */
388 static int cb_pcimdas_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
389 {
390         int n,i;
391         unsigned int d;
392         unsigned int busy;
393         int chan = CR_CHAN(insn->chanspec);
394         unsigned short chanlims;
395         int maxchans;
396
397         // only support sw initiated reads from a single channel
398
399         //check channel number
400         if ((inb(devpriv->BADR3+2) & 0x20)==0) //differential mode
401                 maxchans=thisboard->ai_diff_chans;
402         else
403                 maxchans=thisboard->ai_se_chans;
404
405         if (chan>(maxchans-1)) 
406                 return -ETIMEDOUT;  //*** Wrong error code. Fixme.
407
408         //configure for sw initiated read
409         d=inb(devpriv->BADR3+5);
410         if ((d & 0x03)>0) {                     //only reset if needed.
411                 d=d & 0xfd;
412                 outb(d,devpriv->BADR3+5);
413         }
414         outb(0x01,devpriv->BADR3+6); //set bursting off, conversions on
415         outb(0x00,devpriv->BADR3+7); //set range to 10V. UP/BP is controlled by a switch on the board
416
417         // write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan.
418         chanlims=chan | (chan<<4);
419         outb(chanlims,devpriv->BADR3+0);
420
421         /* convert n samples */
422         for(n=0;n<insn->n;n++){
423                 /* trigger conversion */
424                 outw(0,devpriv->BADR2+0);
425
426 #define TIMEOUT 1000    //typically takes 5 loops on a lightly loaded Pentium 100MHz,
427                         //this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit.
428
429                 /* wait for conversion to end */
430                 for(i=0;i<TIMEOUT;i++){
431                         busy = inb(devpriv->BADR3+2)&0x80;
432                         if(!busy)break;
433                 }
434                 if(i==TIMEOUT){
435                         printk("timeout\n");
436                         return -ETIMEDOUT;
437                 }
438                 /* read data */
439                 d = inw(devpriv->BADR2+0);
440
441                 /* mangle the data as necessary */
442                 //d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed.
443
444                 data[n] = d;
445         }
446
447         /* return the number of samples read/written */
448         return n;
449 }
450
451
452 static int cb_pcimdas_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
453 {
454         int i;
455         int chan = CR_CHAN(insn->chanspec);
456
457         /* Writing a list of values to an AO channel is probably not
458          * very useful, but that's how the interface is defined. */
459         for(i=0;i<insn->n;i++){
460                 switch ( chan ) {
461                 case 0:  
462                         outw(data[i] & 0x0FFF,devpriv->BADR2+DAC0_OFFSET);
463                         break;
464                 case 1:
465                         outw(data[i] & 0x0FFF,devpriv->BADR2+DAC1_OFFSET);
466                         break;
467                 default:
468                         return -1;
469                 }
470                 devpriv->ao_readback[chan] = data[i];
471         }
472
473         /* return the number of samples read/written */
474         return i;
475 }
476
477 /* AO subdevices should have a read insn as well as a write insn.
478  * Usually this means copying a value stored in devpriv. */
479 static int cb_pcimdas_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
480 {
481         int i;
482         int chan = CR_CHAN(insn->chanspec);
483
484         for(i=0;i<insn->n;i++)
485                 data[i] = devpriv->ao_readback[chan];
486
487         return i;
488 }
489
490
491 /*
492  * A convenient macro that defines init_module() and cleanup_module(),
493  * as necessary.
494  */
495 COMEDI_INITCLEANUP(driver_cb_pcimdas);
496
497