Added some ack'ing of b interrupts, and do acks before handling
[comedi.git] / comedi / drivers / adl_pci7432.c
1 /*
2     comedi/drivers/adl_pci7432.c
3
4     Hardware comedi driver fot PCI7432 Adlink card
5     Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
6
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22 /*
23 Driver: adl_pci7432.o
24 Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board
25 Devices: [ADLink] PCI-7432 (pci7432)
26 Author: Michel Lachaine <mike@mikelachaine.ca>
27 Status: experimental
28
29 Configuration Options:
30   none
31 */
32
33 #include <linux/comedidev.h>
34 #include <linux/kernel.h>
35 #include <linux/pci.h>
36
37 #define PCI7432_DI      0x00
38 #define PCI7432_DO          0x00
39
40 #define PCI_DEVICE_ID_PCI7432 0x7432
41
42 typedef struct {
43         char *name;
44         int  vendor_id;
45         int  device_id;
46 } adl_pci7432_board;
47
48 static adl_pci7432_board adl_pci7432_boards[] = {
49         { "pci7432", PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432 },
50 };
51
52 static struct pci_device_id adl_pci7432_pci_table[] __devinitdata = {
53         { PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
54         { 0 }
55 };
56 MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
57
58 #define thisboard ((adl_pci7432_board *)dev->board_ptr)
59
60 typedef struct{
61         int data;
62         struct pci_dev *pci_dev;
63 } adl_pci7432_private;
64
65 #define devpriv ((adl_pci7432_private *)dev->private)
66
67 static int adl_pci7432_attach(comedi_device *dev,comedi_devconfig *it);
68 static int adl_pci7432_detach(comedi_device *dev);
69 static comedi_driver driver_adl_pci7432={
70         driver_name:    "adl_pci7432",
71         module:         THIS_MODULE,
72         attach:         adl_pci7432_attach,
73         detach:         adl_pci7432_detach,
74         num_names:  1,
75         board_name: (const char**)adl_pci7432_boards,
76         offset:     sizeof(adl_pci7432_board),
77 };
78
79 /* Digital IO */
80
81 static int adl_pci7432_di_insn_bits(comedi_device *dev,comedi_subdevice *s,
82         comedi_insn *insn,lsampl_t *data);
83
84 static int adl_pci7432_do_insn_bits(comedi_device *dev,comedi_subdevice *s,
85         comedi_insn *insn,lsampl_t *data);
86
87 /*            */
88
89 static int adl_pci7432_attach(comedi_device *dev,comedi_devconfig *it)
90 {
91         struct pci_dev *pcidev;
92         comedi_subdevice *s;
93
94         printk("comedi: attempt to attach...\n");
95         printk("comedi%d: adl_pci7432: board=%s\n",dev->minor, thisboard->name);
96
97         dev->board_name = thisboard->name;
98
99         if(alloc_private(dev,sizeof(adl_pci7432_private))<0)
100                 return -ENOMEM;
101
102         if(alloc_subdevices(dev, 2)<0)
103                 return -ENOMEM;
104
105         for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
106                 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
107         {
108
109                 if ( pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
110                      pcidev->device == PCI_DEVICE_ID_PCI7432 ) {
111                         devpriv->pci_dev = pcidev;
112                         if (pci_enable_device(pcidev) < 0) {
113                                 printk("comedi%d: Failed to enable PCI device\n", dev->minor);
114                                 return -EIO;
115                         }
116                         if (pci_request_regions(pcidev, "adl_pci7432") < 0) {
117                                 printk("comedi%d: I/O port conflict\n", dev->minor);
118                                 return -EIO;
119                         }
120                         dev->iobase = pci_resource_start ( pcidev, 2 );
121                         printk ( "comedi: base addr %4lx\n", dev->iobase );
122
123                         dev->board_ptr = adl_pci7432_boards + 0;
124
125                         s=dev->subdevices+0;
126                         s->type = COMEDI_SUBD_DI;
127                         s->subdev_flags = SDF_READABLE|SDF_GROUND|SDF_COMMON;
128                         s->n_chan = 32;
129                         s->maxdata = 1;
130                         s->len_chanlist = 32;
131                         s->io_bits = 0x00000000;
132                         s->range_table = &range_digital;
133                         s->insn_bits = adl_pci7432_di_insn_bits;
134
135                         s=dev->subdevices+1;
136             s->type = COMEDI_SUBD_DO;
137             s->subdev_flags = SDF_WRITABLE|SDF_GROUND|SDF_COMMON;
138             s->n_chan = 32;
139             s->maxdata = 1      ;
140                         s->len_chanlist = 32;
141                         s->io_bits = 0xffffffff;
142             s->range_table = &range_digital;
143             s->insn_bits = adl_pci7432_do_insn_bits;
144
145                         break;
146                 }
147         }
148
149         printk("comedi: attached\n");
150
151         return 1;
152 }
153
154
155 static int adl_pci7432_detach(comedi_device *dev)
156 {
157         printk("comedi%d: pci7432: remove\n",dev->minor);
158
159         if (devpriv && devpriv->pci_dev) {
160                 if (dev->iobase) {
161                         pci_release_regions(devpriv->pci_dev);
162                         pci_disable_device(devpriv->pci_dev);
163                 }
164                 pci_dev_put(devpriv->pci_dev);
165         }
166
167         return 0;
168 }
169
170
171 static int adl_pci7432_do_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)
172 {
173         printk ( "comedi: pci7432_do_insn_bits called\n" );
174         printk ( "comedi: data0: %8x data1: %8x\n", data[0], data[1] );
175
176         if(insn->n!=2)return -EINVAL;
177
178         if(data[0]){
179                 s->state &= ~data[0];
180                 s->state |= (data[0]&data[1]);
181
182                 printk ( "comedi: out: %8x on iobase %4lx\n", s->state, dev->iobase + PCI7432_DO);
183                 outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
184         }
185         return 2;
186 }
187
188 static int adl_pci7432_di_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)
189 {
190         printk ( "comedi: pci7432_di_insn_bits called\n" );
191         printk ( "comedi: data0: %8x data1: %8x\n", data[0], data[1] );
192
193         if(insn->n!=2)return -EINVAL;
194
195         data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
196         printk ( "comedi: data1 %8x\n", data[1] );
197
198         return 2;
199 }
200
201 COMEDI_INITCLEANUP(driver_adl_pci7432);