]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/addi-data/addi_common.c
staging: comedi: addi-data: remove io_addr array from card data
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / comedi / drivers / addi-data / addi_common.c
CommitLineData
c995fe94
ADG
1/**
2@verbatim
3
4Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
5
356cdbcb
BP
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
25417922 11 http://www.addi-data.com
356cdbcb 12 info@addi-data.com
c995fe94
ADG
13
14This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
39cfb97b 20You should also find the complete GPL in the COPYING file accompanying this source code.
c995fe94
ADG
21
22@endverbatim
23*/
24/*
25
26 +-----------------------------------------------------------------------+
27 | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
28 +-----------------------------------------------------------------------+
29 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
30 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
31 +-----------------------------------------------------------------------+
32 | Project : ADDI DATA | Compiler : GCC |
33 | Modulname : addi_common.c | Version : 2.96 |
34 +-------------------------------+---------------------------------------+
35 | Author : | Date : |
36 +-----------------------------------------------------------------------+
37 | Description : ADDI COMMON Main Module |
38 +-----------------------------------------------------------------------+
39 | CONFIG OPTIONS |
40 | option[0] - PCI bus number - if bus number and slot number are 0, |
41 | then driver search for first unused card |
42 | option[1] - PCI slot number |
43 | |
44 | option[2] = 0 - DMA ENABLE |
45 | = 1 - DMA DISABLE |
46 +----------+-----------+------------------------------------------------+
47*/
48
c995fe94
ADG
49#ifndef COMEDI_SUBD_TTLIO
50#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
51#endif
52
17d51852
HS
53static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
54 struct comedi_subdevice *s,
55 struct comedi_insn *insn,
56 unsigned int *data)
57{
58 const struct addi_board *this_board = comedi_board(dev);
59 struct addi_private *devpriv = dev->private;
60 unsigned short w_Address = CR_CHAN(insn->chanspec);
61 unsigned short w_Data;
62
66be78f6 63 w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
85c1dcba 64 this_board->pc_EepromChip, 2 * w_Address);
17d51852
HS
65 data[0] = w_Data;
66
67 return insn->n;
68}
69
70static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
71{
72 struct comedi_device *dev = d;
73 const struct addi_board *this_board = comedi_board(dev);
74
75 this_board->interrupt(irq, d);
76 return IRQ_RETVAL(1);
77}
78
79static int i_ADDI_Reset(struct comedi_device *dev)
80{
81 const struct addi_board *this_board = comedi_board(dev);
82
83 this_board->reset(dev);
84 return 0;
85}
86
da91b269 87static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
c995fe94 88{
02913e06 89 const struct addi_board *this_board = comedi_board(dev);
843690b7 90 struct addi_private *devpriv;
34c43922 91 struct comedi_subdevice *s;
c995fe94 92 int ret, pages, i, n_subdevices;
756e9d7c 93 unsigned int dw_Dummy;
c995fe94
ADG
94 resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved;
95 struct pcilst_struct *card = NULL;
c995fe94 96 int i_Dma = 0;
c995fe94 97
c34fa261
HS
98 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
99 if (!devpriv)
100 return -ENOMEM;
101 dev->private = devpriv;
c995fe94
ADG
102
103 if (!pci_list_builded) {
92db8be4 104 v_pci_card_list_init(this_board->i_VendorId);
c995fe94
ADG
105 pci_list_builded = 1;
106 }
c995fe94
ADG
107
108 if ((this_board->i_Dma) && (it->options[2] == 0)) {
109 i_Dma = 1;
110 }
111
c3744138
BP
112 card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
113 this_board->i_DeviceId,
114 it->options[0],
115 it->options[1], i_Dma);
116
117 if (card == NULL)
c995fe94 118 return -EIO;
c3744138 119
c995fe94
ADG
120 devpriv->allocated = 1;
121
e864e2c8
HS
122 iobase_a = pci_resource_start(card->pcidev, 0);
123 iobase_main = pci_resource_start(card->pcidev, 1);
124 iobase_addon = pci_resource_start(card->pcidev, 2);
125 iobase_reserved = pci_resource_start(card->pcidev, 3);
c995fe94
ADG
126
127 if ((this_board->pc_EepromChip == NULL)
128 || (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
129 /************************************/
130 /* Test if more that 1 address used */
131 /************************************/
132
133 if (this_board->i_IorangeBase1 != 0) {
2696fb57 134 dev->iobase = (unsigned long)iobase_main; /* DAQ base address... */
c995fe94 135 } else {
2696fb57 136 dev->iobase = (unsigned long)iobase_a; /* DAQ base address... */
c995fe94
ADG
137 }
138
139 dev->board_name = this_board->pc_DriverName;
140 devpriv->amcc = card;
74b894e5 141 devpriv->iobase = (int) dev->iobase;
2696fb57
BP
142 devpriv->i_IobaseAmcc = (int) iobase_a; /* AMCC base address... */
143 devpriv->i_IobaseAddon = (int) iobase_addon; /* ADD ON base address.... */
74b894e5 144 devpriv->i_IobaseReserved = (int) iobase_reserved;
c995fe94
ADG
145 } else {
146 dev->board_name = this_board->pc_DriverName;
e864e2c8 147 dev->iobase = pci_resource_start(card->pcidev, 2);
c995fe94 148 devpriv->amcc = card;
e864e2c8
HS
149 devpriv->iobase = pci_resource_start(card->pcidev, 2);
150 devpriv->i_IobaseReserved = pci_resource_start(card->pcidev, 3);
151 devpriv->dw_AiBase = ioremap(pci_resource_start(card->pcidev, 3),
2f78c642 152 this_board->i_IorangeBase3);
c995fe94
ADG
153 }
154
57517878
IA
155 /* Initialize parameters that can be overridden in EEPROM */
156 devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
157 devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
158 devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata;
159 devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata;
160 devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
161 devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
162 devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
163 devpriv->s_EeParameters.i_Dma = this_board->i_Dma;
164 devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
165 devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
166 this_board->ui_MinAcquisitiontimeNs;
167 devpriv->s_EeParameters.ui_MinDelaytimeNs =
168 this_board->ui_MinDelaytimeNs;
169
2696fb57 170 /* ## */
c995fe94 171
e6fee79e
HS
172 if (card->irq > 0) {
173 ret = request_irq(card->irq, v_ADDI_Interrupt, IRQF_SHARED,
174 this_board->pc_DriverName, dev);
175 if (ret == 0)
176 dev->irq = card->irq;
c995fe94
ADG
177 }
178
2696fb57 179 /* Read eepeom and fill addi_board Structure */
c995fe94
ADG
180
181 if (this_board->i_PCIEeprom) {
c995fe94 182 if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
2696fb57 183 /* Set 3 wait stait */
c995fe94
ADG
184 if (!(strcmp(this_board->pc_DriverName, "apci035"))) {
185 outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
186 } else {
187 outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
188 }
af02b584 189 /* Enable the interrupt for the controller */
c995fe94
ADG
190 dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
191 outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
c995fe94 192 }
e864e2c8 193 addi_eeprom_read_info(dev, pci_resource_start(card->pcidev, 0));
c995fe94
ADG
194 }
195
196 if (it->options[2] > 0) {
197 devpriv->us_UseDma = ADDI_DISABLE;
198 } else {
199 devpriv->us_UseDma = ADDI_ENABLE;
200 }
201
57517878 202 if (devpriv->s_EeParameters.i_Dma) {
c995fe94 203 if (devpriv->us_UseDma == ADDI_ENABLE) {
2696fb57 204 /* alloc DMA buffers */
c995fe94
ADG
205 devpriv->b_DmaDoubleBuffer = 0;
206 for (i = 0; i < 2; i++) {
207 for (pages = 4; pages >= 0; pages--) {
c3744138
BP
208 devpriv->ul_DmaBufferVirtual[i] =
209 (void *) __get_free_pages(GFP_KERNEL, pages);
210
211 if (devpriv->ul_DmaBufferVirtual[i])
c995fe94 212 break;
c995fe94
ADG
213 }
214 if (devpriv->ul_DmaBufferVirtual[i]) {
215 devpriv->ui_DmaBufferPages[i] = pages;
216 devpriv->ui_DmaBufferSize[i] =
217 PAGE_SIZE * pages;
218 devpriv->ui_DmaBufferSamples[i] =
219 devpriv->
220 ui_DmaBufferSize[i] >> 1;
221 devpriv->ul_DmaBufferHw[i] =
222 virt_to_bus((void *)devpriv->
223 ul_DmaBufferVirtual[i]);
224 }
225 }
48d1db93 226 if (!devpriv->ul_DmaBufferVirtual[0])
c995fe94 227 devpriv->us_UseDma = ADDI_DISABLE;
c995fe94 228
48d1db93 229 if (devpriv->ul_DmaBufferVirtual[1])
c995fe94 230 devpriv->b_DmaDoubleBuffer = 1;
c995fe94
ADG
231 }
232 }
233
234 if (!strcmp(this_board->pc_DriverName, "apci1710")) {
235#ifdef CONFIG_APCI_1710
236 i_ADDI_AttachPCI1710(dev);
237
2696fb57 238 /* save base address */
e864e2c8 239 devpriv->s_BoardInfos.ui_Address = pci_resource_start(card->pcidev, 2);
c995fe94
ADG
240#endif
241 } else {
c995fe94 242 n_subdevices = 7;
2f0b9d08 243 ret = comedi_alloc_subdevices(dev, n_subdevices);
8b6c5694 244 if (ret)
c995fe94
ADG
245 return ret;
246
2696fb57 247 /* Allocate and Initialise AI Subdevice Structures */
3237c964 248 s = &dev->subdevices[0];
57517878 249 if ((devpriv->s_EeParameters.i_NbrAiChannel)
c995fe94
ADG
250 || (this_board->i_NbrAiChannelDiff)) {
251 dev->read_subdev = s;
252 s->type = COMEDI_SUBD_AI;
253 s->subdev_flags =
fcea1154 254 SDF_READABLE | SDF_COMMON | SDF_GROUND
c995fe94 255 | SDF_DIFF;
57517878
IA
256 if (devpriv->s_EeParameters.i_NbrAiChannel) {
257 s->n_chan =
258 devpriv->s_EeParameters.i_NbrAiChannel;
c995fe94
ADG
259 devpriv->b_SingelDiff = 0;
260 } else {
261 s->n_chan = this_board->i_NbrAiChannelDiff;
262 devpriv->b_SingelDiff = 1;
263 }
57517878 264 s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
c995fe94
ADG
265 s->len_chanlist = this_board->i_AiChannelList;
266 s->range_table = this_board->pr_AiRangelist;
267
268 /* Set the initialisation flag */
269 devpriv->b_AiInitialisation = 1;
270
a19fb006
HS
271 s->insn_config = this_board->ai_config;
272 s->insn_read = this_board->ai_read;
273 s->insn_write = this_board->ai_write;
274 s->insn_bits = this_board->ai_bits;
275 s->do_cmdtest = this_board->ai_cmdtest;
276 s->do_cmd = this_board->ai_cmd;
277 s->cancel = this_board->ai_cancel;
c995fe94
ADG
278
279 } else {
280 s->type = COMEDI_SUBD_UNUSED;
281 }
282
2696fb57 283 /* Allocate and Initialise AO Subdevice Structures */
3237c964 284 s = &dev->subdevices[1];
57517878 285 if (devpriv->s_EeParameters.i_NbrAoChannel) {
c995fe94 286 s->type = COMEDI_SUBD_AO;
fcea1154 287 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
57517878
IA
288 s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
289 s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
290 s->len_chanlist =
291 devpriv->s_EeParameters.i_NbrAoChannel;
c995fe94 292 s->range_table = this_board->pr_AoRangelist;
a19fb006
HS
293 s->insn_config = this_board->ao_config;
294 s->insn_write = this_board->ao_write;
c995fe94
ADG
295 } else {
296 s->type = COMEDI_SUBD_UNUSED;
297 }
2696fb57 298 /* Allocate and Initialise DI Subdevice Structures */
3237c964 299 s = &dev->subdevices[2];
57517878 300 if (devpriv->s_EeParameters.i_NbrDiChannel) {
c995fe94 301 s->type = COMEDI_SUBD_DI;
fcea1154 302 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
57517878 303 s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
c995fe94 304 s->maxdata = 1;
57517878
IA
305 s->len_chanlist =
306 devpriv->s_EeParameters.i_NbrDiChannel;
c995fe94
ADG
307 s->range_table = &range_digital;
308 s->io_bits = 0; /* all bits input */
a19fb006
HS
309 s->insn_config = this_board->di_config;
310 s->insn_read = this_board->di_read;
311 s->insn_write = this_board->di_write;
312 s->insn_bits = this_board->di_bits;
c995fe94
ADG
313 } else {
314 s->type = COMEDI_SUBD_UNUSED;
315 }
2696fb57 316 /* Allocate and Initialise DO Subdevice Structures */
3237c964 317 s = &dev->subdevices[3];
57517878 318 if (devpriv->s_EeParameters.i_NbrDoChannel) {
c995fe94
ADG
319 s->type = COMEDI_SUBD_DO;
320 s->subdev_flags =
fcea1154 321 SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
57517878
IA
322 s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
323 s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
324 s->len_chanlist =
325 devpriv->s_EeParameters.i_NbrDoChannel;
c995fe94
ADG
326 s->range_table = &range_digital;
327 s->io_bits = 0xf; /* all bits output */
328
a19fb006
HS
329 /* insn_config - for digital output memory */
330 s->insn_config = this_board->do_config;
331 s->insn_write = this_board->do_write;
332 s->insn_bits = this_board->do_bits;
333 s->insn_read = this_board->do_read;
c995fe94
ADG
334 } else {
335 s->type = COMEDI_SUBD_UNUSED;
336 }
337
2696fb57 338 /* Allocate and Initialise Timer Subdevice Structures */
3237c964 339 s = &dev->subdevices[4];
57517878 340 if (devpriv->s_EeParameters.i_Timer) {
c995fe94 341 s->type = COMEDI_SUBD_TIMER;
fcea1154 342 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
c995fe94
ADG
343 s->n_chan = 1;
344 s->maxdata = 0;
345 s->len_chanlist = 1;
346 s->range_table = &range_digital;
347
a19fb006
HS
348 s->insn_write = this_board->timer_write;
349 s->insn_read = this_board->timer_read;
350 s->insn_config = this_board->timer_config;
351 s->insn_bits = this_board->timer_bits;
c995fe94
ADG
352 } else {
353 s->type = COMEDI_SUBD_UNUSED;
354 }
355
2696fb57 356 /* Allocate and Initialise TTL */
3237c964 357 s = &dev->subdevices[5];
c995fe94
ADG
358 if (this_board->i_NbrTTLChannel) {
359 s->type = COMEDI_SUBD_TTLIO;
360 s->subdev_flags =
fcea1154 361 SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
c995fe94
ADG
362 s->n_chan = this_board->i_NbrTTLChannel;
363 s->maxdata = 1;
364 s->io_bits = 0; /* all bits input */
365 s->len_chanlist = this_board->i_NbrTTLChannel;
366 s->range_table = &range_digital;
a19fb006
HS
367 s->insn_config = this_board->ttl_config;
368 s->insn_bits = this_board->ttl_bits;
369 s->insn_read = this_board->ttl_read;
370 s->insn_write = this_board->ttl_write;
c995fe94
ADG
371 } else {
372 s->type = COMEDI_SUBD_UNUSED;
373 }
374
375 /* EEPROM */
3237c964 376 s = &dev->subdevices[6];
c995fe94
ADG
377 if (this_board->i_PCIEeprom) {
378 s->type = COMEDI_SUBD_MEMORY;
379 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
380 s->n_chan = 256;
381 s->maxdata = 0xffff;
382 s->insn_read = i_ADDIDATA_InsnReadEeprom;
383 } else {
384 s->type = COMEDI_SUBD_UNUSED;
385 }
386 }
387
c995fe94
ADG
388 i_ADDI_Reset(dev);
389 devpriv->b_ValidDriver = 1;
390 return 0;
391}
392
484ecc95 393static void i_ADDI_Detach(struct comedi_device *dev)
c995fe94 394{
02913e06 395 const struct addi_board *this_board = comedi_board(dev);
843690b7
HS
396 struct addi_private *devpriv = dev->private;
397
398 if (devpriv) {
484ecc95 399 if (devpriv->b_ValidDriver)
c995fe94 400 i_ADDI_Reset(dev);
484ecc95 401 if (dev->irq)
5f74ea14 402 free_irq(dev->irq, dev);
484ecc95
HS
403 if ((this_board->pc_EepromChip == NULL) ||
404 (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
405 if (devpriv->allocated)
c995fe94 406 i_pci_card_free(devpriv->amcc);
c995fe94
ADG
407 if (devpriv->ul_DmaBufferVirtual[0]) {
408 free_pages((unsigned long)devpriv->
409 ul_DmaBufferVirtual[0],
410 devpriv->ui_DmaBufferPages[0]);
411 }
c995fe94
ADG
412 if (devpriv->ul_DmaBufferVirtual[1]) {
413 free_pages((unsigned long)devpriv->
414 ul_DmaBufferVirtual[1],
415 devpriv->ui_DmaBufferPages[1]);
416 }
417 } else {
2f78c642 418 iounmap(devpriv->dw_AiBase);
484ecc95 419 if (devpriv->allocated)
c995fe94 420 i_pci_card_free(devpriv->amcc);
c995fe94 421 }
c995fe94 422 if (pci_list_builded) {
c995fe94
ADG
423 v_pci_card_list_cleanup(this_board->i_VendorId);
424 pci_list_builded = 0;
425 }
426 }
c995fe94 427}