11f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks/*
21f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     comedi/drivers/ni_daq_700.c
31f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     Driver for DAQCard-700 DIO only
41f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     copied from 8255
51f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *
61f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     COMEDI - Linux Control and Measurement Device Interface
71f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     Copyright (C) 1998 David A. Schleef <ds@schleef.org>
81f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *
91f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     This program is free software; you can redistribute it and/or modify
101f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     it under the terms of the GNU General Public License as published by
111f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     the Free Software Foundation; either version 2 of the License, or
121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     (at your option) any later version.
131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *
141f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     This program is distributed in the hope that it will be useful,
151f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     but WITHOUT ANY WARRANTY; without even the implied warranty of
161f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     GNU General Public License for more details.
181f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *
191f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     You should have received a copy of the GNU General Public License
201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     along with this program; if not, write to the Free Software
211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
221f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks *
231f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks */
241f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks/*
261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksDriver: ni_daq_700
271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksDescription: National Instruments PCMCIA DAQCard-700 DIO only
281f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksAuthor: Fred Brooks <nsaspook@nsaspook.com>,
291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks  based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
301f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksDevices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
311f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksStatus: works
321f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksUpdated: Thu, 21 Feb 2008 12:07:20 +0000
331f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksThe daqcard-700 appears in Comedi as a single digital I/O subdevice with
351f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks16 channels.  The channel 0 corresponds to the daqcard-700's output
361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksport, bit 0; channel 8 corresponds to the input port, bit 0.
371f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
381f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksDirection configuration: channels 0-7 output, 8-15 input (8225 device
391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksemu as port A output, port B input, port C N/A).
401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksIRQ is assigned but not used.
421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks*/
431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4425436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
455a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
461f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#include "../comedidev.h"
471f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
481f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#include <linux/ioport.h>
491f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
501f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#include <pcmcia/cistpl.h>
511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#include <pcmcia/cisreg.h>
521f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#include <pcmcia/ds.h>
531f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
54ee4d07d8e1c72043299ac4118fbdee0ad883e966Ravishankarstatic struct pcmcia_device *pcmcia_cur_dev;
551f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
562696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DIO700_SIZE 8		/*  size of io region used by board */
571f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dio700_attach(struct comedi_device *dev,
590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			 struct comedi_devconfig *it);
60da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dio700_detach(struct comedi_device *dev);
611f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
621f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksenum dio700_bustype { pcmcia_bustype };
631f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
644cab3740734fb8582fa68f899105790c05935b55Bill Pembertonstruct dio700_board {
651f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	const char *name;
662696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	int device_id;		/*  device id for pcmcia board */
672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	enum dio700_bustype bustype;	/*  PCMCIA */
682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	int have_dio;		/*  have daqcard-700 dio */
692696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  function pointers so we can use inb/outb or readb/writeb */
702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  as appropriate */
711f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned int (*read_byte) (unsigned int address);
721f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	void (*write_byte) (unsigned int byte, unsigned int address);
734cab3740734fb8582fa68f899105790c05935b55Bill Pemberton};
741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
754cab3740734fb8582fa68f899105790c05935b55Bill Pembertonstatic const struct dio700_board dio700_boards[] = {
761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	{
770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "daqcard-700",
789a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	  /*  0x10b is manufacturer id, 0x4743 is device id */
799a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	 .device_id = 0x4743,
800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .bustype = pcmcia_bustype,
810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .have_dio = 1,
820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
831f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	{
840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "ni_daq_700",
859a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	  /*  0x10b is manufacturer id, 0x4743 is device id */
869a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	 .device_id = 0x4743,
870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .bustype = pcmcia_bustype,
880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .have_dio = 1,
890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
911f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
921f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks/*
931f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks * Useful for shorthand access to the particular board structure
941f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks */
954cab3740734fb8582fa68f899105790c05935b55Bill Pemberton#define thisboard ((const struct dio700_board *)dev->board_ptr)
961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
97adf328432473a9baf2b7b0a50864d9736890fa8aBill Pembertonstruct dio700_private {
98adf328432473a9baf2b7b0a50864d9736890fa8aBill Pemberton
991f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int data;		/* number of data points left to be taken */
100adf328432473a9baf2b7b0a50864d9736890fa8aBill Pemberton};
101adf328432473a9baf2b7b0a50864d9736890fa8aBill Pemberton
102adf328432473a9baf2b7b0a50864d9736890fa8aBill Pemberton#define devpriv ((struct dio700_private *)dev->private)
1031f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
104139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_dio700 = {
10568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "ni_daq_700",
10668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
10768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = dio700_attach,
10868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = dio700_detach,
1098629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton	.num_names = ARRAY_SIZE(dio700_boards),
11068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &dio700_boards[0].name,
11168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct dio700_board),
1121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
1131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1141f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks/*	the real driver routines	*/
1151f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1161f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define _700_SIZE 8
1171f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1181f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define _700_DATA 0
1191f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define DIO_W		0x04
1211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define DIO_R		0x05
1221f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1231f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstruct subdev_700_struct {
1241f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned long cb_arg;
1251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int (*cb_func) (int, int, int, unsigned long);
1261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int have_irq;
1271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
1281f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define CALLBACK_ARG	(((struct subdev_700_struct *)s->private)->cb_arg)
1301f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define CALLBACK_FUNC	(((struct subdev_700_struct *)s->private)->cb_func)
1311f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#define subdevpriv	((struct subdev_700_struct *)s->private)
1321f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
133da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
1341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
135da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonvoid subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
1361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
137790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short d;
1381f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
1401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	comedi_buf_put(s->async, d);
1421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->async->events |= COMEDI_CB_EOS;
1431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1441f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	comedi_event(dev, s);
1451f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
146ee21350fae9333acc11e3b1b77c887fd94e450f5Robert BabilonEXPORT_SYMBOL(subdev_700_interrupt);
1471f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1481f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int subdev_700_cb(int dir, int port, int data, unsigned long arg)
1491f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
1501f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* port is always A for output and B for input (8255 emu) */
1511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned long iobase = arg;
1521f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1531f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (dir) {
1541f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		outb(data, iobase + DIO_W);
1551f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return 0;
1561f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	} else {
1571f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return inb(iobase + DIO_R);
1581f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
1591f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
1601f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_700_insn(struct comedi_device *dev,
1620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
1630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
1641f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
1651f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (data[0]) {
1661f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		s->state &= ~data[0];
1671f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		s->state |= (data[0] & data[1]);
1681f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1691f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		if (data[0] & 0xff)
1701f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks			CALLBACK_FUNC(1, _700_DATA, s->state & 0xff,
1710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      CALLBACK_ARG);
1721f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
1731f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	data[1] = s->state & 0xff;
1751f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8;
1761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1771f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 2;
1781f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
1791f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_700_insn_config(struct comedi_device *dev,
1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_subdevice *s,
1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_insn *insn, unsigned int *data)
1831f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
1841f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
1851f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	switch (data[0]) {
1861f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	case INSN_CONFIG_DIO_INPUT:
1871f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		break;
1881f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	case INSN_CONFIG_DIO_OUTPUT:
1891f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		break;
1901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	case INSN_CONFIG_DIO_QUERY:
1911f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		data[1] =
1920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->
1930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    COMEDI_INPUT;
1951f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return insn->n;
1961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		break;
1971f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	default:
1981f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -EINVAL;
1991f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2001f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2011f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 1;
2021f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
2031f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
204da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
2051f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{				/* use powerup defaults */
2061f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return;
2071f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
2081f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_700_cmdtest(struct comedi_device *dev,
2100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
2110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
2121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
2131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int err = 0;
2141f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned int tmp;
2151f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2161f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* step 1 */
2171f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2181f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	tmp = cmd->start_src;
2191f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	cmd->start_src &= TRIG_NOW;
2201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!cmd->start_src || tmp != cmd->start_src)
2211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2221f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2231f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	tmp = cmd->scan_begin_src;
2241f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	cmd->scan_begin_src &= TRIG_EXT;
2251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
2261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2281f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	tmp = cmd->convert_src;
2291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	cmd->convert_src &= TRIG_FOLLOW;
2301f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!cmd->convert_src || tmp != cmd->convert_src)
2311f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2321f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2331f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	tmp = cmd->scan_end_src;
2341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	cmd->scan_end_src &= TRIG_COUNT;
2351f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
2361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2371f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2381f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	tmp = cmd->stop_src;
2391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	cmd->stop_src &= TRIG_NONE;
2401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!cmd->stop_src || tmp != cmd->stop_src)
2411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (err)
2441f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return 1;
2451f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2461f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* step 2 */
2471f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2481f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (err)
2491f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return 2;
2501f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* step 3 */
2521f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2531f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (cmd->start_arg != 0) {
2541f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		cmd->start_arg = 0;
2551f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2561f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2571f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (cmd->scan_begin_arg != 0) {
2581f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		cmd->scan_begin_arg = 0;
2591f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2601f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2611f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (cmd->convert_arg != 0) {
2621f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		cmd->convert_arg = 0;
2631f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2641f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2651f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (cmd->scan_end_arg != 1) {
2661f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		cmd->scan_end_arg = 1;
2671f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2681f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2691f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (cmd->stop_arg != 0) {
2701f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		cmd->stop_arg = 0;
2711f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		err++;
2721f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
2731f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (err)
2751f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return 3;
2761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2771f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* step 4 */
2781f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2791f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (err)
2801f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return 4;
2811f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2821f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
2831f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
2841f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
285da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2861f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
2871f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* FIXME */
2881f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2891f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
2901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
2911f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_700_cancel(struct comedi_device *dev,
2930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
2941f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
2951f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* FIXME */
2961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
2971f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
2981f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
2991f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralint subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    int (*cb) (int, int, int, unsigned long), unsigned long arg)
3021f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
3031f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->type = COMEDI_SUBD_DIO;
3041f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
3051f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->n_chan = 16;
3061f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->range_table = &range_digital;
3071f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->maxdata = 1;
3081f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3091f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL);
3101f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!s->private)
3111f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -ENOMEM;
3121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	CALLBACK_ARG = arg;
3149a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	if (cb == NULL)
3151f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		CALLBACK_FUNC = subdev_700_cb;
3169a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	 else
3171f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		CALLBACK_FUNC = cb;
3189a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe
3191f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->insn_bits = subdev_700_insn;
3201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->insn_config = subdev_700_insn_config;
3211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3221f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->state = 0;
3231f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->io_bits = 0x00ff;
3241f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	do_config(dev, s);
3251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
3271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
328ee21350fae9333acc11e3b1b77c887fd94e450f5Robert BabilonEXPORT_SYMBOL(subdev_700_init);
3291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
330da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonint subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			int (*cb) (int, int, int, unsigned long),
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			unsigned long arg)
3331f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
3341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int ret;
3351f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	ret = subdev_700_init(dev, s, cb, arg);
3371f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (ret < 0)
3381f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return ret;
3391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->do_cmdtest = subdev_700_cmdtest;
3411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->do_cmd = subdev_700_cmd;
3421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s->cancel = subdev_700_cancel;
3431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3441f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	subdevpriv->have_irq = 1;
3451f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3461f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
3471f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
348ee21350fae9333acc11e3b1b77c887fd94e450f5Robert BabilonEXPORT_SYMBOL(subdev_700_init_irq);
3491f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
350da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonvoid subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
3511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
3529a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	if (s->private)
3539a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe		if (subdevpriv->have_irq)
3541f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3559a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe			kfree(s->private);
3561f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
3571f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksEXPORT_SYMBOL(subdev_700_cleanup);
3581f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
359da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
3601f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
36134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
3621f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned long iobase = 0;
3631f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#ifdef incomplete
3641f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	unsigned int irq = 0;
3651f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#endif
3661f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	struct pcmcia_device *link;
3671f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3681f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* allocate and initialize dev->private */
369adf328432473a9baf2b7b0a50864d9736890fa8aBill Pemberton	if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
3701f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -ENOMEM;
3711f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3722696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  get base address, irq etc. based on bustype */
3731f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	switch (thisboard->bustype) {
3741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	case pcmcia_bustype:
3751f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		link = pcmcia_cur_dev;	/* XXX hack */
3761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		if (!link)
3771f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks			return -EIO;
3789a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski		iobase = link->resource[0]->start;
3791f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#ifdef incomplete
380eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski		irq = link->irq;
3811f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#endif
3821f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		break;
3831f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	default:
384ee4d07d8e1c72043299ac4118fbdee0ad883e966Ravishankar		printk(KERN_ERR "bug! couldn't determine board type\n");
3851f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -EINVAL;
3861f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		break;
3871f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
388ee4d07d8e1c72043299ac4118fbdee0ad883e966Ravishankar	printk(KERN_ERR "comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       thisboard->name, iobase);
3901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#ifdef incomplete
3919a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe	if (irq)
3921f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		printk(", irq %u", irq);
3939a16a92c11e82a0a80b4847343cfb8b5c54ed6b6Graham M Howe
3941f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#endif
3951f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	printk("\n");
3971f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
3981f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (iobase == 0) {
399ee4d07d8e1c72043299ac4118fbdee0ad883e966Ravishankar		printk(KERN_ERR "io base address is zero!\n");
4001f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -EINVAL;
4011f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
4021f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4031f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	dev->iobase = iobase;
4041f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4051f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#ifdef incomplete
4061f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* grab our IRQ */
4071f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	dev->irq = irq;
4081f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks#endif
4091f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4101f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	dev->board_name = thisboard->name;
4111f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (alloc_subdevices(dev, 1) < 0)
4131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -ENOMEM;
4141f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4151f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* DAQCard-700 dio */
4161f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	s = dev->subdevices + 0;
4171f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	subdev_700_init(dev, s, NULL, dev->iobase);
4181f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4191f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
4201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
4211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
422da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dio700_detach(struct comedi_device *dev)
4231f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
424ee4d07d8e1c72043299ac4118fbdee0ad883e966Ravishankar	printk(KERN_ERR "comedi%d: ni_daq_700: cs-remove\n", dev->minor);
4251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (dev->subdevices)
4271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		subdev_700_cleanup(dev, dev->subdevices + 0);
4281f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (thisboard->bustype != pcmcia_bustype && dev->iobase)
4301f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		release_region(dev->iobase, DIO700_SIZE);
4311f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (dev->irq)
4325f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
4331f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
4351f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
4361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4371f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void dio700_config(struct pcmcia_device *link);
4381f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void dio700_release(struct pcmcia_device *link);
4391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_suspend(struct pcmcia_device *p_dev);
4401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_resume(struct pcmcia_device *p_dev);
4411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_attach(struct pcmcia_device *);
4431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void dio700_cs_detach(struct pcmcia_device *);
4441f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
44530570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pembertonstruct local_info_t {
4461f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	struct pcmcia_device *link;
4471f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int stop;
4481f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	struct bus_operations *bus;
44930570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton};
4501f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_attach(struct pcmcia_device *link)
4521f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
45330570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton	struct local_info_t *local;
4541f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4551f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	printk(KERN_INFO "ni_daq_700:  cs-attach\n");
4561f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
45755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "dio700_cs_attach()\n");
4581f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4591f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* Allocate space for private device-specific data */
46030570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
4611f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (!local)
4621f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return -ENOMEM;
4631f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	local->link = link;
4641f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	link->priv = local;
4651f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4661f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	pcmcia_cur_dev = link;
4671f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4681f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	dio700_config(link);
4691f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4701f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
4711f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_cs_attach */
4721f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4731f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void dio700_cs_detach(struct pcmcia_device *link)
4741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
4751f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	printk(KERN_INFO "ni_daq_700: cs-detach!\n");
4771f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
47855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "dio700_cs_detach\n");
4791f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
480cdc268b4a029d489798db10d10fea72b7a415ab9Javier Martinez Canillas	((struct local_info_t *)link->priv)->stop = 1;
481cdc268b4a029d489798db10d10fea72b7a415ab9Javier Martinez Canillas	dio700_release(link);
4821f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
48330570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton	/* This points to the parent struct local_info_t struct */
484f25bd6bfdf9bccd8164c151b027f9c14ec07960bDan Carpenter	kfree(link->priv);
4851f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
4861f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_cs_detach */
4871f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
48855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
48955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski				void *priv_data)
4901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
49100990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	if (p_dev->config_index == 0)
49200990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski		return -EINVAL;
493c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
49400990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	return pcmcia_request_io(p_dev);
49555a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski}
4961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
49755a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskistatic void dio700_config(struct pcmcia_device *link)
49855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski{
49955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	int ret;
5001f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
50155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	printk(KERN_INFO "ni_daq_700:  cs-config\n");
5021f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
50355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "dio700_config\n");
504c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
50500990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
50600990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski		CONF_AUTO_SET_IO;
507440eed43e2a95bb842488755683716814da10f2bDominik Brodowski
5080f52e86ded65749c6037473013ad77b2afa4f68dDominik Brodowski	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
50955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret) {
51055a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		dev_warn(&link->dev, "no configuration found\n");
51155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
5121f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	}
5131f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
514eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski	if (!link->irq)
515eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski		goto failed;
5161f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5171ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski	ret = pcmcia_enable_device(link);
51855a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	if (ret != 0)
51955a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski		goto failed;
5201f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5211f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return;
5221f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
52355a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowskifailed:
5241f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	printk(KERN_INFO "ni_daq_700 cs failed");
5251f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	dio700_release(link);
5261f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5271f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_config */
5281f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5291f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void dio700_release(struct pcmcia_device *link)
5301f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
53155a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	dev_dbg(&link->dev, "dio700_release\n");
5321f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5331f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	pcmcia_disable_device(link);
5341f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_release */
5351f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5361f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_suspend(struct pcmcia_device *link)
5371f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
53830570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton	struct local_info_t *local = link->priv;
5391f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5401f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* Mark the device as stopped, to block IO until later */
5411f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	local->stop = 1;
5421f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
5431f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_cs_suspend */
5441f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5451f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int dio700_cs_resume(struct pcmcia_device *link)
5461f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
54730570f0dee2b0e3ede09e08eb5dfd514317a7587Bill Pemberton	struct local_info_t *local = link->priv;
5481f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5491f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	local->stop = 0;
5501f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
5511f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}				/* dio700_cs_resume */
5521f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5531f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks/*====================================================================*/
5541f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5552202a5a7490a9de282846ea8d4a56d0249e09033Joe Perchesstatic const struct pcmcia_device_id dio700_cs_ids[] = {
5561f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	/* N.B. These IDs should match those in dio700_boards */
5571f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),	/* daqcard-700 */
5581f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	PCMCIA_DEVICE_NULL
5591f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
5601f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5616c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander Kurz
5621f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred BrooksMODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
5636c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
5646c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_DESCRIPTION("Comedi driver for National Instruments "
5656c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander Kurz		   "PCMCIA DAQCard-700 DIO");
5666c7f81967b8984e6fb6b1f04c63f32d90a15c479Alexander KurzMODULE_LICENSE("GPL");
5671f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5681f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstruct pcmcia_driver dio700_cs_driver = {
5691f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.probe = dio700_cs_attach,
5701f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.remove = dio700_cs_detach,
5711f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.suspend = dio700_cs_suspend,
5721f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.resume = dio700_cs_resume,
5731f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.id_table = dio700_cs_ids,
5741f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	.owner = THIS_MODULE,
5752e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski	.name = "ni_daq_700",
5761f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks};
5771f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5781f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic int __init init_dio700_cs(void)
5791f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
5801f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	pcmcia_register_driver(&dio700_cs_driver);
5811f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return 0;
5821f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
5831f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5841f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksstatic void __exit exit_dio700_cs(void)
5851f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
58655a19b39acb8888af8e9cfe5b762d03c52fdb48cDominik Brodowski	pr_debug("ni_daq_700: unloading\n");
5871f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	pcmcia_unregister_driver(&dio700_cs_driver);
5881f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
5890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
5901f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksint __init init_module(void)
5911f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
5921f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	int ret;
5931f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5941f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	ret = init_dio700_cs();
5951f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	if (ret < 0)
5961f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks		return ret;
5971f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
5981f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	return comedi_driver_register(&driver_dio700);
5991f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
6001f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks
6011f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooksvoid __exit cleanup_module(void)
6021f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks{
6031f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	exit_dio700_cs();
6041f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks	comedi_driver_unregister(&driver_dio700);
6051f9bbbe2ad29901057e9bc97e29415052aaa8aaaFred Brooks}
606