cb_das16_cs.c revision 68c3dbff9fc9f25872408d0e95980d41733d48d0
1f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
2f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    comedi/drivers/das16cs.c
3f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    Driver for Computer Boards PC-CARD DAS16/16.
4f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
5f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    COMEDI - Linux Control and Measurement Device Interface
6f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org>
7f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
8f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    This program is free software; you can redistribute it and/or modify
9f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    it under the terms of the GNU General Public License as published by
10f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    the Free Software Foundation; either version 2 of the License, or
11f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    (at your option) any later version.
12f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
13f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    This program is distributed in the hope that it will be useful,
14f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    but WITHOUT ANY WARRANTY; without even the implied warranty of
15f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    GNU General Public License for more details.
17f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
18f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    You should have received a copy of the GNU General Public License
19f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    along with this program; if not, write to the Free Software
20f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
22f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
23f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
24f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDriver: cb_das16_cs
25f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDescription: Computer Boards PC-CARD DAS16/16
26f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDevices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO
27f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefAuthor: ds
28f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefUpdated: Mon, 04 Nov 2002 20:04:21 -0800
29f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefStatus: experimental
30f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
31f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
32f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
33f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
34f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "../comedidev.h"
35f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/delay.h>
36f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/pci.h>
37f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
38f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs_types.h>
39f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs.h>
40f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cistpl.h>
41f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/ds.h>
42f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
43f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "8253.h"
44f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
45f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_SIZE			18
46f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
47f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_ADC_DATA		0
48f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO_MUX			2
49f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC1			4
50f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC2			6
51f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR0			8
52f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR1			10
53f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR2			12
54f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR_CONTROL		14
55f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO			16
56f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
573281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstruct das16cs_board {
58f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	const char *name;
59f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int device_id;
60f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int n_ao_chans;
613281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton};
623281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstatic const struct das16cs_board das16cs_boards[] = {
63f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
6468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x0000,/* unknown */
6568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "PC-CARD DAS16/16",
6668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.n_ao_chans = 0,
67f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
68f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
6968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x0039,
7068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "PC-CARD DAS16/16-AO",
7168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.n_ao_chans = 2,
72f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
73f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
7468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x4009,
7568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "PCM-DAS16s/16",
7668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.n_ao_chans = 0,
77f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
78f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
79f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
80f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
813281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton#define thisboard ((const struct das16cs_board *)dev->board_ptr)
82f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
83bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pembertonstruct das16cs_private {
84f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
85f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
86790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int ao_readback[2];
87f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
88f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status2;
89bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton};
90bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton#define devpriv ((struct das16cs_private *)dev->private)
91f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
92da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
93da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev);
94139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das16cs = {
9568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_das16_cs",
9668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
9768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das16cs_attach,
9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das16cs_detach,
99f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
100f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
101f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device *cur_dev = NULL;
102f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1039ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange das16cs_ai_range = { 4, {
104f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			RANGE(-10, 10),
105f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			RANGE(-5, 5),
106f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			RANGE(-2.5, 2.5),
107f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			RANGE(-1.25, 1.25),
108f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
109f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
110f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
11170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d);
11234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
11390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
11434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
11534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
116ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
11734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
11890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
11934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
12090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
12134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
12290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
12334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
12490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
12534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
12690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
12734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
12890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
129f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
13071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
131f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
132f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple_t tuple;
133f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	u_short buf[128];
134f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int prodid = 0;
135f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
136f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleData = (cisdata_t *) buf;
137f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleOffset = 0;
138f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleDataMax = 255;
139f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.DesiredTuple = CISTPL_MANFID;
140f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.Attributes = TUPLE_RETURN_COMMON;
141f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
142f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		(pcmcia_get_tuple_data(link, &tuple) == 0)) {
143f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		prodid = le16_to_cpu(buf[1]);
144f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
145f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
146f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return prodid;
147f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
148f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1493281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstatic const struct das16cs_board *das16cs_probe(struct comedi_device * dev,
150f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link)
151f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
152f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int id;
153f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
154f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
155f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	id = get_prodid(dev, link);
156f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
157f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < n_boards; i++) {
158f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (das16cs_boards[i].device_id == id) {
159f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return das16cs_boards + i;
160f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
161f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
162f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
163f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("unknown board!\n");
164f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
165f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return NULL;
166f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
167f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
168da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
169f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
170f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
17134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
172f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
173f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
174f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
175f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: cb_das16_cs: ", dev->minor);
176f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
177f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link = cur_dev;		/* XXX hack */
178f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!link)
179f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
180f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
181f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->iobase = link->io.BasePort1;
182f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("I/O base=0x%04lx ", dev->iobase);
183f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
184f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("fingerprint:\n");
185f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < 48; i += 2) {
186f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk("%04x ", inw(dev->iobase + i));
187f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
188f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
189f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
190f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = comedi_request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
191f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		IRQF_SHARED, "cb_das16_cs", dev);
192f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0) {
193f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
194f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
195f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->irq = link->irq.AssignedIRQ;
196f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("irq=%u ", dev->irq);
197f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
198f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_ptr = das16cs_probe(dev, link);
199f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!dev->board_ptr)
200f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
201f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
202f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_name = thisboard->name;
203f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
204bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
205f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
206f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
207f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (alloc_subdevices(dev, 4) < 0)
208f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
209f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
210f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 0;
211f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->read_subdev = s;
212f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog input subdevice */
213f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->type = COMEDI_SUBD_AI;
214f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
215f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->n_chan = 16;
216f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->maxdata = 0xffff;
217f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->range_table = &das16cs_ai_range;
218f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->len_chanlist = 16;
219f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->insn_read = das16cs_ai_rinsn;
220f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmd = das16cs_ai_cmd;
221f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmdtest = das16cs_ai_cmdtest;
222f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
223f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 1;
224f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog output subdevice */
225f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (thisboard->n_ao_chans) {
226f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_AO;
227f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_WRITABLE;
228f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = thisboard->n_ao_chans;
229f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xffff;
230f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_bipolar10;
231f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_write = &das16cs_ao_winsn;
232f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = &das16cs_ao_rinsn;
233f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
234f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
235f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 2;
236f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* digital i/o subdevice */
237f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (1) {
238f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_DIO;
239f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
240f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 8;
241f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 1;
242f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_digital;
243f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_bits = das16cs_dio_insn_bits;
244f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_dio_insn_config;
245f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
246f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
247f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
248f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
249f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 3;
250f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* timer subdevice */
251f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (0) {
252f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_TIMER;
253f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
254f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 1;
255f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xff;
256f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_unknown;
257f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = das16cs_timer_insn_read;
258f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_timer_insn_config;
259f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
260f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
261f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
262f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
263f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("attached\n");
264f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
265f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 1;
266f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
267f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
268da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev)
269f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
270f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: das16cs: remove\n", dev->minor);
271f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
272f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (dev->irq) {
273f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		comedi_free_irq(dev->irq, dev);
274f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
275f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
276f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
277f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
278f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
27970265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d)
280f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
2812696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* struct comedi_device *dev = d; */
282f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return IRQ_HANDLED;
283f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
284f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
285f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
286f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered"
287f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * mode.
288f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */
289da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
290da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
291f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
292f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
293f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int to;
294f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int aref;
295f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int range;
296f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan;
297f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
298f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
299f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	chan = CR_CHAN(insn->chanspec);
300f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	aref = CR_AREF(insn->chanspec);
301f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	range = CR_RANGE(insn->chanspec);
302f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
303f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(chan, dev->iobase + 2);
304f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
305f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 &= ~0xf320;
306f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
307f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status1, dev->iobase + 4);
308f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
309f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0xff00;
310f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= range_bits[range];
311f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
312f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
313f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
314f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(0, dev->iobase);
315f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
316f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define TIMEOUT 1000
317f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (to = 0; to < TIMEOUT; to++) {
318f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (inw(dev->iobase + 4) & 0x0080)
319f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				break;
320f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
321f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (to == TIMEOUT) {
322f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			printk("cb_das16_cs: ai timeout\n");
323f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return -ETIME;
324f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
325f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = (unsigned short)inw(dev->iobase + 0);
326f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
327f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
328f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
329f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
330f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
331da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
332f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
336da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
337da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_cmd *cmd)
338f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
339f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int err = 0;
340f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int tmp;
341f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
342f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* cmdtest tests a particular command to see if it is valid.
343f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * Using the cmdtest ioctl, a user can create a valid cmd
344f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * and then have it executes by the cmd ioctl.
345f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 *
346f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
347f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * the command passes. */
348f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
349f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
350f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
351f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->start_src;
352f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->start_src &= TRIG_NOW;
353f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
354f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
355f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
356f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_begin_src;
357f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
358f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
359f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
360f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
361f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->convert_src;
362f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
363f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
364f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
365f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
366f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_end_src;
367f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
368f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
369f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
370f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
371f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->stop_src;
372f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
373f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
374f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
375f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
376f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
377f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 1;
378f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
379f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 2: make sure trigger sources are unique and mutually compatible */
380f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
381f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* note that mutual compatiblity is not an issue here */
382f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
383f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->scan_begin_src != TRIG_EXT)
384f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
385f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
386f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
387f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
388f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
389f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
390f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
391f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 2;
392f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
393f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 3: make sure arguments are trivially compatible */
394f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
395f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->start_arg != 0) {
396f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->start_arg = 0;
397f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
398f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
399f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MAX_SPEED	10000	/* in nanoseconds */
400f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MIN_SPEED	1000000000	/* in nanoseconds */
401f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
402f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
403f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
404f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
405f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
406f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
407f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > MIN_SPEED) {
408f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MIN_SPEED;
409f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
410f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
411f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
412f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
413f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should be level/edge, hi/lo specification here */
414f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should specify multiple external triggers */
415f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > 9) {
416f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = 9;
417f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
418f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
419f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
420f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
421f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg < MAX_SPEED) {
422f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MAX_SPEED;
423f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
424f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
425f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > MIN_SPEED) {
426f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MIN_SPEED;
427f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
428f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
429f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
430f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
431f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* see above */
432f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > 9) {
433f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = 9;
434f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
435f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
436f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
437f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
438f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
439f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
440f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
441f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
442f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
443f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg > 0x00ffffff) {
444f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0x00ffffff;
445f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
446f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
447f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
448f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* TRIG_NONE */
449f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg != 0) {
450f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0;
451f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
452f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
453f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
454f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
455f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
456f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 3;
457f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
458f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 4: fix up any arguments */
459f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
460f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
461f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		unsigned int div1, div2;
462f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
463f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->scan_begin_arg;
464f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
465f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
466f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->scan_begin_arg)
467f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
468f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
469f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
470f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		unsigned int div1, div2;
471f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
472f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->convert_arg;
473f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
474f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
475f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->convert_arg)
476f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
477f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_src == TRIG_TIMER &&
478f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg <
479f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg * cmd->scan_end_arg) {
480f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg =
481f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				cmd->convert_arg * cmd->scan_end_arg;
482f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
483f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
484f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
485f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
486f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
487f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 4;
488f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
489f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
490f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
491f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
492da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
493da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
494f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
495f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
496f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
497f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
498f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short d;
499f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bit;
500f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
501f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
502f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		devpriv->ao_readback[chan] = data[i];
503f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		d = data[i];
504f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
505f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(devpriv->status1, dev->iobase + 4);
506f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		comedi_udelay(1);
507f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
508f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		status1 = devpriv->status1 & ~0xf;
509f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (chan)
510f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0001;
511f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		else
512f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0008;
513f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
514f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 		printk("0x%04x\n",status1);*/
515f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1, dev->iobase + 4);
516f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		comedi_udelay(1);
517f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
518f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (bit = 15; bit >= 0; bit--) {
519f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			int b = (d >> bit) & 0x1;
520f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			b <<= 1;
521f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0000);*/
522f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0000, dev->iobase + 4);
523f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			comedi_udelay(1);
524f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0004);*/
525f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0004, dev->iobase + 4);
526f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			comedi_udelay(1);
527f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
528f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*		make high both DAC0CS and DAC1CS to load
529f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		new data and update analog output*/
530f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1 | 0x9, dev->iobase + 4);
531f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
532f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
533f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
534f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
535f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
536f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* AO subdevices should have a read insn as well as a write insn.
537f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Usually this means copying a value stored in devpriv. */
538da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
539da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
540f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
541f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
542f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
543f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
544f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++)
545f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = devpriv->ao_readback[chan];
546f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
547f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
548f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
549f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
550f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* DIO devices are slightly special.  Although it is possible to
551f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * implement the insn_read/insn_write interface, it is much more
552f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * useful to applications if you implement the insn_bits interface.
553f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * This allows packed reading/writing of the DIO channels.  The
554f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * comedi core can convert between insn_bits and insn_read/write */
555da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
556da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
557f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
558f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (insn->n != 2)
559f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
560f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
561f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (data[0]) {
562f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state &= ~data[0];
563f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state |= data[0] & data[1];
564f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
565f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(s->state, dev->iobase + 16);
566f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
567f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
568f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* on return, data[1] contains the value of the digital
569f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * input and output lines. */
570f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	data[1] = inw(dev->iobase + 16);
571f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
572f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 2;
573f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
574f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
575da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
576da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
577f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
578f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
579f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bits;
580f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
581f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (chan < 4)
582f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0x0f;
583f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	else
584f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0xf0;
585f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
586f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	switch (data[0]) {
587f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
588f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits |= bits;
589f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
590f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_INPUT:
591f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits &= bits;
592f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
593f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_QUERY:
594f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[1] =
595f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			(s->
596f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
597f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return insn->n;
598f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
599f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	default:
600f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
601f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
602f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
603f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
604f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0x00c0;
605f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
606f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
607f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
608f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
609f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
610f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return insn->n;
611f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
612f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
613da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
614da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
615f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
618f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
619da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
620da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
621f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
622f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
623f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
624f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
625f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* PCMCIA stuff */
626f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
627f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
628f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
629f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The following pcmcia code for the pcm-das08 is adapted from the
630f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    dummy_cs.c driver of the Linux PCMCIA Card Services package.
631f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
632f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The initial developer of the original code is David A. Hinds
633f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
634f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
635f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
636f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
637f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
638f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
639f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
640f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   you do not define PCMCIA_DEBUG at all, all the debug code will be
641f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
642f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   be present but disabled -- but it can then be enabled for specific
643f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   modules at load time with a 'pc_debug=#' option to insmod.
644f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
645f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
646f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
647f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#ifdef PCMCIA_DEBUG
648f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int pc_debug = PCMCIA_DEBUG;
649f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefmodule_param(pc_debug, int, 0644);
650f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
651f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic char *version =
652f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	"cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
653f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
654f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DEBUG(n, args...)
655f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#endif
656f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
657f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
658f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
659f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link);
660f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link);
661f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
662f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
663f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
664f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
665f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The attach() and detach() entry points are used to create and destroy
666f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   "instances" of the driver, where each instance represents everything
667f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   needed to manage one actual PCMCIA card.
668f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
669f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
670f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *);
671f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *);
672f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
673f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
674f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   You'll also need to prototype all the functions that will actually
675f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   be used to talk to your device.  See 'memory_cs' for a good example
676f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   of a fully self-sufficient driver; the other drivers rely more or
677f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   less on other parts of the kernel.
678f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
679f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
680f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
681f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The dev_info variable is the "key" that is used to match up this
682f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   device driver with appropriate cards, through the card configuration
683f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   database.
684f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
685f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
686f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic dev_info_t dev_info = "cb_das16_cs";
687f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
688d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pembertonstruct local_info_t {
689f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
690f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev_node_t node;
691f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int stop;
692f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct bus_operations *bus;
693d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton};
694f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
695f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
696f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
697f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
698f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    local data structures for one device.  The device is registered
699f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    with Card Services.
700f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
701f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The dev_link structure is initialized, but we don't actually
702f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    configure the card at this point -- we wait until we receive a
703f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    card insertion event.
704f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
705f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
706f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
707f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *link)
708f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
709d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local;
710f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
711f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_attach()\n");
712f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
713f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Allocate space for private device-specific data */
714d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
715f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!local)
716f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
717f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->link = link;
718f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->priv = local;
719f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
720f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Initialize the pcmcia_device structure */
721f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Interrupt setup */
722f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
723f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
724f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->irq.Handler = NULL;
725f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
726f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.Attributes = 0;
727f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.IntType = INT_MEMORY_AND_IO;
728f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
729f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cur_dev = link;
730f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
731f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_config(link);
732f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
733f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
734f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_attach */
735f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
736f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *link)
737f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
738f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
739f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
740f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->dev_node) {
741d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton		((struct local_info_t *) link->priv)->stop = 1;
742f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		das16cs_pcmcia_release(link);
743f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
744d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	/* This points to the parent struct local_info_t struct */
745f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->priv)
746f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		kfree(link->priv);
747f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_detach */
748f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
749f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link)
750f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
751d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *dev = link->priv;
752f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple_t tuple;
753f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cisparse_t parse;
754f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int last_fn, last_ret;
755f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	u_char buf[64];
756f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cistpl_cftable_entry_t dflt = { 0 };
757f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
758f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link);
759f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
760f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
761f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   This reads the card's CONFIG tuple to find its configuration
762f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   registers.
763f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
764f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.DesiredTuple = CISTPL_CONFIG;
765f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.Attributes = 0;
766f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleData = buf;
767f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleDataMax = sizeof(buf);
768f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.TupleOffset = 0;
769c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
770f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetFirstTuple;
771c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	last_ret = pcmcia_get_first_tuple(link, &tuple);
772c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (last_ret != 0)
773f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
774c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
775f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetTupleData;
776c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	last_ret = pcmcia_get_tuple_data(link, &tuple);
777c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (last_ret != 0)
778f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
779c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
780f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = ParseTuple;
781c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	last_ret = pcmcia_parse_tuple(&tuple, &parse);
782c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (last_ret != 0)
783f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
784c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.ConfigBase = parse.config.base;
786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.Present = parse.config.rmask[0];
787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
789f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   In this loop, we scan the CIS for configuration table entries,
790f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   each of which describes a valid card configuration, including
791f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   voltage, IO window, memory window, and interrupt settings.
792f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
793f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   We make no assumptions about the card to be configured: we use
794f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   just the information available in the CIS.  In an ideal world,
795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   this would work for any PCMCIA card, but it requires a complete
796f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   and accurate CIS.  In practice, a driver usually "knows" most of
797f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   these things without consulting the CIS, and most client drivers
798f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   will only use the CIS to fill in implementation-defined details.
799f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
800f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
801f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetFirstTuple;
802c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
803c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	last_ret = pcmcia_get_first_tuple(link, &tuple);
804c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (last_ret)
805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
806c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
807f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	while (1) {
808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
809f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (pcmcia_get_tuple_data(link, &tuple))
810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
811de15d7fcd6452894e82657fb44b7b93c2afe97a4Ian Abbott		if (pcmcia_parse_tuple(&tuple, &parse))
812f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			dflt = *cfg;
816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->index == 0)
817f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.ConfigIndex = cfg->index;
819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
820f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* Does this card need audio output? */
821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.Attributes |= CONF_ENABLE_SPKR;
823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.Status = CCSR_AUDIO_ENA;
824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
825f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
826f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* Do we need to allocate an interrupt? */
827f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
828f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->conf.Attributes |= CONF_ENABLE_IRQ;
829f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
830f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* IO window settings */
831f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->io.NumPorts1 = link->io.NumPorts2 = 0;
832f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
833f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
834f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
835f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (!(io->flags & CISTPL_IO_8BIT))
836f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
837f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (!(io->flags & CISTPL_IO_16BIT))
838f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
839f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
840f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort1 = io->win[0].base;
841f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.NumPorts1 = io->win[0].len;
842f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (io->nwin > 1) {
843f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes2 = link->io.Attributes1;
844f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.BasePort2 = io->win[1].base;
845f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.NumPorts2 = io->win[1].len;
846f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			}
847f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			/* This reserves IO space but doesn't actually enable it */
848f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (pcmcia_request_io(link, &link->io))
849f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				goto next_entry;
850f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
851f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
852f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* If we got this far, we're cool! */
853f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
854f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
855f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      next_entry:
856f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		last_fn = GetNextTuple;
857c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
858c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		last_ret = pcmcia_get_next_tuple(link, &tuple);
859c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		if (last_ret)
860f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto cs_failed;
861f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
862f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
863f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
864f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   Allocate an interrupt line.  Note that this does not assign a
865f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   handler to the interrupt, unless the 'Handler' member of the
866f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   irq structure is initialized.
867f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
868f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
869f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		last_fn = RequestIRQ;
870c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
871c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		last_ret = pcmcia_request_irq(link, &link->irq);
872c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		if (last_ret)
873f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto cs_failed;
874f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
875f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
876f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   This actually configures the PCMCIA socket -- setting up
877f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   the I/O windows and the interrupt mapping, and putting the
878f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   card and host interface into "Memory and IO" mode.
879f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
880f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = RequestConfiguration;
881c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	last_ret = pcmcia_request_configuration(link, &link->conf);
882c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (last_ret)
883f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
884f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
885f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
886f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   At this point, the dev_node_t structure(s) need to be
887f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   initialized and arranged in a linked list at link->dev.
888f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
889f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	sprintf(dev->node.dev_name, "cb_das16_cs");
890f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->node.major = dev->node.minor = 0;
891f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->dev_node = &dev->node;
892f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
893f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Finally, report what we've done */
894f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk(KERN_INFO "%s: index 0x%02x",
895f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		dev->node.dev_name, link->conf.ConfigIndex);
896f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ)
897f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", irq %u", link->irq.AssignedIRQ);
898f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts1)
899f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
900f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort1 + link->io.NumPorts1 - 1);
901f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts2)
902f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
903f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort2 + link->io.NumPorts2 - 1);
904f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
905f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
906f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return;
907f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
908f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      cs_failed:
909f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cs_error(link, last_fn, last_ret);
910f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_release(link);
911f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_config */
912f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
913f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link)
914f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
915f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
916f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_disable_device(link);
917f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_release */
918f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
919f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link)
920f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
921d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
922f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
923f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Mark the device as stopped, to block IO until later */
924f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 1;
925f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
926f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
927f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_suspend */
928f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
929f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link)
930f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
931d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
932f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
933f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 0;
934f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
935f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_resume */
936f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
937f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
938f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
939f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device_id das16cs_id_table[] = {
940f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
941f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
942f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_NULL
943f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
944f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
945f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
946f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
947f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = {
948f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.probe = das16cs_pcmcia_attach,
949f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.remove = das16cs_pcmcia_detach,
950f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.suspend = das16cs_pcmcia_suspend,
951f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.resume = das16cs_pcmcia_resume,
952f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.id_table = das16cs_id_table,
953f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.owner = THIS_MODULE,
954f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.drv = {
955f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			.name = dev_info,
956f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
957f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
958f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
959f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void)
960f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
961f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "%s\n", version);
962f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_register_driver(&das16cs_driver);
963f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
964f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
965f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
966f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void)
967f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
968f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
969f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_unregister_driver(&das16cs_driver);
970f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
971f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
972f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void)
973f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
974f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
975f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
976f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = init_das16cs_pcmcia_cs();
977f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0)
978f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
979f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
980f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return comedi_driver_register(&driver_das16cs);
981f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
982f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
983f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void)
984f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
985f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	exit_das16cs_pcmcia_cs();
986f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_driver_unregister(&driver_das16cs);
987f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
988f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
989f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
990f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefCOMEDI_INITCLEANUP(driver_das16cs);
9912696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#endif /* CONFIG_PCMCIA */
992