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
102036f419529d4dd83a1d46de04551d60994d1f372Ravishankar karkala Mallikarjunayyastatic struct pcmcia_device *cur_dev;
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
153cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "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
166cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "comedi%d: cb_das16_cs: attached\n", 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;
173cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "I/O base=0x%04lx\n", dev->iobase);
174f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
175cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "fingerprint:\n");
1767b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	for (i = 0; i < 48; i += 2)
177cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "%04x\n", inw(dev->iobase + i));
1787b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
179f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
180eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	ret = request_irq(link->irq, das16cs_interrupt,
1815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			  IRQF_SHARED, "cb_das16_cs", dev);
1827b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	if (ret < 0)
183f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
1847b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
185eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	dev->irq = link->irq;
186c8d1a126924fcbc1d61ceb830226e0c7afdcc841Greg Kroah-Hartman
187cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "irq=%u\n", dev->irq);
188f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
189f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_ptr = das16cs_probe(dev, link);
190f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!dev->board_ptr)
191f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EIO;
192f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
193f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->board_name = thisboard->name;
194f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
195bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
196f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
197f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
198f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (alloc_subdevices(dev, 4) < 0)
199f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
200f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
201f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 0;
202f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	dev->read_subdev = s;
203f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog input subdevice */
204f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->type = COMEDI_SUBD_AI;
205f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
206f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->n_chan = 16;
207f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->maxdata = 0xffff;
208f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->range_table = &das16cs_ai_range;
209f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->len_chanlist = 16;
210f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->insn_read = das16cs_ai_rinsn;
211f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmd = das16cs_ai_cmd;
212f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s->do_cmdtest = das16cs_ai_cmdtest;
213f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
214f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 1;
215f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* analog output subdevice */
216f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (thisboard->n_ao_chans) {
217f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_AO;
218f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_WRITABLE;
219f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = thisboard->n_ao_chans;
220f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xffff;
221f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_bipolar10;
222f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_write = &das16cs_ao_winsn;
223f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = &das16cs_ao_rinsn;
224f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
225f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
226f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 2;
227f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* digital i/o subdevice */
228f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (1) {
229f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_DIO;
230f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
231f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 8;
232f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 1;
233f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_digital;
234f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_bits = das16cs_dio_insn_bits;
235f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_dio_insn_config;
236f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
237f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
238f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
239f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
240f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	s = dev->subdevices + 3;
241f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* timer subdevice */
242f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (0) {
243f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_TIMER;
244f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
245f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->n_chan = 1;
246f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->maxdata = 0xff;
247f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->range_table = &range_unknown;
248f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_read = das16cs_timer_insn_read;
249f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->insn_config = das16cs_timer_insn_config;
250f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
251f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->type = COMEDI_SUBD_UNUSED;
252f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
253f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
254f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
255f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 1;
256f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
257f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
258da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev)
259f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
260cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "comedi%d: das16cs: remove\n", dev->minor);
261f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
2627b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong	if (dev->irq)
2635f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
2647b8f2d1a2ece4180ac5fe418bf915efe728583a8Jason Wong
265f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
266f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
267f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
268f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
26970265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d)
270f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
2712696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* struct comedi_device *dev = d; */
272f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return IRQ_HANDLED;
273f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
274f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
275f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
276f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered"
277f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * mode.
278f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev,
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
282f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
283f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
284f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int to;
285f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int aref;
286f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int range;
287f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan;
288f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };
289f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
290f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	chan = CR_CHAN(insn->chanspec);
291f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	aref = CR_AREF(insn->chanspec);
292f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	range = CR_RANGE(insn->chanspec);
293f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
294f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(chan, dev->iobase + 2);
295f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
296f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 &= ~0xf320;
297f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020;
298f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status1, dev->iobase + 4);
299f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
300f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0xff00;
301f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= range_bits[range];
302f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
303f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
304f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
305f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(0, dev->iobase);
306f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
307f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define TIMEOUT 1000
308f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (to = 0; to < TIMEOUT; to++) {
309f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			if (inw(dev->iobase + 4) & 0x0080)
310f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef				break;
311f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
312f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (to == TIMEOUT) {
313cc780e8f92e1576e4ac867e5d26d22ffbc39ddd8Ravishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "cb_das16_cs: ai timeout\n");
314f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			return -ETIME;
315f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
316f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = (unsigned short)inw(dev->iobase + 0);
317f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
318f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
319f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
320f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
321f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
322da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
323f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
324f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
325f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
326f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev,
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
330f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
331f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int err = 0;
332f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int tmp;
333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* cmdtest tests a particular command to see if it is valid.
335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * Using the cmdtest ioctl, a user can create a valid cmd
336f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * and then have it executes by the cmd ioctl.
337f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 *
338f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
339f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * the command passes. */
340f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
341f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
342f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
343f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->start_src;
344f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->start_src &= TRIG_NOW;
345f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
346f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
347f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
348f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_begin_src;
349f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
350f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
351f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
352f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
353f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->convert_src;
354f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
355f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
356f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
357f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
358f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->scan_end_src;
359f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
360f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
361f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
362f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
363f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	tmp = cmd->stop_src;
364f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
365f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
366f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
367f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
368f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
369f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 1;
370f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
371589cabe1b13576b85419d73ba87e50f7f80463fbChristopher Rice	/* step 2: make sure trigger sources are unique and
372589cabe1b13576b85419d73ba87e50f7f80463fbChristopher Rice	 * mutually compatible */
373f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
374828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
375f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
377f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
378f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
379f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
380f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
381f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
382f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
383f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
384f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 2;
385f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
386f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 3: make sure arguments are trivially compatible */
387f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
388f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->start_arg != 0) {
389f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->start_arg = 0;
390f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
391f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
392f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MAX_SPEED	10000	/* in nanoseconds */
393f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MIN_SPEED	1000000000	/* in nanoseconds */
394f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
395f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
396f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
397f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
398f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
399f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
400f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > MIN_SPEED) {
401f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = MIN_SPEED;
402f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
403f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
404f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
405f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
406f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should be level/edge, hi/lo specification here */
407f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* should specify multiple external triggers */
408f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_arg > 9) {
409f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg = 9;
410f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
411f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
412f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
413f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
414f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg < MAX_SPEED) {
415f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MAX_SPEED;
416f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
417f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
418f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > MIN_SPEED) {
419f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = MIN_SPEED;
420f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
421f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
422f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
423f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* external trigger */
424f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* see above */
425f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->convert_arg > 9) {
426f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->convert_arg = 9;
427f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
428f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
429f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
430f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
431f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
432f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
433f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		err++;
434f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
435f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
436f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg > 0x00ffffff) {
437f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0x00ffffff;
438f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
439f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
440f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	} else {
441f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		/* TRIG_NONE */
442f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->stop_arg != 0) {
443f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->stop_arg = 0;
444f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
445f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
446f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
447f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
448f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
449f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 3;
450f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
451f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* step 4: fix up any arguments */
452f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
453f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
45448b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
455f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
456f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->scan_begin_arg;
457f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
460f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->scan_begin_arg)
461f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
462f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
463f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (cmd->convert_src == TRIG_TIMER) {
46448b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott		unsigned int div1 = 0, div2 = 0;
465f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
466f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		tmp = cmd->convert_arg;
467f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		i8253_cascade_ns_to_timer(100, &div1, &div2,
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->scan_begin_arg,
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
470f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (tmp != cmd->convert_arg)
471f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
472f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (cmd->scan_begin_src == TRIG_TIMER &&
4730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->scan_begin_arg <
4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->convert_arg * cmd->scan_end_arg) {
475f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			cmd->scan_begin_arg =
4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    cmd->convert_arg * cmd->scan_end_arg;
477f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			err++;
478f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
479f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
480f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
481f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (err)
482f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return 4;
483f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
484f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
485f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
486f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
4870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev,
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
490f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
491f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
492f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
493f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short status1;
494f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	unsigned short d;
495f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bit;
496f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
497f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++) {
498f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		devpriv->ao_readback[chan] = data[i];
499f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		d = data[i];
500f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
501f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(devpriv->status1, dev->iobase + 4);
5025f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
503f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
504f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		status1 = devpriv->status1 & ~0xf;
505f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		if (chan)
506f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0001;
507f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		else
508f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			status1 |= 0x0008;
509f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
510589cabe1b13576b85419d73ba87e50f7f80463fbChristopher Rice/*		printk("0x%04x\n",status1);*/
511f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1, dev->iobase + 4);
5125f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
513f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
514f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		for (bit = 15; bit >= 0; bit--) {
515f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			int b = (d >> bit) & 0x1;
516f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			b <<= 1;
517f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0000);*/
518f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0000, dev->iobase + 4);
5195f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
520f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*			printk("0x%04x\n",status1 | b | 0x0004);*/
521f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef			outw(status1 | b | 0x0004, dev->iobase + 4);
5225f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
523f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		}
524f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*		make high both DAC0CS and DAC1CS to load
525f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		new data and update analog output*/
526f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(status1 | 0x9, dev->iobase + 4);
527f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
528f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
529f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
530f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
531f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
532f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* AO subdevices should have a read insn as well as a write insn.
533f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Usually this means copying a value stored in devpriv. */
5340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev,
5350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
537f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
538f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int i;
539f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
540f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
541f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	for (i = 0; i < insn->n; i++)
542f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[i] = devpriv->ao_readback[chan];
543f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
544f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return i;
545f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
546f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
547f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* DIO devices are slightly special.  Although it is possible to
548f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * implement the insn_read/insn_write interface, it is much more
549f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * useful to applications if you implement the insn_bits interface.
550f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * This allows packed reading/writing of the DIO channels.  The
551f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * comedi core can convert between insn_bits and insn_read/write */
5520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev,
5530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data)
555f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
556f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (insn->n != 2)
557f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
558f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
559f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (data[0]) {
560f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state &= ~data[0];
561f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->state |= data[0] & data[1];
562f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
563f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		outw(s->state, dev->iobase + 16);
564f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
565f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
566f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* on return, data[1] contains the value of the digital
567f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	 * input and output lines. */
568f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	data[1] = inw(dev->iobase + 16);
569f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
570f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 2;
571f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
572f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
5730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev,
5740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
5750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
576f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
577f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int chan = CR_CHAN(insn->chanspec);
578f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int bits;
579f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
580f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (chan < 4)
581f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0x0f;
582f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	else
583f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		bits = 0xf0;
584f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
585f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	switch (data[0]) {
586f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
587f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits |= bits;
588f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
589f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_INPUT:
590f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		s->io_bits &= bits;
591f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
592f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	case INSN_CONFIG_DIO_QUERY:
593f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		data[1] =
5940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
595f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return insn->n;
596f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
597f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	default:
598f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -EINVAL;
599f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		break;
600f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
601f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
602f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 &= ~0x00c0;
603f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
604f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0;
605f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
606f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	outw(devpriv->status2, dev->iobase + 6);
607f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
608f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return insn->n;
609f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
610f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
6110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev,
6120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
6130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
614f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
615f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev,
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
6200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
6210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data)
622f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
623f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return -EINVAL;
624f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
625f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
626f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* PCMCIA stuff */
627f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
628f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
629f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
630f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The following pcmcia code for the pcm-das08 is adapted from the
631f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    dummy_cs.c driver of the Linux PCMCIA Card Services package.
632f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
633f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The initial developer of the original code is David A. Hinds
634f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
635f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
636f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
637f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
638f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
639f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
640f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
641f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link);
642f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link);
643f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev);
644f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *p_dev);
645f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
646f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
647f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   The attach() and detach() entry points are used to create and destroy
648f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   "instances" of the driver, where each instance represents everything
649f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   needed to manage one actual PCMCIA card.
650f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
651f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
652f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *);
653f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *);
654f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
655f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*
656f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   You'll also need to prototype all the functions that will actually
657f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   be used to talk to your device.  See 'memory_cs' for a good example
658f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   of a fully self-sufficient driver; the other drivers rely more or
659f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef   less on other parts of the kernel.
660f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/
661f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
662d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pembertonstruct local_info_t {
663f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct pcmcia_device *link;
664f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int stop;
665f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	struct bus_operations *bus;
666d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton};
667f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
668f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*======================================================================
669f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
670f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    das16cs_pcmcia_attach() creates an "instance" of the driver, allocating
671f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    local data structures for one device.  The device is registered
672f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    with Card Services.
673f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
674f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    The dev_link structure is initialized, but we don't actually
675f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    configure the card at this point -- we wait until we receive a
676f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef    card insertion event.
677f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
678f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/
679f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
680f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *link)
681f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
682d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local;
683f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
68455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_attach()\n");
685f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
686f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Allocate space for private device-specific data */
687d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
688f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (!local)
689f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return -ENOMEM;
690f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->link = link;
691f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	link->priv = local;
692f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
693f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	cur_dev = link;
694f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
695f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_config(link);
696f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
697f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
698f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_attach */
699f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
700f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *link)
701f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
70255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_detach\n");
703f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
704eb8804f654a512a1a4e2f189d1bbaa41565e46b5Javier Martinez Canillas	((struct local_info_t *)link->priv)->stop = 1;
705eb8804f654a512a1a4e2f189d1bbaa41565e46b5Javier Martinez Canillas	das16cs_pcmcia_release(link);
706d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	/* This points to the parent struct local_info_t struct */
707f25bd6bfdf9bccd8164c151b027f9c14ec07960bDan Carpenter	kfree(link->priv);
708f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_detach */
709f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
710f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
71155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
71255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				void *priv_data)
71355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
71400990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	if (p_dev->config_index == 0)
71555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		return -EINVAL;
716f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
71700990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	return pcmcia_request_io(p_dev);
71855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski}
71955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski
72055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic void das16cs_pcmcia_config(struct pcmcia_device *link)
72155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
72255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	int ret;
723f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
72455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
725c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
72600990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	/* Do we need to allocate an interrupt? */
72700990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
72800990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski
72955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
73055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret) {
73155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		dev_warn(&link->dev, "no configuration found\n");
73255a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
733f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	}
734f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
735eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	if (!link->irq)
736eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski		goto failed;
737eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski
7381ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski	ret = pcmcia_enable_device(link);
73955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret)
74055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
741f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
742f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return;
743f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
74455a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskifailed:
745f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	das16cs_pcmcia_release(link);
746f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_config */
747f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
748f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link)
749f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
75055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "das16cs_pcmcia_release\n");
751f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_disable_device(link);
752f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_release */
753f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
754f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link)
755f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
756d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
757f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
758f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	/* Mark the device as stopped, to block IO until later */
759f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 1;
760f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
761f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
762f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_suspend */
763f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
764f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link)
765f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
766d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton	struct local_info_t *local = link->priv;
767f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
768f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	local->stop = 0;
769f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
770f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}				/* das16cs_pcmcia_resume */
771f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
772f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/
773f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
7742202a5a7490a9de282846ea8d4a56d0249e09033Joe Perchesstatic const struct pcmcia_device_id das16cs_id_table[] = {
775f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039),
776f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009),
777f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	PCMCIA_DEVICE_NULL
778f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
779f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
780f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
7816c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
7826c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_DESCRIPTION("Comedi driver for Computer Boards PC-CARD DAS16/16");
7836c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_LICENSE("GPL");
784f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = {
786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.probe = das16cs_pcmcia_attach,
787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.remove = das16cs_pcmcia_detach,
788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.suspend = das16cs_pcmcia_suspend,
789f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.resume = das16cs_pcmcia_resume,
790f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.id_table = das16cs_id_table,
791f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	.owner = THIS_MODULE,
7922e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski	.name = "cb_das16_cs",
793f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef};
794f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void)
796f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
797f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_register_driver(&das16cs_driver);
798f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return 0;
799f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
800f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
801f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void)
802f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
80355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	pr_debug("das16cs_pcmcia_cs: unloading\n");
804f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	pcmcia_unregister_driver(&das16cs_driver);
805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
806f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
807f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void)
808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
809f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	int ret;
810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
811f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	ret = init_das16cs_pcmcia_cs();
812f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	if (ret < 0)
813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef		return ret;
814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	return comedi_driver_register(&driver_das16cs);
816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
817f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void)
819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{
820f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	exit_das16cs_pcmcia_cs();
821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef	comedi_driver_unregister(&driver_das16cs);
822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}
823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef
824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else
8257114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_das16cs_init_module(void)
8267114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
8277114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_das16cs);
8287114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
8297114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
8307114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_das16cs_cleanup_module(void)
8317114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
8327114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_das16cs);
8337114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
8347114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
8357114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_das16cs_init_module);
8367114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_das16cs_cleanup_module);
8372696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#endif /* CONFIG_PCMCIA */
838