addi_apci_3xxx.c revision 178bd8d3a61432ce24399604b13cc756293d1ac8
1#include <linux/pci.h>
2
3#include "../comedidev.h"
4#include "comedi_fc.h"
5#include "amcc_s5933.h"
6
7#include "addi-data/addi_common.h"
8
9#include "addi-data/addi_eeprom.c"
10#include "addi-data/hwdrv_apci3xxx.c"
11
12#ifndef COMEDI_SUBD_TTLIO
13#define COMEDI_SUBD_TTLIO   11	/* Digital Input Output But TTL */
14#endif
15
16static const struct comedi_lrange apci3xxx_ai_range = {
17	8, {
18		BIP_RANGE(10),
19		BIP_RANGE(5),
20		BIP_RANGE(2),
21		BIP_RANGE(1),
22		UNI_RANGE(10),
23		UNI_RANGE(5),
24		UNI_RANGE(2),
25		UNI_RANGE(1)
26	}
27};
28
29static const struct comedi_lrange apci3xxx_ao_range = {
30	2, {
31		BIP_RANGE(10),
32		UNI_RANGE(10)
33	}
34};
35
36enum apci3xxx_boardid {
37	BOARD_APCI3000_16,
38	BOARD_APCI3000_8,
39	BOARD_APCI3000_4,
40	BOARD_APCI3006_16,
41	BOARD_APCI3006_8,
42	BOARD_APCI3006_4,
43	BOARD_APCI3010_16,
44	BOARD_APCI3010_8,
45	BOARD_APCI3010_4,
46	BOARD_APCI3016_16,
47	BOARD_APCI3016_8,
48	BOARD_APCI3016_4,
49	BOARD_APCI3100_16_4,
50	BOARD_APCI3100_8_4,
51	BOARD_APCI3106_16_4,
52	BOARD_APCI3106_8_4,
53	BOARD_APCI3110_16_4,
54	BOARD_APCI3110_8_4,
55	BOARD_APCI3116_16_4,
56	BOARD_APCI3116_8_4,
57	BOARD_APCI3003,
58	BOARD_APCI3002_16,
59	BOARD_APCI3002_8,
60	BOARD_APCI3002_4,
61	BOARD_APCI3500,
62};
63
64static const struct addi_board apci3xxx_boardtypes[] = {
65	[BOARD_APCI3000_16] = {
66		.pc_DriverName		= "apci3000-16",
67		.i_IorangeBase1		= 256,
68		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
69		.pc_EepromChip		= ADDIDATA_9054,
70		.i_NbrAiChannel		= 16,
71		.i_NbrAiChannelDiff	= 8,
72		.i_AiChannelList	= 16,
73		.i_AiMaxdata		= 4095,
74		.i_NbrTTLChannel	= 24,
75		.b_AvailableConvertUnit	= 6,
76		.ui_MinAcquisitiontimeNs = 10000,
77		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
78		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
79		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
80		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
81		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
82		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
83	},
84	[BOARD_APCI3000_8] = {
85		.pc_DriverName		= "apci3000-8",
86		.i_IorangeBase1		= 256,
87		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
88		.pc_EepromChip		= ADDIDATA_9054,
89		.i_NbrAiChannel		= 8,
90		.i_NbrAiChannelDiff	= 4,
91		.i_AiChannelList	= 8,
92		.i_AiMaxdata		= 4095,
93		.i_NbrTTLChannel	= 24,
94		.b_AvailableConvertUnit	= 6,
95		.ui_MinAcquisitiontimeNs = 10000,
96		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
97		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
98		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
99		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
100		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
101		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
102	},
103	[BOARD_APCI3000_4] = {
104		.pc_DriverName		= "apci3000-4",
105		.i_IorangeBase1		= 256,
106		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
107		.pc_EepromChip		= ADDIDATA_9054,
108		.i_NbrAiChannel		= 4,
109		.i_NbrAiChannelDiff	= 2,
110		.i_AiChannelList	= 4,
111		.i_AiMaxdata		= 4095,
112		.i_NbrTTLChannel	= 24,
113		.b_AvailableConvertUnit	= 6,
114		.ui_MinAcquisitiontimeNs = 10000,
115		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
116		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
117		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
118		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
119		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
120		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
121	},
122	[BOARD_APCI3006_16] = {
123		.pc_DriverName		= "apci3006-16",
124		.i_IorangeBase1		= 256,
125		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
126		.pc_EepromChip		= ADDIDATA_9054,
127		.i_NbrAiChannel		= 16,
128		.i_NbrAiChannelDiff	= 8,
129		.i_AiChannelList	= 16,
130		.i_AiMaxdata		= 65535,
131		.i_NbrTTLChannel	= 24,
132		.b_AvailableConvertUnit	= 6,
133		.ui_MinAcquisitiontimeNs = 10000,
134		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
135		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
136		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
137		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
138		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
139		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
140	},
141	[BOARD_APCI3006_8] = {
142		.pc_DriverName		= "apci3006-8",
143		.i_IorangeBase1		= 256,
144		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
145		.pc_EepromChip		= ADDIDATA_9054,
146		.i_NbrAiChannel		= 8,
147		.i_NbrAiChannelDiff	= 4,
148		.i_AiChannelList	= 8,
149		.i_AiMaxdata		= 65535,
150		.i_NbrTTLChannel	= 24,
151		.b_AvailableConvertUnit	= 6,
152		.ui_MinAcquisitiontimeNs = 10000,
153		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
154		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
155		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
156		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
157		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
158		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
159	},
160	[BOARD_APCI3006_4] = {
161		.pc_DriverName		= "apci3006-4",
162		.i_IorangeBase1		= 256,
163		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
164		.pc_EepromChip		= ADDIDATA_9054,
165		.i_NbrAiChannel		= 4,
166		.i_NbrAiChannelDiff	= 2,
167		.i_AiChannelList	= 4,
168		.i_AiMaxdata		= 65535,
169		.i_NbrTTLChannel	= 24,
170		.b_AvailableConvertUnit	= 6,
171		.ui_MinAcquisitiontimeNs = 10000,
172		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
173		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
174		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
175		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
176		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
177		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
178	},
179	[BOARD_APCI3010_16] = {
180		.pc_DriverName		= "apci3010-16",
181		.i_IorangeBase1		= 256,
182		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
183		.pc_EepromChip		= ADDIDATA_9054,
184		.i_NbrAiChannel		= 16,
185		.i_NbrAiChannelDiff	= 8,
186		.i_AiChannelList	= 16,
187		.i_AiMaxdata		= 4095,
188		.i_NbrDiChannel		= 4,
189		.i_NbrDoChannel		= 4,
190		.i_DoMaxdata		= 1,
191		.i_NbrTTLChannel	= 24,
192		.b_AvailableConvertUnit	= 6,
193		.ui_MinAcquisitiontimeNs = 5000,
194		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
195		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
196		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
197		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
198		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
199		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
200	},
201	[BOARD_APCI3010_8] = {
202		.pc_DriverName		= "apci3010-8",
203		.i_IorangeBase1		= 256,
204		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
205		.pc_EepromChip		= ADDIDATA_9054,
206		.i_NbrAiChannel		= 8,
207		.i_NbrAiChannelDiff	= 4,
208		.i_AiChannelList	= 8,
209		.i_AiMaxdata		= 4095,
210		.i_NbrDiChannel		= 4,
211		.i_NbrDoChannel		= 4,
212		.i_DoMaxdata		= 1,
213		.i_NbrTTLChannel	= 24,
214		.b_AvailableConvertUnit	= 6,
215		.ui_MinAcquisitiontimeNs = 5000,
216		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
217		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
218		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
219		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
220		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
221		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
222	},
223	[BOARD_APCI3010_4] = {
224		.pc_DriverName		= "apci3010-4",
225		.i_IorangeBase1		= 256,
226		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
227		.pc_EepromChip		= ADDIDATA_9054,
228		.i_NbrAiChannel		= 4,
229		.i_NbrAiChannelDiff	= 2,
230		.i_AiChannelList	= 4,
231		.i_AiMaxdata		= 4095,
232		.i_NbrDiChannel		= 4,
233		.i_NbrDoChannel		= 4,
234		.i_DoMaxdata		= 1,
235		.i_NbrTTLChannel	= 24,
236		.b_AvailableConvertUnit	= 6,
237		.ui_MinAcquisitiontimeNs = 5000,
238		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
239		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
240		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
241		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
242		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
243		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
244	},
245	[BOARD_APCI3016_16] = {
246		.pc_DriverName		= "apci3016-16",
247		.i_IorangeBase1		= 256,
248		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
249		.pc_EepromChip		= ADDIDATA_9054,
250		.i_NbrAiChannel		= 16,
251		.i_NbrAiChannelDiff	= 8,
252		.i_AiChannelList	= 16,
253		.i_AiMaxdata		= 65535,
254		.i_NbrDiChannel		= 4,
255		.i_NbrDoChannel		= 4,
256		.i_DoMaxdata		= 1,
257		.i_NbrTTLChannel	= 24,
258		.b_AvailableConvertUnit	= 6,
259		.ui_MinAcquisitiontimeNs = 5000,
260		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
261		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
262		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
263		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
264		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
265		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
266	},
267	[BOARD_APCI3016_8] = {
268		.pc_DriverName		= "apci3016-8",
269		.i_IorangeBase1		= 256,
270		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
271		.pc_EepromChip		= ADDIDATA_9054,
272		.i_NbrAiChannel		= 8,
273		.i_NbrAiChannelDiff	= 4,
274		.i_AiChannelList	= 8,
275		.i_AiMaxdata		= 65535,
276		.i_NbrDiChannel		= 4,
277		.i_NbrDoChannel		= 4,
278		.i_DoMaxdata		= 1,
279		.i_NbrTTLChannel	= 24,
280		.b_AvailableConvertUnit	= 6,
281		.ui_MinAcquisitiontimeNs = 5000,
282		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
283		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
284		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
285		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
286		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
287		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
288	},
289	[BOARD_APCI3016_4] = {
290		.pc_DriverName		= "apci3016-4",
291		.i_IorangeBase1		= 256,
292		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
293		.pc_EepromChip		= ADDIDATA_9054,
294		.i_NbrAiChannel		= 4,
295		.i_NbrAiChannelDiff	= 2,
296		.i_AiChannelList	= 4,
297		.i_AiMaxdata		= 65535,
298		.i_NbrDiChannel		= 4,
299		.i_NbrDoChannel		= 4,
300		.i_DoMaxdata		= 1,
301		.i_NbrTTLChannel	= 24,
302		.b_AvailableConvertUnit	= 6,
303		.ui_MinAcquisitiontimeNs = 5000,
304		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
305		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
306		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
307		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
308		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
309		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
310	},
311	[BOARD_APCI3100_16_4] = {
312		.pc_DriverName		= "apci3100-16-4",
313		.i_IorangeBase1		= 256,
314		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
315		.pc_EepromChip		= ADDIDATA_9054,
316		.i_NbrAiChannel		= 16,
317		.i_NbrAiChannelDiff	= 8,
318		.i_AiChannelList	= 16,
319		.i_NbrAoChannel		= 4,
320		.i_AiMaxdata		= 4095,
321		.i_AoMaxdata		= 4095,
322		.i_NbrTTLChannel	= 24,
323		.b_AvailableConvertUnit	= 6,
324		.ui_MinAcquisitiontimeNs = 10000,
325		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
326		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
327		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
328		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
329		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
330		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
331		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
332	},
333	[BOARD_APCI3100_8_4] = {
334		.pc_DriverName		= "apci3100-8-4",
335		.i_IorangeBase1		= 256,
336		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
337		.pc_EepromChip		= ADDIDATA_9054,
338		.i_NbrAiChannel		= 8,
339		.i_NbrAiChannelDiff	= 4,
340		.i_AiChannelList	= 8,
341		.i_NbrAoChannel		= 4,
342		.i_AiMaxdata		= 4095,
343		.i_AoMaxdata		= 4095,
344		.i_NbrTTLChannel	= 24,
345		.b_AvailableConvertUnit	= 6,
346		.ui_MinAcquisitiontimeNs = 10000,
347		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
348		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
349		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
350		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
351		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
352		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
353		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
354	},
355	[BOARD_APCI3106_16_4] = {
356		.pc_DriverName		= "apci3106-16-4",
357		.i_IorangeBase1		= 256,
358		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
359		.pc_EepromChip		= ADDIDATA_9054,
360		.i_NbrAiChannel		= 16,
361		.i_NbrAiChannelDiff	= 8,
362		.i_AiChannelList	= 16,
363		.i_NbrAoChannel		= 4,
364		.i_AiMaxdata		= 65535,
365		.i_AoMaxdata		= 4095,
366		.i_NbrTTLChannel	= 24,
367		.b_AvailableConvertUnit	= 6,
368		.ui_MinAcquisitiontimeNs = 10000,
369		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
370		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
371		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
372		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
373		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
374		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
375		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
376	},
377	[BOARD_APCI3106_8_4] = {
378		.pc_DriverName		= "apci3106-8-4",
379		.i_IorangeBase1		= 256,
380		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
381		.pc_EepromChip		= ADDIDATA_9054,
382		.i_NbrAiChannel		= 8,
383		.i_NbrAiChannelDiff	= 4,
384		.i_AiChannelList	= 8,
385		.i_NbrAoChannel		= 4,
386		.i_AiMaxdata		= 65535,
387		.i_AoMaxdata		= 4095,
388		.i_NbrTTLChannel	= 24,
389		.b_AvailableConvertUnit	= 6,
390		.ui_MinAcquisitiontimeNs = 10000,
391		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
392		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
393		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
394		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
395		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
396		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
397		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
398	},
399	[BOARD_APCI3110_16_4] = {
400		.pc_DriverName		= "apci3110-16-4",
401		.i_IorangeBase1		= 256,
402		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
403		.pc_EepromChip		= ADDIDATA_9054,
404		.i_NbrAiChannel		= 16,
405		.i_NbrAiChannelDiff	= 8,
406		.i_AiChannelList	= 16,
407		.i_NbrAoChannel		= 4,
408		.i_AiMaxdata		= 4095,
409		.i_AoMaxdata		= 4095,
410		.i_NbrDiChannel		= 4,
411		.i_NbrDoChannel		= 4,
412		.i_DoMaxdata		= 1,
413		.i_NbrTTLChannel	= 24,
414		.b_AvailableConvertUnit	= 6,
415		.ui_MinAcquisitiontimeNs = 5000,
416		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
417		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
418		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
419		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
420		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
421		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
422		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
423	},
424	[BOARD_APCI3110_8_4] = {
425		.pc_DriverName		= "apci3110-8-4",
426		.i_IorangeBase1		= 256,
427		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
428		.pc_EepromChip		= ADDIDATA_9054,
429		.i_NbrAiChannel		= 8,
430		.i_NbrAiChannelDiff	= 4,
431		.i_AiChannelList	= 8,
432		.i_NbrAoChannel		= 4,
433		.i_AiMaxdata		= 4095,
434		.i_AoMaxdata		= 4095,
435		.i_NbrDiChannel		= 4,
436		.i_NbrDoChannel		= 4,
437		.i_DoMaxdata		= 1,
438		.i_NbrTTLChannel	= 24,
439		.b_AvailableConvertUnit	= 6,
440		.ui_MinAcquisitiontimeNs = 5000,
441		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
442		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
443		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
444		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
445		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
446		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
447		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
448	},
449	[BOARD_APCI3116_16_4] = {
450		.pc_DriverName		= "apci3116-16-4",
451		.i_IorangeBase1		= 256,
452		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
453		.pc_EepromChip		= ADDIDATA_9054,
454		.i_NbrAiChannel		= 16,
455		.i_NbrAiChannelDiff	= 8,
456		.i_AiChannelList	= 16,
457		.i_NbrAoChannel		= 4,
458		.i_AiMaxdata		= 65535,
459		.i_AoMaxdata		= 4095,
460		.i_NbrDiChannel		= 4,
461		.i_NbrDoChannel		= 4,
462		.i_DoMaxdata		= 1,
463		.i_NbrTTLChannel	= 24,
464		.b_AvailableConvertUnit	= 6,
465		.ui_MinAcquisitiontimeNs = 5000,
466		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
467		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
468		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
469		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
470		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
471		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
472		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
473	},
474	[BOARD_APCI3116_8_4] = {
475		.pc_DriverName		= "apci3116-8-4",
476		.i_IorangeBase1		= 256,
477		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
478		.pc_EepromChip		= ADDIDATA_9054,
479		.i_NbrAiChannel		= 8,
480		.i_NbrAiChannelDiff	= 4,
481		.i_AiChannelList	= 8,
482		.i_NbrAoChannel		= 4,
483		.i_AiMaxdata		= 65535,
484		.i_AoMaxdata		= 4095,
485		.i_NbrDiChannel		= 4,
486		.i_NbrDoChannel		= 4,
487		.i_DoMaxdata		= 1,
488		.i_NbrTTLChannel	= 24,
489		.b_AvailableConvertUnit	= 6,
490		.ui_MinAcquisitiontimeNs = 5000,
491		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
492		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
493		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
494		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
495		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
496		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
497		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
498	},
499	[BOARD_APCI3003] = {
500		.pc_DriverName		= "apci3003",
501		.i_IorangeBase1		= 256,
502		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
503		.pc_EepromChip		= ADDIDATA_9054,
504		.i_NbrAiChannelDiff	= 4,
505		.i_AiChannelList	= 4,
506		.i_AiMaxdata		= 65535,
507		.i_NbrDiChannel		= 4,
508		.i_NbrDoChannel		= 4,
509		.i_DoMaxdata		= 1,
510		.b_AvailableConvertUnit	= 7,
511		.ui_MinAcquisitiontimeNs = 2500,
512		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
513		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
514	},
515	[BOARD_APCI3002_16] = {
516		.pc_DriverName		= "apci3002-16",
517		.i_IorangeBase1		= 256,
518		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
519		.pc_EepromChip		= ADDIDATA_9054,
520		.i_NbrAiChannelDiff	= 16,
521		.i_AiChannelList	= 16,
522		.i_AiMaxdata		= 65535,
523		.i_NbrDiChannel		= 4,
524		.i_NbrDoChannel		= 4,
525		.i_DoMaxdata		= 1,
526		.b_AvailableConvertUnit	= 6,
527		.ui_MinAcquisitiontimeNs = 5000,
528		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
529		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
530	},
531	[BOARD_APCI3002_8] = {
532		.pc_DriverName		= "apci3002-8",
533		.i_IorangeBase1		= 256,
534		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
535		.pc_EepromChip		= ADDIDATA_9054,
536		.i_NbrAiChannelDiff	= 8,
537		.i_AiChannelList	= 8,
538		.i_AiMaxdata		= 65535,
539		.i_NbrDiChannel		= 4,
540		.i_NbrDoChannel		= 4,
541		.i_DoMaxdata		= 1,
542		.b_AvailableConvertUnit	= 6,
543		.ui_MinAcquisitiontimeNs = 5000,
544		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
545		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
546	},
547	[BOARD_APCI3002_4] = {
548		.pc_DriverName		= "apci3002-4",
549		.i_IorangeBase1		= 256,
550		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
551		.pc_EepromChip		= ADDIDATA_9054,
552		.i_NbrAiChannelDiff	= 4,
553		.i_AiChannelList	= 4,
554		.i_AiMaxdata		= 65535,
555		.i_NbrDiChannel		= 4,
556		.i_NbrDoChannel		= 4,
557		.i_DoMaxdata		= 1,
558		.b_AvailableConvertUnit	= 6,
559		.ui_MinAcquisitiontimeNs = 5000,
560		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
561		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
562	},
563	[BOARD_APCI3500] = {
564		.pc_DriverName		= "apci3500",
565		.i_IorangeBase1		= 256,
566		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
567		.pc_EepromChip		= ADDIDATA_9054,
568		.i_NbrAoChannel		= 4,
569		.i_AoMaxdata		= 4095,
570		.i_NbrTTLChannel	= 24,
571		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
572		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
573		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
574		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
575		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
576	},
577};
578
579static irqreturn_t apci3xxx_irq_handler(int irq, void *d)
580{
581	struct comedi_device *dev = d;
582	struct addi_private *devpriv = dev->private;
583	unsigned int status;
584	int i;
585
586	/* Test if interrupt occur */
587	status = readl(devpriv->dw_AiBase + 16);
588	if ((status & 0x2) == 0x2) {
589		/* Reset the interrupt */
590		writel(status, devpriv->dw_AiBase + 16);
591
592		/* Test if interrupt enabled */
593		if (devpriv->b_EocEosInterrupt == 1) {
594			/* Read all analog inputs value */
595			for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
596				unsigned int val;
597
598				val = readl(devpriv->dw_AiBase + 28);
599				devpriv->ui_AiReadData[i] = val;
600			}
601
602			/* Set the interrupt flag */
603			devpriv->b_EocEosInterrupt = 2;
604
605			/* Send a signal to from kernel to user space */
606			send_sig(SIGIO, devpriv->tsk_Current, 0);
607		}
608	}
609	return IRQ_RETVAL(1);
610}
611
612static int apci3xxx_di_insn_bits(struct comedi_device *dev,
613				 struct comedi_subdevice *s,
614				 struct comedi_insn *insn,
615				 unsigned int *data)
616{
617	struct addi_private *devpriv = dev->private;
618
619	data[1] = inl(devpriv->iobase + 32) & 0xf;
620
621	return insn->n;
622}
623
624static int apci3xxx_do_insn_bits(struct comedi_device *dev,
625				 struct comedi_subdevice *s,
626				 struct comedi_insn *insn,
627				 unsigned int *data)
628{
629	struct addi_private *devpriv = dev->private;
630	unsigned int mask = data[0];
631	unsigned int bits = data[1];
632
633	s->state = inl(devpriv->iobase + 48) & 0xf;
634	if (mask) {
635		s->state &= ~mask;
636		s->state |= (bits & mask);
637
638		outl(s->state, devpriv->iobase + 48);
639	}
640
641	data[1] = s->state;
642
643	return insn->n;
644}
645
646static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
647				     struct comedi_subdevice *s,
648				     struct comedi_insn *insn,
649				     unsigned int *data)
650{
651	const struct addi_board *this_board = comedi_board(dev);
652	struct addi_private *devpriv = dev->private;
653	unsigned short w_Address = CR_CHAN(insn->chanspec);
654	unsigned short w_Data;
655
656	w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
657		this_board->pc_EepromChip, 2 * w_Address);
658	data[0] = w_Data;
659
660	return insn->n;
661}
662
663static int apci3xxx_reset(struct comedi_device *dev)
664{
665	struct addi_private *devpriv = dev->private;
666	unsigned int val;
667	int i;
668
669	/* Disable the interrupt */
670	disable_irq(dev->irq);
671
672	/* Reset the interrupt flag */
673	devpriv->b_EocEosInterrupt = 0;
674
675	/* Clear the start command */
676	writel(0, devpriv->dw_AiBase + 8);
677
678	/* Reset the interrupt flags */
679	val = readl(devpriv->dw_AiBase + 16);
680	writel(val, devpriv->dw_AiBase + 16);
681
682	/* clear the EOS */
683	readl(devpriv->dw_AiBase + 20);
684
685	/* Clear the FIFO */
686	for (i = 0; i < 16; i++)
687		val = readl(devpriv->dw_AiBase + 28);
688
689	/* Enable the interrupt */
690	enable_irq(dev->irq);
691
692	return 0;
693}
694
695static int apci3xxx_auto_attach(struct comedi_device *dev,
696				unsigned long context)
697{
698	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
699	const struct addi_board *board = NULL;
700	struct addi_private *devpriv;
701	struct comedi_subdevice *s;
702	int ret, n_subdevices;
703	unsigned int dw_Dummy;
704
705	if (context < ARRAY_SIZE(apci3xxx_boardtypes))
706		board = &apci3xxx_boardtypes[context];
707	if (!board)
708		return -ENODEV;
709	dev->board_ptr = board;
710	dev->board_name = board->pc_DriverName;
711
712	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
713	if (!devpriv)
714		return -ENOMEM;
715	dev->private = devpriv;
716
717	ret = comedi_pci_enable(dev);
718	if (ret)
719		return ret;
720
721	/* board has an ADDIDATA_9054 eeprom */
722	dev->iobase = pci_resource_start(pcidev, 2);
723	devpriv->iobase = pci_resource_start(pcidev, 2);
724	devpriv->dw_AiBase = pci_ioremap_bar(pcidev, 3);
725	devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
726
727	/* Initialize parameters that can be overridden in EEPROM */
728	devpriv->s_EeParameters.i_NbrAiChannel = board->i_NbrAiChannel;
729	devpriv->s_EeParameters.i_NbrAoChannel = board->i_NbrAoChannel;
730	devpriv->s_EeParameters.i_AiMaxdata = board->i_AiMaxdata;
731	devpriv->s_EeParameters.i_AoMaxdata = board->i_AoMaxdata;
732	devpriv->s_EeParameters.i_NbrDiChannel = board->i_NbrDiChannel;
733	devpriv->s_EeParameters.i_NbrDoChannel = board->i_NbrDoChannel;
734	devpriv->s_EeParameters.i_DoMaxdata = board->i_DoMaxdata;
735	devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
736						board->ui_MinAcquisitiontimeNs;
737	devpriv->s_EeParameters.ui_MinDelaytimeNs = board->ui_MinDelaytimeNs;
738
739	/* ## */
740
741	if (pcidev->irq > 0) {
742		ret = request_irq(pcidev->irq, apci3xxx_irq_handler,
743				  IRQF_SHARED, dev->board_name, dev);
744		if (ret == 0)
745			dev->irq = pcidev->irq;
746	}
747
748	/*  Read eepeom and fill addi_board Structure */
749
750	if (board->i_PCIEeprom) {
751		if (!(strcmp(board->pc_EepromChip, "S5920"))) {
752			/*  Set 3 wait stait */
753			if (!(strcmp(dev->board_name, "apci035")))
754				outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
755			else
756				outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
757
758			/*  Enable the interrupt for the controller */
759			dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
760			outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
761		}
762		addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
763	}
764
765	n_subdevices = 7;
766	ret = comedi_alloc_subdevices(dev, n_subdevices);
767	if (ret)
768		return ret;
769
770	/*  Allocate and Initialise AI Subdevice Structures */
771	s = &dev->subdevices[0];
772	if (devpriv->s_EeParameters.i_NbrAiChannel ||
773	    board->i_NbrAiChannelDiff) {
774		dev->read_subdev = s;
775		s->type = COMEDI_SUBD_AI;
776		s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND |
777				  SDF_DIFF;
778		if (devpriv->s_EeParameters.i_NbrAiChannel) {
779			s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel;
780			devpriv->b_SingelDiff = 0;
781		} else {
782			s->n_chan = board->i_NbrAiChannelDiff;
783			devpriv->b_SingelDiff = 1;
784		}
785		s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
786		s->len_chanlist = board->i_AiChannelList;
787		s->range_table = &apci3xxx_ai_range;
788
789		/* Set the initialisation flag */
790		devpriv->b_AiInitialisation = 1;
791
792		s->insn_config = board->ai_config;
793		s->insn_read = board->ai_read;
794		s->insn_write = board->ai_write;
795		s->insn_bits = board->ai_bits;
796		s->do_cmdtest = board->ai_cmdtest;
797		s->do_cmd = board->ai_cmd;
798		s->cancel = board->ai_cancel;
799
800	} else {
801		s->type = COMEDI_SUBD_UNUSED;
802	}
803
804	/*  Allocate and Initialise AO Subdevice Structures */
805	s = &dev->subdevices[1];
806	if (devpriv->s_EeParameters.i_NbrAoChannel) {
807		s->type = COMEDI_SUBD_AO;
808		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
809		s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
810		s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
811		s->len_chanlist = devpriv->s_EeParameters.i_NbrAoChannel;
812		s->range_table = &apci3xxx_ao_range;
813		s->insn_config = board->ao_config;
814		s->insn_write = board->ao_write;
815	} else {
816		s->type = COMEDI_SUBD_UNUSED;
817	}
818	/*  Allocate and Initialise DI Subdevice Structures */
819	s = &dev->subdevices[2];
820	if (devpriv->s_EeParameters.i_NbrDiChannel) {
821		s->type = COMEDI_SUBD_DI;
822		s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
823		s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
824		s->maxdata = 1;
825		s->len_chanlist = devpriv->s_EeParameters.i_NbrDiChannel;
826		s->range_table = &range_digital;
827		s->io_bits = 0;	/* all bits input */
828		s->insn_bits = apci3xxx_di_insn_bits;
829	} else {
830		s->type = COMEDI_SUBD_UNUSED;
831	}
832	/*  Allocate and Initialise DO Subdevice Structures */
833	s = &dev->subdevices[3];
834	if (devpriv->s_EeParameters.i_NbrDoChannel) {
835		s->type = COMEDI_SUBD_DO;
836		s->subdev_flags =
837			SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
838		s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
839		s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
840		s->len_chanlist = devpriv->s_EeParameters.i_NbrDoChannel;
841		s->range_table = &range_digital;
842		s->io_bits = 0xf;	/* all bits output */
843		s->insn_bits = apci3xxx_do_insn_bits;
844	} else {
845		s->type = COMEDI_SUBD_UNUSED;
846	}
847
848	/*  Allocate and Initialise Timer Subdevice Structures */
849	s = &dev->subdevices[4];
850	s->type = COMEDI_SUBD_UNUSED;
851
852	/*  Allocate and Initialise TTL */
853	s = &dev->subdevices[5];
854	if (board->i_NbrTTLChannel) {
855		s->type = COMEDI_SUBD_TTLIO;
856		s->subdev_flags =
857			SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
858		s->n_chan = board->i_NbrTTLChannel;
859		s->maxdata = 1;
860		s->io_bits = 0;	/* all bits input */
861		s->len_chanlist = board->i_NbrTTLChannel;
862		s->range_table = &range_digital;
863		s->insn_config = board->ttl_config;
864		s->insn_bits = board->ttl_bits;
865		s->insn_read = board->ttl_read;
866		s->insn_write = board->ttl_write;
867	} else {
868		s->type = COMEDI_SUBD_UNUSED;
869	}
870
871	/* EEPROM */
872	s = &dev->subdevices[6];
873	if (board->i_PCIEeprom) {
874		s->type = COMEDI_SUBD_MEMORY;
875		s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
876		s->n_chan = 256;
877		s->maxdata = 0xffff;
878		s->insn_read = i_ADDIDATA_InsnReadEeprom;
879	} else {
880		s->type = COMEDI_SUBD_UNUSED;
881	}
882
883	apci3xxx_reset(dev);
884	return 0;
885}
886
887static void apci3xxx_detach(struct comedi_device *dev)
888{
889	struct addi_private *devpriv = dev->private;
890
891	if (devpriv) {
892		if (dev->iobase)
893			apci3xxx_reset(dev);
894		if (dev->irq)
895			free_irq(dev->irq, dev);
896		if (devpriv->dw_AiBase)
897			iounmap(devpriv->dw_AiBase);
898	}
899	comedi_pci_disable(dev);
900}
901
902static struct comedi_driver apci3xxx_driver = {
903	.driver_name	= "addi_apci_3xxx",
904	.module		= THIS_MODULE,
905	.auto_attach	= apci3xxx_auto_attach,
906	.detach		= apci3xxx_detach,
907};
908
909static int apci3xxx_pci_probe(struct pci_dev *dev,
910			      const struct pci_device_id *id)
911{
912	return comedi_pci_auto_config(dev, &apci3xxx_driver, id->driver_data);
913}
914
915static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = {
916	{ PCI_VDEVICE(ADDIDATA, 0x3010), BOARD_APCI3000_16 },
917	{ PCI_VDEVICE(ADDIDATA, 0x300f), BOARD_APCI3000_8 },
918	{ PCI_VDEVICE(ADDIDATA, 0x300e), BOARD_APCI3000_4 },
919	{ PCI_VDEVICE(ADDIDATA, 0x3013), BOARD_APCI3006_16 },
920	{ PCI_VDEVICE(ADDIDATA, 0x3014), BOARD_APCI3006_8 },
921	{ PCI_VDEVICE(ADDIDATA, 0x3015), BOARD_APCI3006_4 },
922	{ PCI_VDEVICE(ADDIDATA, 0x3016), BOARD_APCI3010_16 },
923	{ PCI_VDEVICE(ADDIDATA, 0x3017), BOARD_APCI3010_8 },
924	{ PCI_VDEVICE(ADDIDATA, 0x3018), BOARD_APCI3010_4 },
925	{ PCI_VDEVICE(ADDIDATA, 0x3019), BOARD_APCI3016_16 },
926	{ PCI_VDEVICE(ADDIDATA, 0x301a), BOARD_APCI3016_8 },
927	{ PCI_VDEVICE(ADDIDATA, 0x301b), BOARD_APCI3016_4 },
928	{ PCI_VDEVICE(ADDIDATA, 0x301c), BOARD_APCI3100_16_4 },
929	{ PCI_VDEVICE(ADDIDATA, 0x301d), BOARD_APCI3100_8_4 },
930	{ PCI_VDEVICE(ADDIDATA, 0x301e), BOARD_APCI3106_16_4 },
931	{ PCI_VDEVICE(ADDIDATA, 0x301f), BOARD_APCI3106_8_4 },
932	{ PCI_VDEVICE(ADDIDATA, 0x3020), BOARD_APCI3110_16_4 },
933	{ PCI_VDEVICE(ADDIDATA, 0x3021), BOARD_APCI3110_8_4 },
934	{ PCI_VDEVICE(ADDIDATA, 0x3022), BOARD_APCI3116_16_4 },
935	{ PCI_VDEVICE(ADDIDATA, 0x3023), BOARD_APCI3116_8_4 },
936	{ PCI_VDEVICE(ADDIDATA, 0x300B), BOARD_APCI3003 },
937	{ PCI_VDEVICE(ADDIDATA, 0x3002), BOARD_APCI3002_16 },
938	{ PCI_VDEVICE(ADDIDATA, 0x3003), BOARD_APCI3002_8 },
939	{ PCI_VDEVICE(ADDIDATA, 0x3004), BOARD_APCI3002_4 },
940	{ PCI_VDEVICE(ADDIDATA, 0x3024), BOARD_APCI3500 },
941	{ 0 }
942};
943MODULE_DEVICE_TABLE(pci, apci3xxx_pci_table);
944
945static struct pci_driver apci3xxx_pci_driver = {
946	.name		= "addi_apci_3xxx",
947	.id_table	= apci3xxx_pci_table,
948	.probe		= apci3xxx_pci_probe,
949	.remove		= comedi_pci_auto_unconfig,
950};
951module_comedi_pci_driver(apci3xxx_driver, apci3xxx_pci_driver);
952
953MODULE_AUTHOR("Comedi http://www.comedi.org");
954MODULE_DESCRIPTION("Comedi low-level driver");
955MODULE_LICENSE("GPL");
956