cb_das16_cs.c revision 790c55415aa31f4c732729f94d2c3a54f7d3bfc2
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
57f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleeftypedef struct das16cs_board_struct {
58f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	const char *name;
59f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int device_id;
60f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int n_ao_chans;
61f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} das16cs_board;
62f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic const das16cs_board das16cs_boards[] = {
63f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
64f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      device_id:0x0000,/* unknown */
65f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      name:	"PC-CARD DAS16/16",
66f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      n_ao_chans:0,
67f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
68f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
69f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      device_id:0x0039,
70f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      name:	"PC-CARD DAS16/16-AO",
71f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      n_ao_chans:2,
72f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
73f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
74f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      device_id:0x4009,
75f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      name:	"PCM-DAS16s/16",
76f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      n_ao_chans:0,
77f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
78f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
79f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
80f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
81f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define thisboard ((const das16cs_board *)dev->board_ptr)
82f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
83f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleeftypedef struct {
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;
89f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} das16cs_private;
90f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define devpriv ((das16cs_private *)dev->private)
91f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
92f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_attach(comedi_device * dev, comedi_devconfig * it);
93f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_detach(comedi_device * dev);
94f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic comedi_driver driver_das16cs = {
95f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      driver_name:"cb_das16_cs",
96f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      module:THIS_MODULE,
97f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      attach:das16cs_attach,
98f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      detach:das16cs_detach,
99f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
100f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
101f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device *cur_dev = NULL;
102f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
103f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic const 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
111f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
112f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
113790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
114f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_cmd(comedi_device * dev, comedi_subdevice * s);
115f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
116f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_cmd * cmd);
117f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
118790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
119f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
120790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
121f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
122790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
123f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
124790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
125f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
126790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
127f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
128790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
129f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
130f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int get_prodid(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
149f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic const das16cs_board *das16cs_probe(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
168f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_attach(comedi_device * dev, comedi_devconfig * it)
169f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
170f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
171f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	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
204f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (alloc_private(dev, sizeof(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
268f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_detach(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
279f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
280f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
281f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	//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 */
289f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
290790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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
331f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_cmd(comedi_device * dev, comedi_subdevice * s)
332f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
336f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
337f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	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
492f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
493790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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. */
538f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
539790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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 */
555f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
556790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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
575f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
576790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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
613f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
614790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
615f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
618f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
619f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
620790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	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
688f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleeftypedef struct 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;
693f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} local_info_t;
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{
709f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	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 */
714f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local = kzalloc(sizeof(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) {
741f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		((local_info_t *) link->priv)->stop = 1;
742f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		das16cs_pcmcia_release(link);
743f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
744f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* This points to the parent 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{
751f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	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;
769f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetFirstTuple;
770f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
771f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
772f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetTupleData;
773f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
774f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
775f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = ParseTuple;
776f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((last_ret = pcmcia_parse_tuple(link, &tuple, &parse)) != 0)
777f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
778f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.ConfigBase = parse.config.base;
779f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.Present = parse.config.rmask[0];
780f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
781f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
782f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   In this loop, we scan the CIS for configuration table entries,
783f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   each of which describes a valid card configuration, including
784f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   voltage, IO window, memory window, and interrupt settings.
785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   We make no assumptions about the card to be configured: we use
787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   just the information available in the CIS.  In an ideal world,
788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   this would work for any PCMCIA card, but it requires a complete
789f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   and accurate CIS.  In practice, a driver usually "knows" most of
790f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   these things without consulting the CIS, and most client drivers
791f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   will only use the CIS to fill in implementation-defined details.
792f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
793f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
794f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = GetFirstTuple;
795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
796f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
797f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	while (1) {
798f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
799f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (pcmcia_get_tuple_data(link, &tuple))
800f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
801f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (pcmcia_parse_tuple(link, &tuple, &parse))
802f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
803f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
804f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			dflt = *cfg;
806f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->index == 0)
807f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto next_entry;
808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.ConfigIndex = cfg->index;
809f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* Does this card need audio output? */
811f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
812f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.Attributes |= CONF_ENABLE_SPKR;
813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->conf.Status = CCSR_AUDIO_ENA;
814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* Do we need to allocate an interrupt? */
817f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->conf.Attributes |= CONF_ENABLE_IRQ;
819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
820f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* IO window settings */
821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		link->io.NumPorts1 = link->io.NumPorts2 = 0;
822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
825f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (!(io->flags & CISTPL_IO_8BIT))
826f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
827f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (!(io->flags & CISTPL_IO_16BIT))
828f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
829f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
830f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort1 = io->win[0].base;
831f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.NumPorts1 = io->win[0].len;
832f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (io->nwin > 1) {
833f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.Attributes2 = link->io.Attributes1;
834f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.BasePort2 = io->win[1].base;
835f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				link->io.NumPorts2 = io->win[1].len;
836f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			}
837f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			/* This reserves IO space but doesn't actually enable it */
838f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (pcmcia_request_io(link, &link->io))
839f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				goto next_entry;
840f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
841f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
842f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* If we got this far, we're cool! */
843f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
844f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
845f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	      next_entry:
846f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		last_fn = GetNextTuple;
847f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0)
848f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto cs_failed;
849f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
850f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
851f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
852f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   Allocate an interrupt line.  Note that this does not assign a
853f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   handler to the interrupt, unless the 'Handler' member of the
854f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   irq structure is initialized.
855f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
856f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
857f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		last_fn = RequestIRQ;
858f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0)
859f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			goto cs_failed;
860f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
861f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
862f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   This actually configures the PCMCIA socket -- setting up
863f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   the I/O windows and the interrupt mapping, and putting the
864f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   card and host interface into "Memory and IO" mode.
865f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
866f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	last_fn = RequestConfiguration;
867f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0)
868f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		goto cs_failed;
869f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
870f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
871f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   At this point, the dev_node_t structure(s) need to be
872f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   initialized and arranged in a linked list at link->dev.
873f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
874f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	sprintf(dev->node.dev_name, "cb_das16_cs");
875f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->node.major = dev->node.minor = 0;
876f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->dev_node = &dev->node;
877f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
878f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Finally, report what we've done */
879f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk(KERN_INFO "%s: index 0x%02x",
880f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		dev->node.dev_name, link->conf.ConfigIndex);
881f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ)
882f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", irq %u", link->irq.AssignedIRQ);
883f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts1)
884f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
885f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort1 + link->io.NumPorts1 - 1);
886f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts2)
887f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
888f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			link->io.BasePort2 + link->io.NumPorts2 - 1);
889f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
890f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
891f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return;
892f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
893f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef      cs_failed:
894f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cs_error(link, last_fn, last_ret);
895f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_release(link);
896f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_config */
897f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
898f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link)
899f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
900f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link);
901f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_disable_device(link);
902f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_release */
903f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
904f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link)
905f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
906f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local_info_t *local = link->priv;
907f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
908f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Mark the device as stopped, to block IO until later */
909f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 1;
910f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
911f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
912f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_suspend */
913f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
914f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link)
915f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
916f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local_info_t *local = link->priv;
917f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
918f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 0;
919f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
920f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_resume */
921f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
922f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
923f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
924f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device_id das16cs_id_table[] = {
925f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
926f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
927f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_NULL
928f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
929f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
930f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
931f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
932f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = {
933f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.probe = das16cs_pcmcia_attach,
934f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.remove = das16cs_pcmcia_detach,
935f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.suspend = das16cs_pcmcia_suspend,
936f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.resume = das16cs_pcmcia_resume,
937f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.id_table = das16cs_id_table,
938f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.owner = THIS_MODULE,
939f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.drv = {
940f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			.name = dev_info,
941f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
942f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
943f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
944f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void)
945f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
946f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "%s\n", version);
947f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_register_driver(&das16cs_driver);
948f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
949f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
950f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
951f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void)
952f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
953f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	DEBUG(0, "das16cs_pcmcia_cs: unloading\n");
954f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_unregister_driver(&das16cs_driver);
955f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
956f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
957f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void)
958f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
959f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
960f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
961f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = init_das16cs_pcmcia_cs();
962f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0)
963f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
964f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
965f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return comedi_driver_register(&driver_das16cs);
966f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
967f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
968f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void)
969f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
970f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	exit_das16cs_pcmcia_cs();
971f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_driver_unregister(&driver_das16cs);
972f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
973f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
974f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
975f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefCOMEDI_INITCLEANUP(driver_das16cs);
976f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#endif //CONFIG_PCMCIA
977