]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/comedi/drivers/addi-data/addi_common.c
Merge remote-tracking branch 'usb-gadget/next'
[karo-tx-linux.git] / drivers / staging / comedi / drivers / addi-data / addi_common.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
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 under
15 the terms of the GNU General Public License as published by the Free Software
16 Foundation; either version 2 of the License, or (at your option) any later
17 version.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 PARTICULAR PURPOSE. See the GNU General Public License for more details.
22
23 @endverbatim
24 */
25 /*
26
27   +-----------------------------------------------------------------------+
28   | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
29   +-----------------------------------------------------------------------+
30   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
31   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
32   +-----------------------------------------------------------------------+
33   | Project   : ADDI DATA         | Compiler : GCC                        |
34   | Modulname : addi_common.c     | Version  : 2.96                       |
35   +-------------------------------+---------------------------------------+
36   | Author    :           | Date     :                                    |
37   +-----------------------------------------------------------------------+
38   | Description : ADDI COMMON Main Module                                 |
39   +-----------------------------------------------------------------------+
40 */
41
42 static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
43                                      struct comedi_subdevice *s,
44                                      struct comedi_insn *insn,
45                                      unsigned int *data)
46 {
47         const struct addi_board *this_board = comedi_board(dev);
48         struct addi_private *devpriv = dev->private;
49         unsigned short w_Address = CR_CHAN(insn->chanspec);
50         unsigned short w_Data;
51
52         w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
53                 this_board->pc_EepromChip, 2 * w_Address);
54         data[0] = w_Data;
55
56         return insn->n;
57 }
58
59 static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
60 {
61         struct comedi_device *dev = d;
62         const struct addi_board *this_board = comedi_board(dev);
63
64         this_board->interrupt(irq, d);
65         return IRQ_RETVAL(1);
66 }
67
68 static int i_ADDI_Reset(struct comedi_device *dev)
69 {
70         const struct addi_board *this_board = comedi_board(dev);
71
72         this_board->reset(dev);
73         return 0;
74 }
75
76 static int addi_auto_attach(struct comedi_device *dev,
77                                       unsigned long context_unused)
78 {
79         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
80         const struct addi_board *this_board = comedi_board(dev);
81         struct addi_private *devpriv;
82         struct comedi_subdevice *s;
83         int ret, n_subdevices;
84         unsigned int dw_Dummy;
85
86         dev->board_name = this_board->pc_DriverName;
87
88         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
89         if (!devpriv)
90                 return -ENOMEM;
91
92         ret = comedi_pci_enable(dev);
93         if (ret)
94                 return ret;
95
96         if (this_board->i_IorangeBase1)
97                 dev->iobase = pci_resource_start(pcidev, 1);
98         else
99                 dev->iobase = pci_resource_start(pcidev, 0);
100
101         devpriv->iobase = dev->iobase;
102         devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
103         devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
104         devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
105
106         /* Initialize parameters that can be overridden in EEPROM */
107         devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
108         devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
109         devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata;
110         devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata;
111         devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
112         devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
113         devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
114         devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
115         devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
116                 this_board->ui_MinAcquisitiontimeNs;
117         devpriv->s_EeParameters.ui_MinDelaytimeNs =
118                 this_board->ui_MinDelaytimeNs;
119
120         /* ## */
121
122         if (pcidev->irq > 0) {
123                 ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
124                                   dev->board_name, dev);
125                 if (ret == 0)
126                         dev->irq = pcidev->irq;
127         }
128
129         /*  Read eepeom and fill addi_board Structure */
130
131         if (this_board->i_PCIEeprom) {
132                 if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
133                         /*  Set 3 wait stait */
134                         if (!(strcmp(dev->board_name, "apci035")))
135                                 outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
136                         else
137                                 outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
138
139                         /*  Enable the interrupt for the controller */
140                         dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
141                         outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
142                 }
143                 addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
144         }
145
146         n_subdevices = 7;
147         ret = comedi_alloc_subdevices(dev, n_subdevices);
148         if (ret)
149                 return ret;
150
151         /*  Allocate and Initialise AI Subdevice Structures */
152         s = &dev->subdevices[0];
153         if ((devpriv->s_EeParameters.i_NbrAiChannel)
154                 || (this_board->i_NbrAiChannelDiff)) {
155                 dev->read_subdev = s;
156                 s->type = COMEDI_SUBD_AI;
157                 s->subdev_flags =
158                         SDF_READABLE | SDF_COMMON | SDF_GROUND
159                         | SDF_DIFF;
160                 if (devpriv->s_EeParameters.i_NbrAiChannel) {
161                         s->n_chan =
162                                 devpriv->s_EeParameters.i_NbrAiChannel;
163                         devpriv->b_SingelDiff = 0;
164                 } else {
165                         s->n_chan = this_board->i_NbrAiChannelDiff;
166                         devpriv->b_SingelDiff = 1;
167                 }
168                 s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
169                 s->len_chanlist = this_board->i_AiChannelList;
170                 s->range_table = this_board->pr_AiRangelist;
171
172                 s->insn_config = this_board->ai_config;
173                 s->insn_read = this_board->ai_read;
174                 s->insn_write = this_board->ai_write;
175                 s->insn_bits = this_board->ai_bits;
176                 s->do_cmdtest = this_board->ai_cmdtest;
177                 s->do_cmd = this_board->ai_cmd;
178                 s->cancel = this_board->ai_cancel;
179
180         } else {
181                 s->type = COMEDI_SUBD_UNUSED;
182         }
183
184         /*  Allocate and Initialise AO Subdevice Structures */
185         s = &dev->subdevices[1];
186         if (devpriv->s_EeParameters.i_NbrAoChannel) {
187                 s->type = COMEDI_SUBD_AO;
188                 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
189                 s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
190                 s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
191                 s->len_chanlist =
192                         devpriv->s_EeParameters.i_NbrAoChannel;
193                 s->insn_write = this_board->ao_write;
194         } else {
195                 s->type = COMEDI_SUBD_UNUSED;
196         }
197         /*  Allocate and Initialise DI Subdevice Structures */
198         s = &dev->subdevices[2];
199         if (devpriv->s_EeParameters.i_NbrDiChannel) {
200                 s->type = COMEDI_SUBD_DI;
201                 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
202                 s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
203                 s->maxdata = 1;
204                 s->len_chanlist =
205                         devpriv->s_EeParameters.i_NbrDiChannel;
206                 s->range_table = &range_digital;
207                 s->io_bits = 0; /* all bits input */
208                 s->insn_config = this_board->di_config;
209                 s->insn_read = this_board->di_read;
210                 s->insn_write = this_board->di_write;
211                 s->insn_bits = this_board->di_bits;
212         } else {
213                 s->type = COMEDI_SUBD_UNUSED;
214         }
215         /*  Allocate and Initialise DO Subdevice Structures */
216         s = &dev->subdevices[3];
217         if (devpriv->s_EeParameters.i_NbrDoChannel) {
218                 s->type = COMEDI_SUBD_DO;
219                 s->subdev_flags =
220                         SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
221                 s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
222                 s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
223                 s->len_chanlist =
224                         devpriv->s_EeParameters.i_NbrDoChannel;
225                 s->range_table = &range_digital;
226                 s->io_bits = 0xf;       /* all bits output */
227
228                 /* insn_config - for digital output memory */
229                 s->insn_config = this_board->do_config;
230                 s->insn_write = this_board->do_write;
231                 s->insn_bits = this_board->do_bits;
232                 s->insn_read = this_board->do_read;
233         } else {
234                 s->type = COMEDI_SUBD_UNUSED;
235         }
236
237         /*  Allocate and Initialise Timer Subdevice Structures */
238         s = &dev->subdevices[4];
239         if (devpriv->s_EeParameters.i_Timer) {
240                 s->type = COMEDI_SUBD_TIMER;
241                 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
242                 s->n_chan = 1;
243                 s->maxdata = 0;
244                 s->len_chanlist = 1;
245                 s->range_table = &range_digital;
246
247                 s->insn_write = this_board->timer_write;
248                 s->insn_read = this_board->timer_read;
249                 s->insn_config = this_board->timer_config;
250                 s->insn_bits = this_board->timer_bits;
251         } else {
252                 s->type = COMEDI_SUBD_UNUSED;
253         }
254
255         /*  Allocate and Initialise TTL */
256         s = &dev->subdevices[5];
257         s->type = COMEDI_SUBD_UNUSED;
258
259         /* EEPROM */
260         s = &dev->subdevices[6];
261         if (this_board->i_PCIEeprom) {
262                 s->type = COMEDI_SUBD_MEMORY;
263                 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
264                 s->n_chan = 256;
265                 s->maxdata = 0xffff;
266                 s->insn_read = i_ADDIDATA_InsnReadEeprom;
267         } else {
268                 s->type = COMEDI_SUBD_UNUSED;
269         }
270
271         i_ADDI_Reset(dev);
272         return 0;
273 }
274
275 static void i_ADDI_Detach(struct comedi_device *dev)
276 {
277         struct addi_private *devpriv = dev->private;
278
279         if (devpriv) {
280                 if (dev->iobase)
281                         i_ADDI_Reset(dev);
282                 if (dev->irq)
283                         free_irq(dev->irq, dev);
284         }
285         comedi_pci_disable(dev);
286 }