[go: nahoru, domu]

1/**
2@verbatim
3
4Copyright (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
14This program is free software; you can redistribute it and/or modify it under
15the terms of the GNU General Public License as published by the Free Software
16Foundation; either version 2 of the License, or (at your option) any later
17version.
18
19This program is distributed in the hope that it will be useful, but WITHOUT ANY
20WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21PARTICULAR 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
42static 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 = dev->board_ptr;
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
59static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
60{
61	struct comedi_device *dev = d;
62	const struct addi_board *this_board = dev->board_ptr;
63
64	this_board->interrupt(irq, d);
65	return IRQ_RETVAL(1);
66}
67
68static int i_ADDI_Reset(struct comedi_device *dev)
69{
70	const struct addi_board *this_board = dev->board_ptr;
71
72	this_board->reset(dev);
73	return 0;
74}
75
76static 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 = dev->board_ptr;
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 = devpriv->s_EeParameters.i_NbrAiChannel;
162		else
163			s->n_chan = this_board->i_NbrAiChannelDiff;
164		s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
165		s->len_chanlist = this_board->i_AiChannelList;
166		s->range_table = this_board->pr_AiRangelist;
167
168		s->insn_config = this_board->ai_config;
169		s->insn_read = this_board->ai_read;
170		s->insn_write = this_board->ai_write;
171		s->insn_bits = this_board->ai_bits;
172		s->do_cmdtest = this_board->ai_cmdtest;
173		s->do_cmd = this_board->ai_cmd;
174		s->cancel = this_board->ai_cancel;
175
176	} else {
177		s->type = COMEDI_SUBD_UNUSED;
178	}
179
180	/*  Allocate and Initialise AO Subdevice Structures */
181	s = &dev->subdevices[1];
182	if (devpriv->s_EeParameters.i_NbrAoChannel) {
183		s->type = COMEDI_SUBD_AO;
184		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
185		s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
186		s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
187		s->len_chanlist =
188			devpriv->s_EeParameters.i_NbrAoChannel;
189		s->insn_write = this_board->ao_write;
190	} else {
191		s->type = COMEDI_SUBD_UNUSED;
192	}
193	/*  Allocate and Initialise DI Subdevice Structures */
194	s = &dev->subdevices[2];
195	if (devpriv->s_EeParameters.i_NbrDiChannel) {
196		s->type = COMEDI_SUBD_DI;
197		s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
198		s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
199		s->maxdata = 1;
200		s->len_chanlist =
201			devpriv->s_EeParameters.i_NbrDiChannel;
202		s->range_table = &range_digital;
203		s->insn_config = this_board->di_config;
204		s->insn_read = this_board->di_read;
205		s->insn_write = this_board->di_write;
206		s->insn_bits = this_board->di_bits;
207	} else {
208		s->type = COMEDI_SUBD_UNUSED;
209	}
210	/*  Allocate and Initialise DO Subdevice Structures */
211	s = &dev->subdevices[3];
212	if (devpriv->s_EeParameters.i_NbrDoChannel) {
213		s->type = COMEDI_SUBD_DO;
214		s->subdev_flags =
215			SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
216		s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
217		s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
218		s->len_chanlist =
219			devpriv->s_EeParameters.i_NbrDoChannel;
220		s->range_table = &range_digital;
221
222		/* insn_config - for digital output memory */
223		s->insn_config = this_board->do_config;
224		s->insn_write = this_board->do_write;
225		s->insn_bits = this_board->do_bits;
226		s->insn_read = this_board->do_read;
227	} else {
228		s->type = COMEDI_SUBD_UNUSED;
229	}
230
231	/*  Allocate and Initialise Timer Subdevice Structures */
232	s = &dev->subdevices[4];
233	if (devpriv->s_EeParameters.i_Timer) {
234		s->type = COMEDI_SUBD_TIMER;
235		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
236		s->n_chan = 1;
237		s->maxdata = 0;
238		s->len_chanlist = 1;
239		s->range_table = &range_digital;
240
241		s->insn_write = this_board->timer_write;
242		s->insn_read = this_board->timer_read;
243		s->insn_config = this_board->timer_config;
244		s->insn_bits = this_board->timer_bits;
245	} else {
246		s->type = COMEDI_SUBD_UNUSED;
247	}
248
249	/*  Allocate and Initialise TTL */
250	s = &dev->subdevices[5];
251	s->type = COMEDI_SUBD_UNUSED;
252
253	/* EEPROM */
254	s = &dev->subdevices[6];
255	if (this_board->i_PCIEeprom) {
256		s->type = COMEDI_SUBD_MEMORY;
257		s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
258		s->n_chan = 256;
259		s->maxdata = 0xffff;
260		s->insn_read = i_ADDIDATA_InsnReadEeprom;
261	} else {
262		s->type = COMEDI_SUBD_UNUSED;
263	}
264
265	i_ADDI_Reset(dev);
266	return 0;
267}
268
269static void i_ADDI_Detach(struct comedi_device *dev)
270{
271	if (dev->iobase)
272		i_ADDI_Reset(dev);
273	comedi_pci_detach(dev);
274}
275