staging: comedi: addi_apci_1032: remove send_sig() use
[linux-2.6-block.git] / drivers / staging / comedi / drivers / addi_apci_1032.c
CommitLineData
6a3734af
HS
1/*
2 * addi_apci_1032.c
3 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
4 * Project manager: Eric Stolz
5 *
6 * ADDI-DATA GmbH
7 * Dieselstrasse 3
8 * D-77833 Ottersweier
9 * Tel: +19(0)7223/9493-0
10 * Fax: +49(0)7223/9493-92
11 * http://www.addi-data.com
12 * info@addi-data.com
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 * Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 * You should also find the complete GPL in the COPYING file accompanying this
29 * source code.
30 */
31
3d41c443
HS
32#include "../comedidev.h"
33#include "comedi_fc.h"
bf36f012 34#include "amcc_s5933.h"
3d41c443
HS
35
36#include "addi-data/addi_common.h"
3d41c443 37
6a3734af
HS
38/*
39 * I/O Register Map
40 */
41#define APCI1032_DI_REG 0x00
42#define APCI1032_MODE1_REG 0x04
43#define APCI1032_MODE2_REG 0x08
44#define APCI1032_STATUS_REG 0x0c
45#define APCI1032_CTRL_REG 0x10
46#define APCI1032_CTRL_INT_OR (0 << 1)
47#define APCI1032_CTRL_INT_AND (1 << 1)
48#define APCI1032_CTRL_INT_ENA (1 << 2)
49
50/* Digital Input IRQ Function Selection */
51#define ADDIDATA_OR 0
52#define ADDIDATA_AND 1
53
54static unsigned int ui_InterruptStatus;
55
56/*
57 * data[0] : 1 Enable Digital Input Interrupt
58 * 0 Disable Digital Input Interrupt
59 * data[1] : 0 ADDIDATA Interrupt OR LOGIC
60 * : 1 ADDIDATA Interrupt AND LOGIC
61 * data[2] : Interrupt mask for the mode 1
62 * data[3] : Interrupt mask for the mode 2
63 */
6835a17a
HS
64static int apci1032_intr_insn_config(struct comedi_device *dev,
65 struct comedi_subdevice *s,
66 struct comedi_insn *insn,
67 unsigned int *data)
6a3734af 68{
6a3734af
HS
69 unsigned int ui_TmpValue;
70 unsigned int ul_Command1 = 0;
71 unsigned int ul_Command2 = 0;
72
6a3734af
HS
73 /*******************************/
74 /* Set the digital input logic */
75 /*******************************/
76 if (data[0] == ADDIDATA_ENABLE) {
77 ul_Command1 = ul_Command1 | data[2];
78 ul_Command2 = ul_Command2 | data[3];
79 outl(ul_Command1, dev->iobase + APCI1032_MODE1_REG);
80 outl(ul_Command2, dev->iobase + APCI1032_MODE2_REG);
81 if (data[1] == ADDIDATA_OR) {
82 outl(APCI1032_CTRL_INT_ENA |
83 APCI1032_CTRL_INT_OR,
84 dev->iobase + APCI1032_CTRL_REG);
85 ui_TmpValue =
86 inl(dev->iobase + APCI1032_CTRL_REG);
87 } /* if (data[1] == ADDIDATA_OR) */
88 else
89 outl(APCI1032_CTRL_INT_ENA |
90 APCI1032_CTRL_INT_AND,
91 dev->iobase + APCI1032_CTRL_REG);
92 /* else if(data[1] == ADDIDATA_OR) */
93 } /* if( data[0] == ADDIDATA_ENABLE) */
94 else {
95 ul_Command1 = ul_Command1 & 0xFFFF0000;
96 ul_Command2 = ul_Command2 & 0xFFFF0000;
97 outl(ul_Command1, dev->iobase + APCI1032_MODE1_REG);
98 outl(ul_Command2, dev->iobase + APCI1032_MODE2_REG);
99 outl(0x0, dev->iobase + APCI1032_CTRL_REG);
100 } /* else if ( data[0] == ADDIDATA_ENABLE) */
101
102 return insn->n;
103}
2bb8b1df 104
12d606f7 105static irqreturn_t apci1032_interrupt(int irq, void *d)
2bb8b1df 106{
12d606f7 107 struct comedi_device *dev = d;
12d606f7
HS
108 unsigned int ctrl;
109
110 /* disable the interrupt */
111 ctrl = inl(dev->iobase + APCI1032_CTRL_REG);
112 outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG);
113
114 ui_InterruptStatus = inl(dev->iobase + APCI1032_STATUS_REG);
115 ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
12d606f7
HS
116
117 /* enable the interrupt */
118 outl(ctrl, dev->iobase + APCI1032_CTRL_REG);
119
120 return IRQ_HANDLED;
2bb8b1df
HS
121}
122
a3de4cd3
HS
123static int apci1032_di_insn_bits(struct comedi_device *dev,
124 struct comedi_subdevice *s,
125 struct comedi_insn *insn,
126 unsigned int *data)
127{
128 data[1] = inl(dev->iobase + APCI1032_DI_REG);
129
130 return insn->n;
131}
132
274113fd
HS
133static int apci1032_reset(struct comedi_device *dev)
134{
135 /* disable the interrupts */
136 outl(0x0, dev->iobase + APCI1032_CTRL_REG);
137 /* Reset the interrupt status register */
138 inl(dev->iobase + APCI1032_STATUS_REG);
139 /* Disable the and/or interrupt */
140 outl(0x0, dev->iobase + APCI1032_MODE1_REG);
141 outl(0x0, dev->iobase + APCI1032_MODE2_REG);
142
143 return 0;
144}
145
2bb8b1df
HS
146static int apci1032_attach_pci(struct comedi_device *dev,
147 struct pci_dev *pcidev)
148{
2bb8b1df 149 struct comedi_subdevice *s;
b37f84d5 150 int ret;
2bb8b1df 151
ac467b5e 152 dev->board_name = dev->driver->driver_name;
2bb8b1df 153
2bb8b1df
HS
154 ret = comedi_pci_enable(pcidev, dev->board_name);
155 if (ret)
156 return ret;
157
05f22ad7 158 dev->iobase = pci_resource_start(pcidev, 2);
2bb8b1df 159
2bb8b1df 160 if (pcidev->irq > 0) {
12d606f7 161 ret = request_irq(pcidev->irq, apci1032_interrupt, IRQF_SHARED,
2bb8b1df
HS
162 dev->board_name, dev);
163 if (ret == 0)
164 dev->irq = pcidev->irq;
165 }
166
6835a17a 167 ret = comedi_alloc_subdevices(dev, 2);
2bb8b1df
HS
168 if (ret)
169 return ret;
170
2bb8b1df 171 /* Allocate and Initialise DI Subdevice Structures */
b37f84d5 172 s = &dev->subdevices[0];
4c2c1488
HS
173 s->type = COMEDI_SUBD_DI;
174 s->subdev_flags = SDF_READABLE;
175 s->n_chan = 32;
176 s->maxdata = 1;
177 s->len_chanlist = 32;
178 s->range_table = &range_digital;
a3de4cd3 179 s->insn_bits = apci1032_di_insn_bits;
5dbdbf67 180
6835a17a
HS
181 if (dev->irq) {
182 s = &dev->subdevices[1];
183 s->type = COMEDI_SUBD_DI;
184 s->subdev_flags = SDF_READABLE;
185 s->n_chan = 1;
186 s->maxdata = 1;
187 s->range_table = &range_digital;
188 s->insn_config = apci1032_intr_insn_config;
189 }
190
274113fd 191 apci1032_reset(dev);
2bb8b1df
HS
192 return 0;
193}
194
195static void apci1032_detach(struct comedi_device *dev)
196{
197 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2bb8b1df 198
14696bbe
HS
199 if (dev->iobase)
200 apci1032_reset(dev);
201 if (dev->irq)
202 free_irq(dev->irq, dev);
2bb8b1df
HS
203 if (pcidev) {
204 if (dev->iobase)
205 comedi_pci_disable(pcidev);
206 }
207}
208
20a22b70
HS
209static struct comedi_driver apci1032_driver = {
210 .driver_name = "addi_apci_1032",
211 .module = THIS_MODULE,
2bb8b1df
HS
212 .attach_pci = apci1032_attach_pci,
213 .detach = apci1032_detach,
20a22b70
HS
214};
215
216static int __devinit apci1032_pci_probe(struct pci_dev *dev,
217 const struct pci_device_id *ent)
218{
219 return comedi_pci_auto_config(dev, &apci1032_driver);
220}
221
222static void __devexit apci1032_pci_remove(struct pci_dev *dev)
223{
224 comedi_pci_auto_unconfig(dev);
225}
226
227static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = {
317285d7
HS
228 { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) },
229 { 0 }
230};
20a22b70 231MODULE_DEVICE_TABLE(pci, apci1032_pci_table);
317285d7 232
20a22b70
HS
233static struct pci_driver apci1032_pci_driver = {
234 .name = "addi_apci_1032",
235 .id_table = apci1032_pci_table,
236 .probe = apci1032_pci_probe,
237 .remove = __devexit_p(apci1032_pci_remove),
238};
239module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
90f703d3
AT
240
241MODULE_AUTHOR("Comedi http://www.comedi.org");
242MODULE_DESCRIPTION("Comedi low-level driver");
243MODULE_LICENSE("GPL");