[go: nahoru, domu]

1eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf/*
2c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * ii_pci20kc.c
3c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Driver for Intelligent Instruments PCI-20001C carrier board and modules.
4eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf *
5c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Copyright (C) 2000 Markus Kempf <kempf@matsci.uni-sb.de>
6c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * with suggestions from David Schleef		16.06.2000
7c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten */
8c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten
9c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten/*
10c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Driver: ii_pci20kc
11c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Description: Intelligent Instruments PCI-20001C carrier board
12c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc]
13c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Author: Markus Kempf <kempf@matsci.uni-sb.de>
14c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Status: works
15eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf *
16c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Supports the PCI-20001C-1a and PCI-20001C-2a carrier boards. The
17c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * -2a version has 32 on-board DIO channels. Three add-on modules
18c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * can be added to the carrier board for additional functionality.
19eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf *
20c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Supported add-on modules:
21c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten *	PCI-20006M-1   1 channel, 16-bit analog output module
22c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten *	PCI-20006M-2   2 channel, 16-bit analog output module
23c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten *	PCI-20341M-1A  4 channel, 16-bit analog input module
24eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf *
25c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Options:
26c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten *   0   Board base address
27c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten *   1   IRQ (not-used)
28eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf */
29eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
30ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h>
31eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf#include "../comedidev.h"
32eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
339abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten/*
349abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten * Register I/O map
359abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten */
3627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott#define II20K_SIZE			0x400
37f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten#define II20K_MOD_OFFSET		0x100
389abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_REG			0x00
399abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD1_EMPTY		(1 << 7)
409abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD2_EMPTY		(1 << 6)
419abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD3_EMPTY		(1 << 5)
429abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MASK			0x1f
439abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_PCI20001C_1A		0x1b	/* no on-board DIO */
449abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_PCI20001C_2A		0x1d	/* on-board DIO */
459abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_REG		0x40
469abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD1	(1 << 7)
479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD2	(1 << 6)
489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD3	(1 << 5)
499abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO0_REG			0x80
509abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO1_REG			0x81
519abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_ENA_REG		0x82
529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO3_OUT		(1 << 7)
539abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO2_OUT		(1 << 6)
549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO3		(1 << 5)
559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO2		(1 << 4)
569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO1_OUT		(1 << 3)
579abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO0_OUT		(1 << 2)
589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO1		(1 << 1)
599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO0		(1 << 0)
609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_REG		0x83
619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_SET		(1 << 7)
629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_DIO0_IN		(1 << 4)
639abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_DIO1_IN		(1 << 1)
649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO2_REG			0xc0
659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO3_REG			0xc1
669abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_REG		0xc3
679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_SET		(1 << 7)
689abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_DIO2_IN		(1 << 4)
699abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_DIO3_IN		(1 << 1)
709abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
7187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_ID_PCI20006M_1		0xe2	/* 1 AO channels */
7287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_ID_PCI20006M_2		0xe3	/* 2 AO channels */
7387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_STRB_REG(x)		(0x0b + ((x) * 0x08))
7487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_LSB_REG(x)		(0x0d + ((x) * 0x08))
7587a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_MSB_REG(x)		(0x0e + ((x) * 0x08))
7687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_STRB_BOTH_REG		0x1b
7787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten
78c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten#define II20K_ID_PCI20341M_1		0x77	/* 4 AI channels */
793aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_REG		0x01
803aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_BUSY	(1 << 7)
813aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_HW_ENA	(1 << 1)
823aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_EXT_START	(1 << 0)
833aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_LSB_REG		0x02
843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_MSB_REG		0x03
853aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_PACER_RESET_REG	0x04
863aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_16BIT_DATA_REG		0x06
873aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CONF_REG		0x10
883aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CONF_ENA		(1 << 2)
893aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_REG		0x11
903aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TRIG_ENA		(1 << 5)
913aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TRIG_INV		(1 << 4)
923aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TIMEBASE(x)	(((x) & 0x3) << 1)
933aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_BURST_MODE		(1 << 0)
943aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_REG		0x12
953aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_INT		(1 << 7)
963aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_TRIG		(1 << 6)
973aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_TRIG_ENA	(1 << 5)
983aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_PACER_ERR	(1 << 2)
993aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_DATA_ERR	(1 << 1)
1003aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_SET_TIME_ERR	(1 << 0)
1013aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_LAST_CHAN_ADDR_REG	0x13
1023aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CUR_ADDR_REG		0x14
1033aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_SET_TIME_REG		0x15
1043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_DELAY_LSB_REG		0x16
1053aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_DELAY_MSB_REG		0x17
1063aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHAN_ADV_REG		0x18
1073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHAN_RESET_REG		0x19
1083aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_START_TRIG_REG		0x1a
1093aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_COUNT_RESET_REG	0x1b
1103aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_REG		0x80
1113aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_ONBOARD_ONLY	(1 << 5)
1123aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_GAIN(x)	(((x) & 0x3) << 3)
1133aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_MUX_ENA	(1 << 2)
1143aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_CHAN(x)	(((x) & 0x3) << 0)
1153aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_LEN		0x80
116eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
11787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten/* the AO range is set by jumpers on the 20006M module */
11887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweetenstatic const struct comedi_lrange ii20k_ao_ranges = {
11987a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	3, {
12087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		BIP_RANGE(5),	/* Chan 0 - W1/W3 in   Chan 1 - W2/W4 in  */
12187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		UNI_RANGE(10),	/* Chan 0 - W1/W3 out  Chan 1 - W2/W4 in  */
12287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		BIP_RANGE(10)	/* Chan 0 - W1/W3 in   Chan 1 - W2/W4 out */
12387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	}
12487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten};
1253366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten
1263aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweetenstatic const struct comedi_lrange ii20k_ai_ranges = {
1273aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	4, {
1283aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		BIP_RANGE(5),		/* gain 1 */
1293aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		BIP_RANGE(0.5),		/* gain 10 */
1303aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		BIP_RANGE(0.05),	/* gain 100 */
1313aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		BIP_RANGE(0.025)	/* gain 200 */
1323aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	},
1333366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten};
1343366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten
13557b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweetenstatic void __iomem *ii20k_module_iobase(struct comedi_device *dev,
13657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten					 struct comedi_subdevice *s)
13757b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten{
138d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	return dev->mmio + (s->index + 1) * II20K_MOD_OFFSET;
13957b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten}
14057b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten
141f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_ao_insn_write(struct comedi_device *dev,
1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
143f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			       struct comedi_insn *insn,
144f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			       unsigned int *data)
145eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{
14657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten	void __iomem *iobase = ii20k_module_iobase(dev, s);
14787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
14887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	int i;
149eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
15087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
1511fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten		unsigned int val = data[i];
15287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten
1531fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten		s->readback[chan] = val;
154c3c17d2eadce4e497a88783a625e07acb31f1dfbH Hartley Sweeten
15587a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		/* munge data */
15687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		val += ((s->maxdata + 1) >> 1);
15787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		val &= s->maxdata;
15887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten
15987a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		writeb(val & 0xff, iobase + II20K_AO_LSB_REG(chan));
16087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		writeb((val >> 8) & 0xff, iobase + II20K_AO_MSB_REG(chan));
16187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		writeb(0x00, iobase + II20K_AO_STRB_REG(chan));
162eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	}
163eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
16487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	return insn->n;
165eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf}
166eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
16783b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweetenstatic int ii20k_ai_eoc(struct comedi_device *dev,
16883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten			struct comedi_subdevice *s,
16983b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten			struct comedi_insn *insn,
17083b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten			unsigned long context)
1713aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten{
1723aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	void __iomem *iobase = ii20k_module_iobase(dev, s);
1733aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	unsigned char status;
1743aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
17583b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten	status = readb(iobase + II20K_AI_STATUS_REG);
17683b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten	if ((status & II20K_AI_STATUS_INT) == 0)
17783b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten		return 0;
17883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten	return -EBUSY;
1793aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten}
1803aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
1813aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweetenstatic void ii20k_ai_setup(struct comedi_device *dev,
1823aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten			   struct comedi_subdevice *s,
1833aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten			   unsigned int chanspec)
1843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten{
1853aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	void __iomem *iobase = ii20k_module_iobase(dev, s);
1863aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	unsigned int chan = CR_CHAN(chanspec);
1873aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	unsigned int range = CR_RANGE(chanspec);
1883aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	unsigned char val;
1893aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
1903aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* initialize module */
1913aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(II20K_AI_CONF_ENA, iobase + II20K_AI_CONF_REG);
1923aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
1933aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* software conversion */
1943aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(0, iobase + II20K_AI_STATUS_CMD_REG);
1953aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
1963aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* set the time base for the settling time counter based on the gain */
1973aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	val = (range < 3) ? II20K_AI_OPT_TIMEBASE(0) : II20K_AI_OPT_TIMEBASE(2);
1983aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(val, iobase + II20K_AI_OPT_REG);
1993aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2003aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* set the settling time counter based on the gain */
2013aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	val = (range < 2) ? 0x58 : (range < 3) ? 0x93 : 0x99;
2023aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(val, iobase + II20K_AI_SET_TIME_REG);
2033aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* set number of input channels */
2053aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(1, iobase + II20K_AI_LAST_CHAN_ADDR_REG);
2063aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* set the channel list byte */
2083aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	val = II20K_AI_CHANLIST_ONBOARD_ONLY |
2093aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	      II20K_AI_CHANLIST_MUX_ENA |
2103aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	      II20K_AI_CHANLIST_GAIN(range) |
2113aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	      II20K_AI_CHANLIST_CHAN(chan);
2123aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(val, iobase + II20K_AI_CHANLIST_REG);
2133aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2143aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* reset settling time counter and trigger delay counter */
2153aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(0, iobase + II20K_AI_COUNT_RESET_REG);
2163aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2173aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	/* reset channel scanner */
2183aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	writeb(0, iobase + II20K_AI_CHAN_RESET_REG);
2193aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten}
2203aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
221f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_ai_insn_read(struct comedi_device *dev,
2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
223f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			      struct comedi_insn *insn,
224f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			      unsigned int *data)
225eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{
22657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten	void __iomem *iobase = ii20k_module_iobase(dev, s);
2273aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	int ret;
2283aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	int i;
2293555a4c35e59c0217983f5df0cfe39a9fa65c2dfXenofon Foukas
2303aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	ii20k_ai_setup(dev, s, insn->chanspec);
2313555a4c35e59c0217983f5df0cfe39a9fa65c2dfXenofon Foukas
2323aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
2333aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		unsigned int val;
234eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
2353aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		/* generate a software start convert signal */
2363aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		readb(iobase + II20K_AI_PACER_RESET_REG);
237eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
23883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten		ret = comedi_timeout(dev, s, insn, ii20k_ai_eoc, 0);
2393aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		if (ret)
2403aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten			return ret;
241eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
2423aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		val = readb(iobase + II20K_AI_LSB_REG);
2433aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		val |= (readb(iobase + II20K_AI_MSB_REG) << 8);
244eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
2453aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		/* munge two's complement data */
2463aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		val += ((s->maxdata + 1) >> 1);
2473aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		val &= s->maxdata;
2483aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2493aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		data[i] = val;
2503aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	}
2513aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten
2523aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten	return insn->n;
253842525c6c1efa0bfefb7fb96838ef6ec588ce95eH Hartley Sweeten}
254842525c6c1efa0bfefb7fb96838ef6ec588ce95eH Hartley Sweeten
2559abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic void ii20k_dio_config(struct comedi_device *dev,
2569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			     struct comedi_subdevice *s)
257eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{
2589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	unsigned char ctrl01 = 0;
2599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	unsigned char ctrl23 = 0;
2609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	unsigned char dir_ena = 0;
261eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
2629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* port 0 - channels 0-7 */
263eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	if (s->io_bits & 0x000000ff) {
2649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* output port */
2659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl01 &= ~II20K_CTRL01_DIO0_IN;
2669abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_BUF_DISAB_DIO0;
2679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena |= II20K_DIR_DIO0_OUT;
268eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	} else {
2699abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* input port */
2709abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl01 |= II20K_CTRL01_DIO0_IN;
2719abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_DIR_DIO0_OUT;
272eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	}
2739abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
2749abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* port 1 - channels 8-15 */
275eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	if (s->io_bits & 0x0000ff00) {
2769abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* output port */
2779abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl01 &= ~II20K_CTRL01_DIO1_IN;
2789abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_BUF_DISAB_DIO1;
2799abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena |= II20K_DIR_DIO1_OUT;
280eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	} else {
2819abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* input port */
2829abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl01 |= II20K_CTRL01_DIO1_IN;
2839abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_DIR_DIO1_OUT;
284eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	}
2859abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
2869abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* port 2 - channels 16-23 */
287eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	if (s->io_bits & 0x00ff0000) {
2889abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* output port */
2899abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl23 &= ~II20K_CTRL23_DIO2_IN;
2909abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_BUF_DISAB_DIO2;
2919abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena |= II20K_DIR_DIO2_OUT;
292eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	} else {
2939abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* input port */
2949abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl23 |= II20K_CTRL23_DIO2_IN;
2959abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_DIR_DIO2_OUT;
296eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	}
2979abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
2989abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* port 3 - channels 24-31 */
299eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	if (s->io_bits & 0xff000000) {
3009abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* output port */
3019abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl23 &= ~II20K_CTRL23_DIO3_IN;
3029abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_BUF_DISAB_DIO3;
3039abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena |= II20K_DIR_DIO3_OUT;
304eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	} else {
3059abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* input port */
3069abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ctrl23 |= II20K_CTRL23_DIO3_IN;
3079abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		dir_ena &= ~II20K_DIR_DIO3_OUT;
308eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf	}
3099abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
3109abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	ctrl23 |= II20K_CTRL01_SET;
3119abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	ctrl23 |= II20K_CTRL23_SET;
3129abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
3139abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* order is important */
314d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	writeb(ctrl01, dev->mmio + II20K_CTRL01_REG);
315d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	writeb(ctrl23, dev->mmio + II20K_CTRL23_REG);
316d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	writeb(dir_ena, dev->mmio + II20K_DIR_ENA_REG);
317eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf}
318eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
3199abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic int ii20k_dio_insn_config(struct comedi_device *dev,
3209abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten				 struct comedi_subdevice *s,
3219abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten				 struct comedi_insn *insn,
3229abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten				 unsigned int *data)
323eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{
3245dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
3255dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	unsigned int mask;
3265dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	int ret;
3275dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten
3285dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	if (chan < 8)
3295dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten		mask = 0x000000ff;
3305dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	else if (chan < 16)
3315dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten		mask = 0x0000ff00;
3325dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	else if (chan < 24)
3335dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten		mask = 0x00ff0000;
33463d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten	else
3355dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten		mask = 0xff000000;
3365dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten
3375dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
3385dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten	if (ret)
3395dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten		return ret;
34063d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten
3419abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	ii20k_dio_config(dev, s);
3429abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
3439abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	return insn->n;
344eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf}
345eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
3469abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic int ii20k_dio_insn_bits(struct comedi_device *dev,
3479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			       struct comedi_subdevice *s,
3489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			       struct comedi_insn *insn,
3499abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			       unsigned int *data)
350eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{
3519b13bc1d4ab0c5abc1b29d4fa95a41bf02238d2aH Hartley Sweeten	unsigned int mask;
3529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
3539b13bc1d4ab0c5abc1b29d4fa95a41bf02238d2aH Hartley Sweeten	mask = comedi_dio_update_state(s, data);
3549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	if (mask) {
3559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		if (mask & 0x000000ff)
3569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			writeb((s->state >> 0) & 0xff,
357d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten			       dev->mmio + II20K_DIO0_REG);
3589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		if (mask & 0x0000ff00)
3599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			writeb((s->state >> 8) & 0xff,
360d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten			       dev->mmio + II20K_DIO1_REG);
3619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		if (mask & 0x00ff0000)
3629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			writeb((s->state >> 16) & 0xff,
363d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten			       dev->mmio + II20K_DIO2_REG);
3649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		if (mask & 0xff000000)
3659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten			writeb((s->state >> 24) & 0xff,
366d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten			       dev->mmio + II20K_DIO3_REG);
3679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	}
368eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf
369d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	data[1] = readb(dev->mmio + II20K_DIO0_REG);
370d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	data[1] |= readb(dev->mmio + II20K_DIO1_REG) << 8;
371d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	data[1] |= readb(dev->mmio + II20K_DIO2_REG) << 16;
372d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	data[1] |= readb(dev->mmio + II20K_DIO3_REG) << 24;
37363d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten
37463d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten	return insn->n;
37563d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten}
37663d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten
377f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_init_module(struct comedi_device *dev,
3783aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten			     struct comedi_subdevice *s)
379f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten{
38057b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten	void __iomem *iobase = ii20k_module_iobase(dev, s);
381f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	unsigned char id;
3821fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten	int ret;
383f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten
384f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	id = readb(iobase + II20K_ID_REG);
385f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	switch (id) {
38687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	case II20K_ID_PCI20006M_1:
38787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten	case II20K_ID_PCI20006M_2:
388f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		/* Analog Output subdevice */
389f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type		= COMEDI_SUBD_AO;
390f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->subdev_flags	= SDF_WRITABLE;
39187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		s->n_chan	= (id == II20K_ID_PCI20006M_2) ? 2 : 1;
392f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->maxdata	= 0xffff;
39387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten		s->range_table	= &ii20k_ao_ranges;
394f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->insn_write	= ii20k_ao_insn_write;
3951fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten		s->insn_read	= comedi_readback_insn_read;
3961fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten
3971fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten		ret = comedi_alloc_subdev_readback(s);
3981fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten		if (ret)
3991fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten			return ret;
400f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		break;
401c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten	case II20K_ID_PCI20341M_1:
402f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		/* Analog Input subdevice */
403f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type		= COMEDI_SUBD_AI;
4043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		s->subdev_flags	= SDF_READABLE | SDF_DIFF;
405f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->n_chan	= 4;
406f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->maxdata	= 0xffff;
4073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		s->range_table	= &ii20k_ai_ranges;
408f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->insn_read	= ii20k_ai_insn_read;
409f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		break;
410f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	default:
411f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type = COMEDI_SUBD_UNUSED;
412f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		break;
413f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	}
414f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten
415f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	return 0;
416f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten}
417f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten
418c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenstatic int ii20k_attach(struct comedi_device *dev,
419c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten			struct comedi_devconfig *it)
4200f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten{
4219abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	struct comedi_subdevice *s;
42227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	unsigned int membase;
4239abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	unsigned char id;
4249abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	bool has_dio;
4259abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	int ret;
4260f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
42727fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	membase = it->options[0];
42827fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	if (!membase || (membase & ~(0x100000 - II20K_SIZE))) {
42927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		dev_warn(dev->class_dev,
43027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott			 "%s: invalid memory address specified\n",
43127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott			 dev->board_name);
43227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		return -EINVAL;
43327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	}
43427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott
43527fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) {
43627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n",
43727fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott			 dev->board_name, membase, II20K_SIZE);
43827fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		return -EIO;
43927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	}
44027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	dev->iobase = membase;	/* actually, a memory address */
44127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott
44227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	dev->mmio = ioremap(membase, II20K_SIZE);
44327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	if (!dev->mmio)
44427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		return -ENOMEM;
4450f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
446d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten	id = readb(dev->mmio + II20K_ID_REG);
4479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	switch (id & II20K_ID_MASK) {
4489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	case II20K_ID_PCI20001C_1A:
44927a2234edd4a5c8b0ebdaaa3f6a5f00183f3154fChristian Engelmayer		has_dio = false;
4509abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		break;
4519abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	case II20K_ID_PCI20001C_2A:
4529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		has_dio = true;
4539abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		break;
4549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	default:
4559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		return -ENODEV;
4560f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten	}
4570f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
4589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 4);
4599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	if (ret)
4609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		return ret;
4619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
462f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	s = &dev->subdevices[0];
463f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	if (id & II20K_ID_MOD1_EMPTY) {
464f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type = COMEDI_SUBD_UNUSED;
465f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	} else {
4663aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		ret = ii20k_init_module(dev, s);
467f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		if (ret)
468f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			return ret;
469f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	}
470f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten
471f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	s = &dev->subdevices[1];
472f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	if (id & II20K_ID_MOD2_EMPTY) {
473f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type = COMEDI_SUBD_UNUSED;
474f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	} else {
4753aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		ret = ii20k_init_module(dev, s);
476f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		if (ret)
477f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			return ret;
478f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	}
479f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten
480f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	s = &dev->subdevices[2];
481f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	if (id & II20K_ID_MOD3_EMPTY) {
482f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		s->type = COMEDI_SUBD_UNUSED;
483f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten	} else {
4843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten		ret = ii20k_init_module(dev, s);
485f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten		if (ret)
486f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten			return ret;
4870f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten	}
4880f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
4899abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	/* Digital I/O subdevice */
4909abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	s = &dev->subdevices[3];
4919abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	if (has_dio) {
4929abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->type		= COMEDI_SUBD_DIO;
4939abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
4949abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->n_chan	= 32;
4959abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->maxdata	= 1;
4969abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->range_table	= &range_digital;
4979abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->insn_bits	= ii20k_dio_insn_bits;
4989abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->insn_config	= ii20k_dio_insn_config;
4999abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten
5009abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		/* default all channels to input */
5019abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		ii20k_dio_config(dev, s);
5029abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	} else {
5039abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten		s->type = COMEDI_SUBD_UNUSED;
5049abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten	}
5050f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
506c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten	return 0;
5070f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten}
5080f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten
50927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbottstatic void ii20k_detach(struct comedi_device *dev)
51027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott{
51127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	if (dev->mmio)
51227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		iounmap(dev->mmio);
51327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	if (dev->iobase)	/* actually, a memory address */
51427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott		release_mem_region(dev->iobase, II20K_SIZE);
51527fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott}
51627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott
517c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenstatic struct comedi_driver ii20k_driver = {
5182396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten	.driver_name	= "ii_pci20kc",
5192396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten	.module		= THIS_MODULE,
520c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten	.attach		= ii20k_attach,
52127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott	.detach		= ii20k_detach,
5222396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten};
523c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenmodule_comedi_driver(ii20k_driver);
52490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
52590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
52690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
52790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
528