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