[go: nahoru, domu]

1027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten/*
2027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * addi_apci_3501.c
3027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
4027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * Project manager: Eric Stolz
5027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *
6027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	ADDI-DATA GmbH
7027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	Dieselstrasse 3
8027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	D-77833 Ottersweier
9027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	Tel: +19(0)7223/9493-0
10027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	Fax: +49(0)7223/9493-92
11027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	http://www.addi-data.com
12027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *	info@addi-data.com
13027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *
14027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * This program is free software; you can redistribute it and/or modify it
15027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * under the terms of the GNU General Public License as published by the
16027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * Free Software Foundation; either version 2 of the License, or (at your
17027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * option) any later version.
18027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten *
19027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * This program is distributed in the hope that it will be useful, but WITHOUT
20027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten * more details.
23027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten */
24027f58c637cda26ba4492b782a08f697f99a1e23H Hartley Sweeten
25ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h>
2633782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/pci.h>
27abac8b54a353b9a1ac7d09ff790812655f618896H Hartley Sweeten#include <linux/interrupt.h>
28abac8b54a353b9a1ac7d09ff790812655f618896H Hartley Sweeten#include <linux/sched.h>
29abac8b54a353b9a1ac7d09ff790812655f618896H Hartley Sweeten
303d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "../comedidev.h"
313d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "comedi_fc.h"
32bf36f012c7ddaff083bb0ef187feddf4d85507a0H Hartley Sweeten#include "amcc_s5933.h"
333d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten
341bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten/*
351bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten * PCI bar 1 register I/O map
361bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten */
371bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_AO_CTRL_STATUS_REG		0x00
381bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_AO_CTRL_BIPOLAR		(1 << 0)
391bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_AO_STATUS_READY		(1 << 8)
401bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_AO_DATA_REG			0x04
41262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten#define APCI3501_AO_DATA_CHAN(x)		((x) << 0)
42262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten#define APCI3501_AO_DATA_VAL(x)			((x) << 8)
43262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten#define APCI3501_AO_DATA_BIPOLAR		(1 << 31)
441bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_AO_TRIG_SCS_REG		0x08
459798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_SYNC_REG			0x20
469798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_RELOAD_REG		0x24
479798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_TIMEBASE_REG		0x28
489798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_CTRL_REG			0x2c
499798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_STATUS_REG		0x30
509798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_IRQ_REG			0x34
519798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_WARN_RELOAD_REG		0x38
529798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten#define APCI3501_TIMER_WARN_TIMEBASE_REG	0x3c
531bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_DO_REG				0x40
541bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten#define APCI3501_DI_REG				0x50
551bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten
5625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten/*
5725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten * AMCC S5933 NVRAM
5825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten */
5925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define NVRAM_USER_DATA_START	0x100
6025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
6125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define NVCMD_BEGIN_READ	(0x7 << 5)
6225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define NVCMD_LOAD_LOW		(0x4 << 5)
6325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define NVCMD_LOAD_HIGH		(0x5 << 5)
6425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
6525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten/*
6625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten * Function types stored in the eeprom
6725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten */
6825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_DIGITALINPUT		0
6925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_DIGITALOUTPUT		1
7025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_ANALOGINPUT		2
7125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_ANALOGOUTPUT		3
7225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_TIMER			4
7325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_WATCHDOG			5
7425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten#define EEPROM_TIMER_WATCHDOG_COUNTER	10
7525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
7653b28a23532f203f4b8287fad2461886088a9158H Hartley Sweetenstruct apci3501_private {
7753b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten	int i_IobaseAmcc;
7853b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten	struct task_struct *tsk_Current;
7953b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten	unsigned char b_TimerSelectMode;
8053b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten};
8153b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten
8299c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweetenstatic struct comedi_lrange apci3501_ao_range = {
8399c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten	2, {
8499c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten		BIP_RANGE(10),
8599c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten		UNI_RANGE(10)
8699c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten	}
8799c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten};
8899c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten
895458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweetenstatic int apci3501_wait_for_dac(struct comedi_device *dev)
905458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten{
915458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten	unsigned int status;
925458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten
935458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten	do {
945458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten		status = inl(dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
955458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten	} while (!(status & APCI3501_AO_STATUS_READY));
965458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten
975458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten	return 0;
985458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten}
995458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten
100298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweetenstatic int apci3501_ao_insn_write(struct comedi_device *dev,
101298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten				  struct comedi_subdevice *s,
102298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten				  struct comedi_insn *insn,
103298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten				  unsigned int *data)
104298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten{
105298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
106298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	unsigned int range = CR_RANGE(insn->chanspec);
107b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten	unsigned int cfg = APCI3501_AO_DATA_CHAN(chan);
108298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	int ret;
109b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten	int i;
110298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
111298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	/*
112298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	 * All analog output channels have the same output range.
113298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	 *	14-bit bipolar: 0-10V
114298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	 *	13-bit unipolar: +/-10V
115298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	 * Changing the range of one channel changes all of them!
116298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	 */
117298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	if (range) {
118298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		outl(0, dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
119298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	} else {
120b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		cfg |= APCI3501_AO_DATA_BIPOLAR;
121298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		outl(APCI3501_AO_CTRL_BIPOLAR,
122298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		     dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
123298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	}
124298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
125298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
126b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		unsigned int val = data[i];
127b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten
128298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		if (range == 1) {
129298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten			if (data[i] > 0x1fff) {
130298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten				dev_err(dev->class_dev,
131298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten					"Unipolar resolution is only 13-bits\n");
132298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten				return -EINVAL;
133298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten			}
134298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		}
135298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
136298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		ret = apci3501_wait_for_dac(dev);
137298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		if (ret)
138298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten			return ret;
139298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
140b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		outl(cfg | APCI3501_AO_DATA_VAL(val),
141298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		     dev->iobase + APCI3501_AO_DATA_REG);
142b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten
143b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		s->readback[chan] = val;
144298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	}
145298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
146298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten	return insn->n;
147298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten}
148298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten
14953b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten#include "addi-data/hwdrv_apci3501.c"
15053b28a23532f203f4b8287fad2461886088a9158H Hartley Sweeten
151513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweetenstatic int apci3501_di_insn_bits(struct comedi_device *dev,
152513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten				 struct comedi_subdevice *s,
153513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten				 struct comedi_insn *insn,
154513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten				 unsigned int *data)
155513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten{
1561bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten	data[1] = inl(dev->iobase + APCI3501_DI_REG) & 0x3;
157513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten
158513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	return insn->n;
159513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten}
160513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten
161953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweetenstatic int apci3501_do_insn_bits(struct comedi_device *dev,
162953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten				 struct comedi_subdevice *s,
163953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten				 struct comedi_insn *insn,
164953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten				 unsigned int *data)
165953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten{
1661bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten	s->state = inl(dev->iobase + APCI3501_DO_REG);
167953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten
16897f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten	if (comedi_dio_update_state(s, data))
1691bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten		outl(s->state, dev->iobase + APCI3501_DO_REG);
170953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten
171953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	data[1] = s->state;
172953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten
173953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	return insn->n;
174953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten}
175953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten
17625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweetenstatic void apci3501_eeprom_wait(unsigned long iobase)
17725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten{
17825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned char val;
17925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
18025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	do {
18125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
18225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	} while (val & 0x80);
18325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten}
18425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
18525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweetenstatic unsigned short apci3501_eeprom_readw(unsigned long iobase,
18625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten					    unsigned short addr)
18725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten{
18825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned short val = 0;
18925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned char tmp;
19025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned char i;
19125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
19225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	/* Add the offset to the start of the user data */
19325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	addr += NVRAM_USER_DATA_START;
19425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
19525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	for (i = 0; i < 2; i++) {
19625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		/* Load the low 8 bit address */
19725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
19825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
19925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
20025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
20125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
20225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		/* Load the high 8 bit address */
20325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
20425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
20525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		outb(((addr + i) >> 8) & 0xff,
20625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten			iobase + AMCC_OP_REG_MCSR_NVDATA);
20725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
20825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
20925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		/* Read the eeprom data byte */
21025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
21125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
21225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
21325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		apci3501_eeprom_wait(iobase);
21425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
21525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		if (i == 0)
21625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten			val |= tmp;
21725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		else
21825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten			val |= (tmp << 8);
21925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	}
22025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
22125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	return val;
22225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten}
22325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
22425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweetenstatic int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
22525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten{
226015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten	struct apci3501_private *devpriv = dev->private;
22725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned long iobase = devpriv->i_IobaseAmcc;
22825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned char nfuncs;
22925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	int i;
23025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
23125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff;
23225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
23325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	/* Read functionality details */
23425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	for (i = 0; i < nfuncs; i++) {
23525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		unsigned short offset = i * 4;
23625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		unsigned short addr;
23725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		unsigned char func;
23825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		unsigned short val;
23925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
24025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f;
24125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		addr = apci3501_eeprom_readw(iobase, 14 + offset);
24225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
24325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		if (func == EEPROM_ANALOGOUTPUT) {
24425b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten			val = apci3501_eeprom_readw(iobase, addr + 10);
24525b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten			return (val >> 4) & 0x3ff;
24625b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		}
24725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	}
24825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	return 0;
24925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten}
25025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
25187c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweetenstatic int apci3501_eeprom_insn_read(struct comedi_device *dev,
2528861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten				     struct comedi_subdevice *s,
2538861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten				     struct comedi_insn *insn,
2548861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten				     unsigned int *data)
2558861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten{
256015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten	struct apci3501_private *devpriv = dev->private;
25725b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	unsigned short addr = CR_CHAN(insn->chanspec);
2588861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
25925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr);
2608861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
2618861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	return insn->n;
2628861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten}
2638861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
264b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweetenstatic irqreturn_t apci3501_interrupt(int irq, void *d)
2658861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten{
2668861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	struct comedi_device *dev = d;
267015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten	struct apci3501_private *devpriv = dev->private;
268b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	unsigned int ui_Timer_AOWatchdog;
269b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	unsigned long ul_Command1;
270b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	int i_temp;
271b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten
272b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	/*  Disable Interrupt */
2739798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
274b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
2759798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
276b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten
2779798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
278b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	if ((!ui_Timer_AOWatchdog)) {
27961768da12ae5f50b4dc3a8e2ca1c066cf827be93H Hartley Sweeten		dev_err(dev->class_dev, "IRQ from unknown source\n");
280b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten		return IRQ_NONE;
281b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	}
2828861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
283b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	/* Enable Interrupt Send a signal to from kernel to user space */
284b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	send_sig(SIGIO, devpriv->tsk_Current, 0);
2859798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
286b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
2879798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
2889798df7269a44fb148d1815542abb844b0dac435H Hartley Sweeten	i_temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
289b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten
290b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten	return IRQ_HANDLED;
2918861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten}
2928861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
293678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweetenstatic int apci3501_reset(struct comedi_device *dev)
2948861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten{
295262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	unsigned int val;
296262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	int chan;
2975458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten	int ret;
298678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten
299262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	/* Reset all digital outputs to "0" */
3001bc5062a9796b2908f5c21c2bc3f50add7431fb8H Hartley Sweeten	outl(0x0, dev->iobase + APCI3501_DO_REG);
301678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten
302262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	/* Default all analog outputs to 0V (bipolar) */
303262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	outl(APCI3501_AO_CTRL_BIPOLAR,
304262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	     dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
305262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	val = APCI3501_AO_DATA_BIPOLAR | APCI3501_AO_DATA_VAL(0);
306678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten
307262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	/* Set all analog output channels */
308262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten	for (chan = 0; chan < 8; chan++) {
3095458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten		ret = apci3501_wait_for_dac(dev);
3105458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten		if (ret) {
3115458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten			dev_warn(dev->class_dev,
3125458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten				 "%s: DAC not-ready for channel %i\n",
313262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten				 __func__, chan);
3145458f3e7b5a8707a49948857d69b2eb2fa5931acH Hartley Sweeten		} else {
315262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten			outl(val | APCI3501_AO_DATA_CHAN(chan),
316262736988d445cb1613aa936bfe343261627f899H Hartley Sweeten			     dev->iobase + APCI3501_AO_DATA_REG);
317678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten		}
318678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten	}
3198861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
3208861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	return 0;
3218861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten}
3228861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
3238861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweetenstatic int apci3501_auto_attach(struct comedi_device *dev,
3248861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten				unsigned long context_unused)
3258861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten{
3268861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
327015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten	struct apci3501_private *devpriv;
3288861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	struct comedi_subdevice *s;
32925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	int ao_n_chan;
330694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	int ret;
3318861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
3320bdab509bf9c6d838dc0a3b1d68bbf841fc20b5aH Hartley Sweeten	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
3338861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	if (!devpriv)
3348861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten		return -ENOMEM;
3358861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
336818f569fe930c5b8a05d1a44ece3c63c99c13c88H Hartley Sweeten	ret = comedi_pci_enable(dev);
3378861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	if (ret)
3388861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten		return ret;
3398861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
3401bdc840224f71768c6bbe41b211f07c0778330c8H Hartley Sweeten	dev->iobase = pci_resource_start(pcidev, 1);
3411bdc840224f71768c6bbe41b211f07c0778330c8H Hartley Sweeten	devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
3428861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
34325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
3448861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
3458861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	if (pcidev->irq > 0) {
346b2b82184c9c9a82553bfd49e7940ebc67fe655a8H Hartley Sweeten		ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED,
3478861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten				  dev->board_name, dev);
3488861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten		if (ret == 0)
3498861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten			dev->irq = pcidev->irq;
3508861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	}
3518861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
352694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 5);
3538861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	if (ret)
3548861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten		return ret;
3558861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
356694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	/* Initialize the analog output subdevice */
3578861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	s = &dev->subdevices[0];
35825b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten	if (ao_n_chan) {
35925b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		s->type		= COMEDI_SUBD_AO;
36025b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		s->subdev_flags	= SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
36125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		s->n_chan	= ao_n_chan;
36225b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		s->maxdata	= 0x3fff;
36399c9fa48b6bbc640066c414d6b413a1f1b4aa857H Hartley Sweeten		s->range_table	= &apci3501_ao_range;
364298ab7de9ced3ecbe7961360ece58d5aa17aa3c1H Hartley Sweeten		s->insn_write	= apci3501_ao_insn_write;
365b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		s->insn_read	= comedi_readback_insn_read;
366b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten
367b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		ret = comedi_alloc_subdev_readback(s);
368b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten		if (ret)
369b1d6bffb92fe78d11e18f8853a80d4cc372afc2dH Hartley Sweeten			return ret;
3708861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	} else {
37125b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten		s->type		= COMEDI_SUBD_UNUSED;
3728861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	}
37325b9b873d3e3c1ed25cd5a7551bfee0b42d4ed1dH Hartley Sweeten
374694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	/* Initialize the digital input subdevice */
375694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	s = &dev->subdevices[1];
376513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->type		= COMEDI_SUBD_DI;
377513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->subdev_flags	= SDF_READABLE;
378513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->n_chan	= 2;
379513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->maxdata	= 1;
380513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->range_table	= &range_digital;
381513192fc7e34d089d4b949a0e7ba6ccd4780f663H Hartley Sweeten	s->insn_bits	= apci3501_di_insn_bits;
3828861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
383953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	/* Initialize the digital output subdevice */
384694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	s = &dev->subdevices[2];
385953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->type		= COMEDI_SUBD_DO;
386953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->subdev_flags	= SDF_WRITEABLE;
387953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->n_chan	= 2;
388953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->maxdata	= 1;
389953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->range_table	= &range_digital;
390953a36c45aa4ba23be687451df6311ad33d89538H Hartley Sweeten	s->insn_bits	= apci3501_do_insn_bits;
3918861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
392694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	/* Initialize the timer/watchdog subdevice */
393694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	s = &dev->subdevices[3];
3943d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->type = COMEDI_SUBD_TIMER;
3953d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
3963d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->n_chan = 1;
3973d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->maxdata = 0;
3983d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->len_chanlist = 1;
3993d596e50ffbb183df6fb132a9a795a5ff8d7842cH Hartley Sweeten	s->range_table = &range_digital;
400805077b90c5a290ec050d5003a4ea9e37be48453Fred Akers	s->insn_write = apci3501_write_insn_timer;
401805077b90c5a290ec050d5003a4ea9e37be48453Fred Akers	s->insn_read = apci3501_read_insn_timer;
402805077b90c5a290ec050d5003a4ea9e37be48453Fred Akers	s->insn_config = apci3501_config_insn_timer;
4038861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
404694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	/* Initialize the eeprom subdevice */
405694dcf501c35b6afcbc90ae3b4f3fea0b59f9888H Hartley Sweeten	s = &dev->subdevices[4];
40687c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweeten	s->type		= COMEDI_SUBD_MEMORY;
40787c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweeten	s->subdev_flags	= SDF_READABLE | SDF_INTERNAL;
40887c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweeten	s->n_chan	= 256;
40987c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweeten	s->maxdata	= 0xffff;
41087c38fbed5bb706785be9171ed4a9b41faf17e13H Hartley Sweeten	s->insn_read	= apci3501_eeprom_insn_read;
4118861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
412678a4d3ab159b776a7cb9c8ca9fdaf5498f3423aH Hartley Sweeten	apci3501_reset(dev);
4138861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	return 0;
4148861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten}
4158861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
4168861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweetenstatic void apci3501_detach(struct comedi_device *dev)
4178861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten{
418015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten	if (dev->iobase)
419015aebe78d3f341fc6aa42f655e191f84bd1a7e5H Hartley Sweeten		apci3501_reset(dev);
420aac307f9dd5ce1fe651140a036ab4b0a0571b54aH Hartley Sweeten	comedi_pci_detach(dev);
4218861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten}
422317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten
42320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct comedi_driver apci3501_driver = {
42420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.driver_name	= "addi_apci_3501",
42520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.module		= THIS_MODULE,
4268861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	.auto_attach	= apci3501_auto_attach,
4278861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	.detach		= apci3501_detach,
42820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
42920a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
430a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int apci3501_pci_probe(struct pci_dev *dev,
431b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten			      const struct pci_device_id *id)
43220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{
433b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten	return comedi_pci_auto_config(dev, &apci3501_driver, id->driver_data);
43420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}
43520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
43641e043fcfa2236bb2c4a8335eb09f4c8cee224b3Jingoo Hanstatic const struct pci_device_id apci3501_pci_table[] = {
4378861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) },
4388861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten	{ 0 }
4398861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten};
4408861b456b8f800208e043b2d0d65985eca538dd9H Hartley SweetenMODULE_DEVICE_TABLE(pci, apci3501_pci_table);
4418861b456b8f800208e043b2d0d65985eca538dd9H Hartley Sweeten
44220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct pci_driver apci3501_pci_driver = {
44320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.name		= "addi_apci_3501",
44420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.id_table	= apci3501_pci_table,
44520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.probe		= apci3501_pci_probe,
4469901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe	.remove		= comedi_pci_auto_unconfig,
44720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
44820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenmodule_comedi_pci_driver(apci3501_driver, apci3501_pci_driver);
44990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
4506ff35881e882f744a4a9954fbf838296a36fe7c2H Hartley SweetenMODULE_DESCRIPTION("ADDI-DATA APCI-3501 Analog output board");
45190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
45290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
453