cb_das16_cs.c revision 2202a5a7490a9de282846ea8d4a56d0249e09033
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/cistpl.h>
41f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/ds.h>
42f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
43f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "8253.h"
44f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
45f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_SIZE			18
46f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
47f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_ADC_DATA		0
48f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO_MUX			2
49f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC1			4
50f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC2			6
51f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR0			8
52f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR1			10
53f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR2			12
54f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR_CONTROL		14
55f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO			16
56f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
573281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstruct das16cs_board {
58f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	const char *name;
59f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int device_id;
60f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int n_ao_chans;
613281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton};
623281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstatic const struct das16cs_board das16cs_boards[] = {
63f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x0000,	/* unknown */
650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PC-CARD DAS16/16",
660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 0,
670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
68f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x0039,
700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PC-CARD DAS16/16-AO",
710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 2,
720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
73f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	{
740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x4009,
750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "PCM-DAS16s/16",
760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_ao_chans = 0,
770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
78f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
79f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
80b6ac161364eccce1bea4a23a9de395883e90d7abStoyan Gaydarov#define n_boards ARRAY_SIZE(das16cs_boards)
813281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton#define thisboard ((const struct das16cs_board *)dev->board_ptr)
82f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
83bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pembertonstruct das16cs_private {
84f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
85f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
86790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int ao_readback[2];
87f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
88f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status2;
89bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton};
90bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton#define devpriv ((struct das16cs_private *)dev->private)
91f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev,
930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
94da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev);
95139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das16cs = {
9668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_das16_cs",
9768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das16cs_attach,
9968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das16cs_detach,
100f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
101f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
102f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device *cur_dev = NULL;
103f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1049ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange das16cs_ai_range = { 4, {
1050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-10, 10),
1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-5, 5),
1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-2.5, 2.5),
1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   RANGE(-1.25, 1.25),
1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							   }
110f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
111f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
11270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d);
1130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev,
1140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmd(struct comedi_device *dev,
1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev,
1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd);
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev,
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev,
1250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
1270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev,
1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data);
1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev,
1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev,
1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
1380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev,
1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
1400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data);
142814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton
1430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic const struct das16cs_board *das16cs_probe(struct comedi_device *dev,
1440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						 struct pcmcia_device *link)
145f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
146f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
147f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
148f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < n_boards; i++) {
14955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		if (das16cs_boards[i].device_id == link->card_id)
150f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return das16cs_boards + i;
151f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
152f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
153f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("unknown board!\n");
154f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
155f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return NULL;
156f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
157f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
1580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev,
1590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
160f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
161f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
16234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
163f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
164f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
165f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
166f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: cb_das16_cs: ", dev->minor);
167f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
168f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link = cur_dev;		/* XXX hack */
169f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!link)
170f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
171f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
172859171ca92f2865453b4b2e17bf679c67044a833Joe Perches	dev->iobase = link->resource[0]->start;
173f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("I/O base=0x%04lx ", dev->iobase);
174f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
175f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("fingerprint:\n");
1767b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	for (i = 0; i < 48; i += 2)
177f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		printk("%04x ", inw(dev->iobase + i));
1787b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
179f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("\n");
180f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
181eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	ret = request_irq(link->irq, das16cs_interrupt,
1825f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			  IRQF_SHARED, "cb_das16_cs", dev);
1837b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	if (ret < 0)
184f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
1857b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
186eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	dev->irq = link->irq;
187c8d1a126924fcbc1d61ceb830226e0c7afdcc841Greg Kroah-Hartman
188f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("irq=%u ", dev->irq);
189f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
190f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_ptr = das16cs_probe(dev, link);
191f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!dev->board_ptr)
192f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
193f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
194f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_name = thisboard->name;
195f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
196bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
197f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
198f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
199f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (alloc_subdevices(dev, 4) < 0)
200f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
201f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
202f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 0;
203f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->read_subdev = s;
204f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog input subdevice */
205f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->type = COMEDI_SUBD_AI;
206f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
207f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->n_chan = 16;
208f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->maxdata = 0xffff;
209f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->range_table = &das16cs_ai_range;
210f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->len_chanlist = 16;
211f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->insn_read = das16cs_ai_rinsn;
212f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmd = das16cs_ai_cmd;
213f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmdtest = das16cs_ai_cmdtest;
214f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
215f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 1;
216f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog output subdevice */
217f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (thisboard->n_ao_chans) {
218f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_AO;
219f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_WRITABLE;
220f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = thisboard->n_ao_chans;
221f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xffff;
222f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_bipolar10;
223f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_write = &das16cs_ao_winsn;
224f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = &das16cs_ao_rinsn;
225f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
226f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
227f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 2;
228f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* digital i/o subdevice */
229f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (1) {
230f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_DIO;
231f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
232f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 8;
233f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 1;
234f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_digital;
235f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_bits = das16cs_dio_insn_bits;
236f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_dio_insn_config;
237f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
238f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
239f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
240f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
241f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 3;
242f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* timer subdevice */
243f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (0) {
244f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_TIMER;
245f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
246f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 1;
247f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xff;
248f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_unknown;
249f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = das16cs_timer_insn_read;
250f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_timer_insn_config;
251f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
252f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
253f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
254f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
255f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("attached\n");
256f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
257f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 1;
258f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
259f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
260da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev)
261f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
262f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	printk("comedi%d: das16cs: remove\n", dev->minor);
263f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
2647b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	if (dev->irq)
2655f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
2667b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
267f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
268f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
269f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
270f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
27170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d)
272f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
2732696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* struct comedi_device *dev = d; */
274f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return IRQ_HANDLED;
275f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
276f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
277f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
278f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered"
279f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * mode.
280f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev,
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
284f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
285f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
286f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int to;
287f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int aref;
288f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int range;
289f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan;
290f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
291f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
292f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	chan = CR_CHAN(insn->chanspec);
293f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	aref = CR_AREF(insn->chanspec);
294f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	range = CR_RANGE(insn->chanspec);
295f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
296f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(chan, dev->iobase + 2);
297f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
298f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 &= ~0xf320;
299f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
300f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status1, dev->iobase + 4);
301f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
302f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0xff00;
303f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= range_bits[range];
304f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
305f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
306f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
307f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(0, dev->iobase);
308f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
309f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define TIMEOUT 1000
310f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (to = 0; to < TIMEOUT; to++) {
311f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (inw(dev->iobase + 4) & 0x0080)
312f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				break;
313f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
314f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (to == TIMEOUT) {
315f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			printk("cb_das16_cs: ai timeout\n");
316f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return -ETIME;
317f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
318f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = (unsigned short)inw(dev->iobase + 0);
319f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
320f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
321f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
322f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
323f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
324da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
325f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
326f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
327f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
328f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev,
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
332f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int err = 0;
334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int tmp;
335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
336f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* cmdtest tests a particular command to see if it is valid.
337f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * Using the cmdtest ioctl, a user can create a valid cmd
338f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * and then have it executes by the cmd ioctl.
339f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 *
340f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
341f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * the command passes. */
342f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
343f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
344f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
345f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->start_src;
346f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->start_src &= TRIG_NOW;
347f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
348f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
349f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
350f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_begin_src;
351f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
352f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
353f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
354f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
355f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->convert_src;
356f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
357f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
358f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
359f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
360f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_end_src;
361f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
362f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
363f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
364f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
365f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->stop_src;
366f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
367f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
368f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
369f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
370f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
371f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 1;
372f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
373f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 2: make sure trigger sources are unique and mutually compatible */
374f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
375828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
376f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
3770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
378f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
379f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
380f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
381f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
382f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
383f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
384f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
385f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 2;
386f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
387f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 3: make sure arguments are trivially compatible */
388f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
389f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->start_arg != 0) {
390f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->start_arg = 0;
391f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
392f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
393f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MAX_SPEED	10000	/* in nanoseconds */
394f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MIN_SPEED	1000000000	/* in nanoseconds */
395f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
396f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
397f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
398f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
399f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
400f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
401f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > MIN_SPEED) {
402f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MIN_SPEED;
403f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
404f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
405f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
406f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
407f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should be level/edge, hi/lo specification here */
408f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should specify multiple external triggers */
409f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > 9) {
410f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = 9;
411f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
412f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
413f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
414f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
415f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg < MAX_SPEED) {
416f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MAX_SPEED;
417f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
418f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
419f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > MIN_SPEED) {
420f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MIN_SPEED;
421f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
422f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
423f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
424f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
425f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* see above */
426f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > 9) {
427f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = 9;
428f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
429f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
430f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
431f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
432f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
433f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
434f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
435f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
436f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
437f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg > 0x00ffffff) {
438f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0x00ffffff;
439f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
440f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
441f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
442f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* TRIG_NONE */
443f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg != 0) {
444f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0;
445f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
446f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
447f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
448f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
449f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
450f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 3;
451f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
452f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 4: fix up any arguments */
453f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
454f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
45548b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
456f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
457f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->scan_begin_arg;
458f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
461f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->scan_begin_arg)
462f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
463f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
464f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
46548b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
466f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
467f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->convert_arg;
468f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
471f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->convert_arg)
472f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
473f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_src == TRIG_TIMER &&
4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->scan_begin_arg <
4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->convert_arg * cmd->scan_end_arg) {
476f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg =
4770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    cmd->convert_arg * cmd->scan_end_arg;
478f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
479f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
480f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
481f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
482f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
483f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 4;
484f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
485f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
486f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
487f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev,
4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
491f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
492f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
493f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
494f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
495f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short d;
496f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bit;
497f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
498f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
499f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		devpriv->ao_readback[chan] = data[i];
500f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		d = data[i];
501f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
502f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(devpriv->status1, dev->iobase + 4);
5035f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
504f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
505f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		status1 = devpriv->status1 & ~0xf;
506f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (chan)
507f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0001;
508f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		else
509f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0008;
510f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
511f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 		printk("0x%04x\n",status1);*/
512f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1, dev->iobase + 4);
5135f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
514f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
515f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (bit = 15; bit >= 0; bit--) {
516f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			int b = (d >> bit) & 0x1;
517f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			b <<= 1;
518f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0000);*/
519f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0000, dev->iobase + 4);
5205f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
521f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0004);*/
522f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0004, dev->iobase + 4);
5235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
524f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
525f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*		make high both DAC0CS and DAC1CS to load
526f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		new data and update analog output*/
527f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1 | 0x9, dev->iobase + 4);
528f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
529f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
530f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
531f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
532f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
533f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* AO subdevices should have a read insn as well as a write insn.
534f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Usually this means copying a value stored in devpriv. */
5350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev,
5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
538f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
539f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
540f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
541f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
542f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++)
543f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = devpriv->ao_readback[chan];
544f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
545f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
546f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
547f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
548f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* DIO devices are slightly special.  Although it is possible to
549f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * implement the insn_read/insn_write interface, it is much more
550f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * useful to applications if you implement the insn_bits interface.
551f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * This allows packed reading/writing of the DIO channels.  The
552f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * comedi core can convert between insn_bits and insn_read/write */
5530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev,
5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
5550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data)
556f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
557f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (insn->n != 2)
558f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
559f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
560f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (data[0]) {
561f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state &= ~data[0];
562f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state |= data[0] & data[1];
563f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
564f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(s->state, dev->iobase + 16);
565f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
566f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
567f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* on return, data[1] contains the value of the digital
568f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * input and output lines. */
569f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	data[1] = inw(dev->iobase + 16);
570f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
571f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 2;
572f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
573f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
5740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev,
5750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
5760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
577f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
578f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
579f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bits;
580f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
581f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (chan < 4)
582f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0x0f;
583f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	else
584f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0xf0;
585f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
586f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	switch (data[0]) {
587f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
588f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits |= bits;
589f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
590f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_INPUT:
591f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits &= bits;
592f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
593f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_QUERY:
594f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[1] =
5950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
596f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return insn->n;
597f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
598f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	default:
599f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
600f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
601f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
602f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
603f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0x00c0;
604f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
605f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
606f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
607f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
608f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
609f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return insn->n;
610f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
611f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
6120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev,
6130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
6140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
615f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
618f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev,
6200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
6210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
6220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data)
623f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
624f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
625f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
626f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
627f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* PCMCIA stuff */
628f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
629f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
630f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
631f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The following pcmcia code for the pcm-das08 is adapted from the
632f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    dummy_cs.c driver of the Linux PCMCIA Card Services package.
633f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
634f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The initial developer of the original code is David A. Hinds
635f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
636f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
637f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
638f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
639f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
640f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
641f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
642f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link);
643f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link);
644f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
645f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
646f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
647f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
648f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The attach() and detach() entry points are used to create and destroy
649f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   "instances" of the driver, where each instance represents everything
650f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   needed to manage one actual PCMCIA card.
651f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
652f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
653f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *);
654f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *);
655f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
656f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
657f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   You'll also need to prototype all the functions that will actually
658f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   be used to talk to your device.  See 'memory_cs' for a good example
659f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   of a fully self-sufficient driver; the other drivers rely more or
660f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   less on other parts of the kernel.
661f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
662f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
663d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pembertonstruct local_info_t {
664f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
665f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int stop;
666f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct bus_operations *bus;
667d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton};
668f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
669f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
670f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
671f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
672f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    local data structures for one device.  The device is registered
673f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    with Card Services.
674f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
675f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The dev_link structure is initialized, but we don't actually
676f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    configure the card at this point -- we wait until we receive a
677f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    card insertion event.
678f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
679f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
680f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
681f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *link)
682f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
683d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local;
684f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
68555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_attach()\n");
686f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
687f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Allocate space for private device-specific data */
688d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
689f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!local)
690f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
691f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->link = link;
692f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->priv = local;
693f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
694f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cur_dev = link;
695f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
696f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_config(link);
697f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
698f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
699f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_attach */
700f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
701f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *link)
702f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
70355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_detach\n");
704f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
705eb8804f654a512a1a4e2f189d1bbaa41565e46b5Javier Martinez Canillas	((struct local_info_t *)link->priv)->stop = 1;
706eb8804f654a512a1a4e2f189d1bbaa41565e46b5Javier Martinez Canillas	das16cs_pcmcia_release(link);
707d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	/* This points to the parent struct local_info_t struct */
708f25bd6bfdf9bccd8164c151b027f9c14ec07960bDan Carpenter	kfree(link->priv);
709f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_detach */
710f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
711f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
71255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
71355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				void *priv_data)
71455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
71500990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	if (p_dev->config_index == 0)
71655a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		return -EINVAL;
717f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
71800990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	return pcmcia_request_io(p_dev);
71955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski}
72055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski
72155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic void das16cs_pcmcia_config(struct pcmcia_device *link)
72255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
72355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	int ret;
724f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
72555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
726c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
72700990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	/* Do we need to allocate an interrupt? */
72800990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
72900990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski
73055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
73155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret) {
73255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		dev_warn(&link->dev, "no configuration found\n");
73355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
734f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
735f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
736eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	if (!link->irq)
737eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski		goto failed;
738eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski
7391ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski	ret = pcmcia_enable_device(link);
74055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret)
74155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
742f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
743f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return;
744f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
74555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskifailed:
746f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_release(link);
747f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_config */
748f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
749f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link)
750f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
75155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_release\n");
752f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_disable_device(link);
753f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_release */
754f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
755f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link)
756f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
757d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
758f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
759f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Mark the device as stopped, to block IO until later */
760f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 1;
761f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
762f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
763f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_suspend */
764f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
765f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link)
766f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
767d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
768f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
769f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 0;
770f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
771f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_resume */
772f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
773f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
774f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
7752202a5a7490a9de282846ea8d4a56d0249e09033Joe Perchesstatic const struct pcmcia_device_id das16cs_id_table[] = {
776f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
777f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
778f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_NULL
779f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
780f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
781f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
7826c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
7836c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_DESCRIPTION("Comedi driver for Computer Boards PC-CARD DAS16/16");
7846c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_LICENSE("GPL");
785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = {
787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.probe = das16cs_pcmcia_attach,
788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.remove = das16cs_pcmcia_detach,
789f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.suspend = das16cs_pcmcia_suspend,
790f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.resume = das16cs_pcmcia_resume,
791f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.id_table = das16cs_id_table,
792f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.owner = THIS_MODULE,
7932e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski	.name = "cb_das16_cs",
794f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
796f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void)
797f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
798f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_register_driver(&das16cs_driver);
799f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
800f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
801f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
802f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void)
803f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
80455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	pr_debug("das16cs_pcmcia_cs: unloading\n");
805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_unregister_driver(&das16cs_driver);
806f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
807f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void)
809f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
811f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
812f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = init_das16cs_pcmcia_cs();
813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0)
814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return comedi_driver_register(&driver_das16cs);
817f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void)
820f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	exit_das16cs_pcmcia_cs();
822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_driver_unregister(&driver_das16cs);
823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
825f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
8267114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_das16cs_init_module(void)
8277114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
8287114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_das16cs);
8297114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
8307114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
8317114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_das16cs_cleanup_module(void)
8327114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
8337114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_das16cs);
8347114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
8357114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
8367114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_das16cs_init_module);
8377114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_das16cs_cleanup_module);
8382696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#endif /* CONFIG_PCMCIA */
839