cb_das16_cs.c revision 5a0e3ad6af8660be21ca98a971cd00f331318c05
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
3425436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
355a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
36f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "../comedidev.h"
37f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/delay.h>
38f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/pci.h>
39f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
40f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs_types.h>
41f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs.h>
42f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cistpl.h>
43f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/ds.h>
44f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
45f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "8253.h"
46f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
47f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_SIZE			18
48f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
49f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_ADC_DATA		0
50f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO_MUX			2
51f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC1			4
52f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC2			6
53f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR0			8
54f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR1			10
55f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR2			12
56f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR_CONTROL		14
57f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO			16
58f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
593281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstruct das16cs_board {
60f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	const char *name;
61f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int device_id;
62f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int n_ao_chans;
633281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton};
643281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstatic const struct das16cs_board das16cs_boards[] = {
65f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x0000,	/* unknown */
670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PC-CARD DAS16/16",
680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 0,
690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
70f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x0039,
720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PC-CARD DAS16/16-AO",
730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 2,
740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
75f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x4009,
770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PCM-DAS16s/16",
780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 0,
790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
80f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
81f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
82b6ac161364eccce1bea4a23a9de395883e90d7abStoyan Gaydarov#define n_boards ARRAY_SIZE(das16cs_boards)
833281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton#define thisboard ((const struct das16cs_board *)dev->board_ptr)
84f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
85bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pembertonstruct das16cs_private {
86f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
87f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
88790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int ao_readback[2];
89f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
90f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status2;
91bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton};
92bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton#define devpriv ((struct das16cs_private *)dev->private)
93f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev,
950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
96da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev);
97139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das16cs = {
9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_das16_cs",
9968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
10068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das16cs_attach,
10168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das16cs_detach,
102f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
103f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
104f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device *cur_dev = NULL;
105f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1069ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange das16cs_ai_range = { 4, {
1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-10, 10),
1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-5, 5),
1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-2.5, 2.5),
1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-1.25, 1.25),
1110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   }
112f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
113f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
11470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d);
1150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev,
1160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmd(struct comedi_device *dev,
1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev,
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd);
1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev,
1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev,
1270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev,
1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data);
1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev,
1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev,
1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
1380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
1400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev,
1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
1430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data);
144814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton
1450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic const struct das16cs_board *das16cs_probe(struct comedi_device *dev,
1460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						 struct pcmcia_device *link)
147f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
148f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
149f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
150f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < n_boards; i++) {
15155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (das16cs_boards[i].device_id == link->card_id)
152f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return das16cs_boards + i;
153f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
154f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
155f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("unknown board!\n");
156f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
157f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return NULL;
158f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
159f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev,
1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
162f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
163f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
16434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
165f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
166f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
167f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
168f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: cb_das16_cs: ", dev->minor);
169f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
170f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link = cur_dev;		/* XXX hack */
171f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!link)
172f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
173f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
174f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->iobase = link->io.BasePort1;
175f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("I/O base=0x%04lx ", dev->iobase);
176f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
177f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("fingerprint:\n");
178f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < 48; i += 2) {
179f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk("%04x ", inw(dev->iobase + i));
180f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
181f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
182f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1835f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt,
1845f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			  IRQF_SHARED, "cb_das16_cs", dev);
185f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0) {
186f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
187f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
188f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->irq = link->irq.AssignedIRQ;
189f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("irq=%u ", dev->irq);
190f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
191f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_ptr = das16cs_probe(dev, link);
192f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!dev->board_ptr)
193f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
194f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
195f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_name = thisboard->name;
196f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
197bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
198f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
199f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
200f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (alloc_subdevices(dev, 4) < 0)
201f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
202f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
203f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 0;
204f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->read_subdev = s;
205f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog input subdevice */
206f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->type = COMEDI_SUBD_AI;
207f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
208f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->n_chan = 16;
209f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->maxdata = 0xffff;
210f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->range_table = &das16cs_ai_range;
211f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->len_chanlist = 16;
212f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->insn_read = das16cs_ai_rinsn;
213f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmd = das16cs_ai_cmd;
214f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmdtest = das16cs_ai_cmdtest;
215f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
216f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 1;
217f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog output subdevice */
218f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (thisboard->n_ao_chans) {
219f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_AO;
220f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_WRITABLE;
221f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = thisboard->n_ao_chans;
222f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xffff;
223f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_bipolar10;
224f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_write = &das16cs_ao_winsn;
225f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = &das16cs_ao_rinsn;
226f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
227f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
228f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 2;
229f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* digital i/o subdevice */
230f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (1) {
231f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_DIO;
232f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
233f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 8;
234f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 1;
235f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_digital;
236f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_bits = das16cs_dio_insn_bits;
237f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_dio_insn_config;
238f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
239f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
240f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
241f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
242f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 3;
243f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* timer subdevice */
244f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (0) {
245f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_TIMER;
246f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
247f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 1;
248f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xff;
249f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_unknown;
250f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = das16cs_timer_insn_read;
251f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_timer_insn_config;
252f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
253f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
254f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
255f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
256f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("attached\n");
257f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
258f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 1;
259f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
260f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
261da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev)
262f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
263f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: das16cs: remove\n", dev->minor);
264f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
265f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (dev->irq) {
2665f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
267f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
268f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
269f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
270f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
271f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
27270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d)
273f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
2742696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* struct comedi_device *dev = d; */
275f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return IRQ_HANDLED;
276f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
277f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
278f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
279f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered"
280f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * mode.
281f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev,
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
285f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
286f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
287f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int to;
288f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int aref;
289f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int range;
290f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan;
291f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
292f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
293f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	chan = CR_CHAN(insn->chanspec);
294f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	aref = CR_AREF(insn->chanspec);
295f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	range = CR_RANGE(insn->chanspec);
296f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
297f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(chan, dev->iobase + 2);
298f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
299f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 &= ~0xf320;
300f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
301f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status1, dev->iobase + 4);
302f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
303f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0xff00;
304f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= range_bits[range];
305f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
306f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
307f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
308f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(0, dev->iobase);
309f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
310f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define TIMEOUT 1000
311f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (to = 0; to < TIMEOUT; to++) {
312f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (inw(dev->iobase + 4) & 0x0080)
313f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				break;
314f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
315f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (to == TIMEOUT) {
316f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			printk("cb_das16_cs: ai timeout\n");
317f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return -ETIME;
318f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
319f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = (unsigned short)inw(dev->iobase + 0);
320f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
321f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
322f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
323f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
324f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
325da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
326f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
327f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
328f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
329f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int err = 0;
335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int tmp;
336f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
337f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* cmdtest tests a particular command to see if it is valid.
338f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * Using the cmdtest ioctl, a user can create a valid cmd
339f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * and then have it executes by the cmd ioctl.
340f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 *
341f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
342f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * the command passes. */
343f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
344f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
345f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
346f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->start_src;
347f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->start_src &= TRIG_NOW;
348f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
349f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
350f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
351f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_begin_src;
352f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
353f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
354f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
355f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
356f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->convert_src;
357f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
358f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
359f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
360f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
361f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_end_src;
362f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
363f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
364f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
365f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
366f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->stop_src;
367f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
368f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
369f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
370f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
371f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
372f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 1;
373f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
374f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 2: make sure trigger sources are unique and mutually compatible */
375f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
376828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
377f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
3780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
379f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
380f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
381f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
382f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
383f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
384f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
385f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
386f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 2;
387f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
388f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 3: make sure arguments are trivially compatible */
389f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
390f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->start_arg != 0) {
391f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->start_arg = 0;
392f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
393f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
394f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MAX_SPEED	10000	/* in nanoseconds */
395f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MIN_SPEED	1000000000	/* in nanoseconds */
396f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
397f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
398f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
399f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
400f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
401f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
402f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > MIN_SPEED) {
403f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MIN_SPEED;
404f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
405f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
406f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
407f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
408f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should be level/edge, hi/lo specification here */
409f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should specify multiple external triggers */
410f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > 9) {
411f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = 9;
412f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
413f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
414f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
415f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
416f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg < MAX_SPEED) {
417f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MAX_SPEED;
418f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
419f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
420f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > MIN_SPEED) {
421f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MIN_SPEED;
422f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
423f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
424f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
425f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
426f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* see above */
427f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > 9) {
428f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = 9;
429f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
430f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
431f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
432f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
433f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
434f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
435f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
436f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
437f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
438f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg > 0x00ffffff) {
439f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0x00ffffff;
440f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
441f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
442f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
443f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* TRIG_NONE */
444f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg != 0) {
445f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0;
446f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
447f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
448f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
449f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
450f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
451f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 3;
452f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
453f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 4: fix up any arguments */
454f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
455f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
45648b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
457f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
458f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->scan_begin_arg;
459f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
462f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->scan_begin_arg)
463f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
464f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
465f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
46648b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
467f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
468f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->convert_arg;
469f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
472f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->convert_arg)
473f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
474f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_src == TRIG_TIMER &&
4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->scan_begin_arg <
4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->convert_arg * cmd->scan_end_arg) {
477f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg =
4780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    cmd->convert_arg * cmd->scan_end_arg;
479f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
480f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
481f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
482f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
483f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
484f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 4;
485f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
486f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
487f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
488f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev,
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
492f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
493f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
494f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
495f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
496f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short d;
497f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bit;
498f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
499f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
500f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		devpriv->ao_readback[chan] = data[i];
501f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		d = data[i];
502f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
503f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(devpriv->status1, dev->iobase + 4);
5045f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
505f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
506f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		status1 = devpriv->status1 & ~0xf;
507f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (chan)
508f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0001;
509f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		else
510f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0008;
511f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
512f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 		printk("0x%04x\n",status1);*/
513f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1, dev->iobase + 4);
5145f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
515f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
516f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (bit = 15; bit >= 0; bit--) {
517f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			int b = (d >> bit) & 0x1;
518f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			b <<= 1;
519f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0000);*/
520f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0000, dev->iobase + 4);
5215f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
522f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0004);*/
523f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0004, dev->iobase + 4);
5245f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
525f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
526f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*		make high both DAC0CS and DAC1CS to load
527f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		new data and update analog output*/
528f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1 | 0x9, dev->iobase + 4);
529f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
530f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
531f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
532f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
533f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
534f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* AO subdevices should have a read insn as well as a write insn.
535f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Usually this means copying a value stored in devpriv. */
5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev,
5370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
539f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
540f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
541f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
542f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
543f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++)
544f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = devpriv->ao_readback[chan];
545f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
546f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
547f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
548f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
549f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* DIO devices are slightly special.  Although it is possible to
550f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * implement the insn_read/insn_write interface, it is much more
551f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * useful to applications if you implement the insn_bits interface.
552f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * This allows packed reading/writing of the DIO channels.  The
553f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * comedi core can convert between insn_bits and insn_read/write */
5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev,
5550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
5560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 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
5750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev,
5760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
5770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
578f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
579f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
580f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bits;
581f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
582f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (chan < 4)
583f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0x0f;
584f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	else
585f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0xf0;
586f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
587f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	switch (data[0]) {
588f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
589f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits |= bits;
590f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
591f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_INPUT:
592f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits &= bits;
593f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
594f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_QUERY:
595f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[1] =
5960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->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
6130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev,
6140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
6150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
618f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
619f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
6200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev,
6210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
6220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
6230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data)
624f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
625f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
626f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
627f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
628f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* PCMCIA stuff */
629f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
630f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
631f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
632f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The following pcmcia code for the pcm-das08 is adapted from the
633f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    dummy_cs.c driver of the Linux PCMCIA Card Services package.
634f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
635f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The initial developer of the original code is David A. Hinds
636f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
637f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
638f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
639f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
640f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
641f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
642f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
643f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link);
644f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link);
645f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
646f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
647f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
648f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
649f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The attach() and detach() entry points are used to create and destroy
650f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   "instances" of the driver, where each instance represents everything
651f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   needed to manage one actual PCMCIA card.
652f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
653f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
654f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *);
655f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *);
656f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
657f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
658f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   You'll also need to prototype all the functions that will actually
659f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   be used to talk to your device.  See 'memory_cs' for a good example
660f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   of a fully self-sufficient driver; the other drivers rely more or
661f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   less on other parts of the kernel.
662f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
663f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
664f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
665f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The dev_info variable is the "key" that is used to match up this
666f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   device driver with appropriate cards, through the card configuration
667f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   database.
668f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
669f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
670f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic dev_info_t dev_info = "cb_das16_cs";
671f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
672d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pembertonstruct local_info_t {
673f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
674f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev_node_t node;
675f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int stop;
676f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct bus_operations *bus;
677d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton};
678f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
679f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
680f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
681f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
682f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    local data structures for one device.  The device is registered
683f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    with Card Services.
684f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
685f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The dev_link structure is initialized, but we don't actually
686f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    configure the card at this point -- we wait until we receive a
687f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    card insertion event.
688f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
689f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
690f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
691f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *link)
692f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
693d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local;
694f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
69555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_attach()\n");
696f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
697f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Allocate space for private device-specific data */
698d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
699f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!local)
700f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
701f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->link = link;
702f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->priv = local;
703f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
704f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Initialize the pcmcia_device structure */
705f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Interrupt setup */
7063d1c28848ea37bf117940e10826f7a485aa32337Frank Mori Hess	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
707f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->irq.Handler = NULL;
708f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
709f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.Attributes = 0;
710f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->conf.IntType = INT_MEMORY_AND_IO;
711f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
712f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cur_dev = link;
713f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
714f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_config(link);
715f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
716f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
717f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_attach */
718f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
719f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *link)
720f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
72155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_detach\n");
722f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
723f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->dev_node) {
7240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		((struct local_info_t *)link->priv)->stop = 1;
725f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		das16cs_pcmcia_release(link);
726f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
727d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	/* This points to the parent struct local_info_t struct */
728f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->priv)
729f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		kfree(link->priv);
730f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_detach */
731f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
732f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
73355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
73455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				cistpl_cftable_entry_t *cfg,
73555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				cistpl_cftable_entry_t *dflt,
73655a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				unsigned int vcc,
73755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				void *priv_data)
73855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
73955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (cfg->index == 0)
74055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		return -EINVAL;
741f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
74255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	/* Do we need to allocate an interrupt? */
74355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
74455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
74555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski
74655a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	/* IO window settings */
74755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
74855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
74955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
75055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
75155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (!(io->flags & CISTPL_IO_8BIT))
75255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
75355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (!(io->flags & CISTPL_IO_16BIT))
75455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
75555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
75655a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		p_dev->io.BasePort1 = io->win[0].base;
75755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		p_dev->io.NumPorts1 = io->win[0].len;
75855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (io->nwin > 1) {
75955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			p_dev->io.Attributes2 = p_dev->io.Attributes1;
76055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			p_dev->io.BasePort2 = io->win[1].base;
76155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			p_dev->io.NumPorts2 = io->win[1].len;
762f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
76355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		/* This reserves IO space but doesn't actually enable it */
76455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		return pcmcia_request_io(p_dev, &p_dev->io);
76555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	}
766f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
76755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	return 0;
76855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski}
76955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski
77055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic void das16cs_pcmcia_config(struct pcmcia_device *link)
77155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
77255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	struct local_info_t *dev = link->priv;
77355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	int ret;
774f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
77555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
776c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
77755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
77855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret) {
77955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		dev_warn(&link->dev, "no configuration found\n");
78055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
781f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
782f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
783f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
784f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   Allocate an interrupt line.  Note that this does not assign a
785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   handler to the interrupt, unless the 'Handler' member of the
786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   irq structure is initialized.
787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
78955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		ret = pcmcia_request_irq(link, &link->irq);
79055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (ret)
79155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski			goto failed;
792f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
793f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
794f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   This actually configures the PCMCIA socket -- setting up
795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   the I/O windows and the interrupt mapping, and putting the
796f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   card and host interface into "Memory and IO" mode.
797f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
79855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	ret = pcmcia_request_configuration(link, &link->conf);
79955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret)
80055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
801f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
802f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/*
803f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   At this point, the dev_node_t structure(s) need to be
804f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	   initialized and arranged in a linked list at link->dev.
805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 */
806f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	sprintf(dev->node.dev_name, "cb_das16_cs");
807f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->node.major = dev->node.minor = 0;
808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->dev_node = &dev->node;
809f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Finally, report what we've done */
811f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk(KERN_INFO "%s: index 0x%02x",
8120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->node.dev_name, link->conf.ConfigIndex);
813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->conf.Attributes & CONF_ENABLE_IRQ)
814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", irq %u", link->irq.AssignedIRQ);
815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts1)
816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
8170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       link->io.BasePort1 + link->io.NumPorts1 - 1);
818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (link->io.NumPorts2)
819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
8200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       link->io.BasePort2 + link->io.NumPorts2 - 1);
821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return;
824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
82555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskifailed:
826f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_release(link);
827f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_config */
828f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
829f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link)
830f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
83155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_release\n");
832f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_disable_device(link);
833f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_release */
834f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
835f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link)
836f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
837d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
838f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
839f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Mark the device as stopped, to block IO until later */
840f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 1;
841f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
842f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
843f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_suspend */
844f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
845f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link)
846f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
847d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
848f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
849f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 0;
850f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
851f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_resume */
852f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
853f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
854f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
855f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device_id das16cs_id_table[] = {
856f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
857f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
858f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_NULL
859f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
860f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
861f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
862f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
863f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = {
864f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.probe = das16cs_pcmcia_attach,
865f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.remove = das16cs_pcmcia_detach,
866f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.suspend = das16cs_pcmcia_suspend,
867f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.resume = das16cs_pcmcia_resume,
868f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.id_table = das16cs_id_table,
869f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.owner = THIS_MODULE,
870f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.drv = {
8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		.name = dev_info,
872f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		},
873f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
874f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
875f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void)
876f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
877f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_register_driver(&das16cs_driver);
878f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
879f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
880f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
881f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void)
882f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
88355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	pr_debug("das16cs_pcmcia_cs: unloading\n");
884f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_unregister_driver(&das16cs_driver);
885f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
886f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
887f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void)
888f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
889f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
890f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
891f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = init_das16cs_pcmcia_cs();
892f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0)
893f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
894f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
895f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return comedi_driver_register(&driver_das16cs);
896f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
897f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
898f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void)
899f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
900f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	exit_das16cs_pcmcia_cs();
901f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_driver_unregister(&driver_das16cs);
902f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
903f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
904f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
905f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefCOMEDI_INITCLEANUP(driver_das16cs);
9062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#endif /* CONFIG_PCMCIA */
907