1e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/*
2e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    comedi/drivers/ni_pcidio.c
3e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    driver for National Instruments PCI-DIO-96/PCI-6508
42d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		National Instruments PCI-DIO-32HS
52d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		National Instruments PCI-6503
6e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    COMEDI - Linux Control and Measurement Device Interface
8e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
9e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    This program is free software; you can redistribute it and/or modify
11e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    it under the terms of the GNU General Public License as published by
12e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    the Free Software Foundation; either version 2 of the License, or
13e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    (at your option) any later version.
14e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
15e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    This program is distributed in the hope that it will be useful,
16e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    but WITHOUT ANY WARRANTY; without even the implied warranty of
17e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    GNU General Public License for more details.
19e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
20e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    You should have received a copy of the GNU General Public License
21e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    along with this program; if not, write to the Free Software
22e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
24e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef*/
25e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/*
26e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefDriver: ni_pcidio
27e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefDescription: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503
28e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefAuthor: ds
29e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefStatus: works
30e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefDevices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533,
31e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef  PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,
32e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef  PXI-6503, PCI-6533, PCI-6534
3322494ed9b8e9404d6646f85c835bcd7b37d3f562Ian AbbottUpdated: Mon, 09 Jan 2012 14:27:23 +0000
34e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
35e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThe DIO-96 appears as four 8255 subdevices.  See the 8255
36e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefdriver notes for details.
37e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
38e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThe DIO32HS board appears as one subdevice, with 32 channels.
39e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefEach channel is individually I/O configurable.  The channel order
40e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefis 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0.  The driver only
41e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefsupports simple digital I/O; no handshaking is supported.
42e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
43e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefDMA mostly works for the PCI-DIO32HS, but only in timed input mode.
44e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4522494ed9b8e9404d6646f85c835bcd7b37d3f562Ian AbbottThe PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting
4622494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbottscan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting
4722494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbottscan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the
4822494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbotttrailing edge.
4922494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott
50e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThis driver could be easily modified to support AT-MIO32HS and
51e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefAT-MIO96.
52e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
53e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThe PCI-6534 requires a firmware upload after power-up to work, the
54e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleeffirmware data and instructions for loading it with comedi_config
55e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefit are contained in the
56e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefcomedi_nonfree_firmware tarball available from http://www.comedi.org
57e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef*/
58e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
59e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/*
60e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96,
61e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   which have very different architectures.  But, since the '96 is
62e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   so simple, it is included here.
63e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
64e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   Manuals (available from ftp://ftp.natinst.com/support/manuals)
65e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
66e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	320938c.pdf	PCI-DIO-96/PXI-6508/PCI-6503 User Manual
67e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	321464b.pdf	AT/PCI-DIO-32HS User Manual
68e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	341329A.pdf	PCI-6533 Register-Level Programmer Manual
69e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	341330A.pdf	DAQ-DIO Technical Reference Manual
70e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
71e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef */
72e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
73e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define USE_DMA
7456e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* #define DEBUG 1 */
7556e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* #define DEBUG_FLAGS */
76e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7725436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
784377a026500a3f59e9c41c23d03e55ff2e712379Greg Kroah-Hartman#include <linux/sched.h>
79e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "../comedidev.h"
80e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
81e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "mite.h"
82e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "8255.h"
83e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
84e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#undef DPRINTK
85e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG
86e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DPRINTK(format, args...)	printk(format, ## args)
87e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
88e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DPRINTK(format, args...)
89e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
90e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
91e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PCI_DIO_SIZE 4096
92e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PCI_MITE_SIZE 4096
93e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
94e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* defines for the PCI-DIO-96 */
95e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
96e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_8255_BASE(x)	((x)*4)
97e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_A 0
98e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_B 4
99e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_C 8
100e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_D 12
101e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
102e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* defines for the PCI-DIO-32HS */
103e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
104e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Window_Address			4	/* W */
105e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Interrupt_And_Window_Status	4	/* R */
106e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntStatus1				(1<<0)
107e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntStatus2				(1<<1)
108e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define WindowAddressStatus_mask		0x7c
109e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
110e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Master_DMA_And_Interrupt_Control 5	/* W */
111e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InterruptLine(x)			((x)&3)
112e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenInt				(1<<2)
113e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_Status			5	/* R */
114e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DataLeft				(1<<0)
115e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Req					(1<<2)
116e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StopTrig				(1<<3)
117e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
118e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_Flags			6	/* R */
119e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_Flags			7	/* R */
120e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferReady				(1<<0)
121e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define CountExpired				(1<<1)
122e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Waited				(1<<5)
123e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PrimaryTC				(1<<6)
124e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define SecondaryTC				(1<<7)
12556e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define SerialRose */
12656e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define ReqRose */
12756e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define Paused */
128e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
129e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_First_Clear		6	/* W */
130e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_First_Clear		7	/* W */
131e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearWaited				(1<<3)
132e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearPrimaryTC			(1<<4)
133e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearSecondaryTC			(1<<5)
134e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMAReset				(1<<6)
135e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOReset				(1<<7)
136e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearAll				0xf8
137e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
138e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_FIFO			8	/* W */
139e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_FIFO			12	/* W */
140e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
141e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Transfer_Count			20
142e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_D			24
143e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_I			25
144e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_O			26
145e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_Version			27
146e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_IO(x)			(28+(x))
147e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Directions(x)		(32+(x))
148e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Mask(x)		(36+(x))
149e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Polarities(x)		(40+(x))
150e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
151e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Master_Clock_Routing		45
152e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RTSIClocking(x)			(((x)&3)<<4)
153e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
154e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_Second_Clear		46	/* W */
155e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_Second_Clear		47	/* W */
156e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearExpired				(1<<0)
157e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
158e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pattern(x)			(48+(x))
159e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
160e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Data_Path			64
161e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableA		(1<<0)
162e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableB		(1<<1)
163e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableC		(1<<2)
164e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableD		(1<<3)
165e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Funneling(x)		(((x)&3)<<4)
166e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define GroupDirection	(1<<7)
167e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
168e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_1		65
169e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpMode				Protocol_Register_1
170e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RunMode(x)		((x)&7)
171e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Numbered		(1<<3)
172e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
173e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_2		66
174e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockReg			Protocol_Register_2
175e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockLine(x)		(((x)&3)<<5)
176e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertStopTrig	(1<<7)
177e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DataLatching(x)       (((x)&3)<<5)
178e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
179e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_3		67
180e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Sequence			Protocol_Register_3
181e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
182e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_14		68	/* 16 bit */
183e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockSpeed			Protocol_Register_14
184e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
185e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_4		70
186e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqReg				Protocol_Register_4
187e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqConditioning(x)	(((x)&7)<<3)
188e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
189e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_5		71
190e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define BlockMode			Protocol_Register_5
191e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
192e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFO_Control			72
193e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReadyLevel(x)		((x)&7)
194e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
195e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_6		73
196e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define LinePolarities			Protocol_Register_6
197e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertAck		(1<<0)
198e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertReq		(1<<1)
199e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertClock		(1<<2)
200e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertSerial		(1<<3)
201e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenAck		(1<<4)
202e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenClock		(1<<5)
203e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
204e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_7		74
205e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckSer				Protocol_Register_7
206e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckLine(x)		(((x)&3)<<2)
207e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ExchangePins		(1<<7)
208e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
209e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Interrupt_Control		75
210e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef  /* bits same as flags */
211e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
212e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMA_Line_Control_Group1		76
213e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMA_Line_Control_Group2		108
21456e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* channel zero is none */
215e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic inline unsigned primary_DMAChannel_bits(unsigned channel)
216e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
217e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return channel & 0x3;
218e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
2190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
220e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic inline unsigned secondary_DMAChannel_bits(unsigned channel)
221e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
222e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return (channel << 2) & 0xc;
223e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
224e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
225e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Transfer_Size_Control		77
226e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferWidth(x)	((x)&3)
227e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferLength(x)	(((x)&3)<<3)
228e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RequireRLevel		(1<<5)
229e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
230e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_15		79
231e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DAQOptions			Protocol_Register_15
232e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StartSource(x)			((x)&0x3)
233e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertStart				(1<<2)
234e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StopSource(x)				(((x)&0x3)<<3)
235e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqStart				(1<<6)
236e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PreStart				(1<<7)
237e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
238e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Pattern_Detection		81
239e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DetectionMethod			(1<<0)
240e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertMatch				(1<<1)
241e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IE_Pattern_Detection			(1<<2)
242e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
243e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_9		82
244e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqDelay			Protocol_Register_9
245e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
246e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_10		83
247e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqNotDelay			Protocol_Register_10
248e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
249e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_11		84
250e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckDelay			Protocol_Register_11
251e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
252e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_12		85
253e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckNotDelay			Protocol_Register_12
254e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
255e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_13		86
256e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Data1Delay			Protocol_Register_13
257e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
258e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_8		88	/* 32 bit */
259e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StartDelay			Protocol_Register_8
260e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
261e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum pci_6534_firmware_registers {	/* 16 bit */
262e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Control_Register = 0x100,
263e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Status_Register = 0x104,
264e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Data_Register = 0x108,
265e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Mask_Register = 0x10c,
266e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Debug_Register = 0x110,
267e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
268e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* main fpga registers (32 bit)*/
269e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum pci_6534_fpga_registers {
270e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Control1_Register = 0x200,
271e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Control2_Register = 0x204,
272e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Irq_Mask_Register = 0x208,
273e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Status_Register = 0x20c,
274e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Signature_Register = 0x210,
275e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCALS_Counter_Register = 0x280,	/*write-clear */
276e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCAMS_Counter_Register = 0x284,	/*write-clear */
277e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCBLS_Counter_Register = 0x288,	/*write-clear */
278e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCBMS_Counter_Register = 0x28c,	/*write-clear */
279e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Temp_Control_Register = 0x2a0,
280e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_DAR_Register = 0x2a8,
281e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_ELC_Read_Register = 0x2b8,
282e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_ELC_Write_Register = 0x2bc,
283e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
284e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum FPGA_Control_Bits {
285e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Enable_Bit = 0x8000,
286e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
287e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
288e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TIMER_BASE 50		/* nanoseconds */
289e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
290e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef USE_DMA
291e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC)
292e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
293e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
294e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
295e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
296da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
297da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_detach(struct comedi_device *dev);
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cancel(struct comedi_device *dev,
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
300e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
301139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_pcidio = {
30268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "ni_pcidio",
30368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
30468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = nidio_attach,
30568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = nidio_detach,
306e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
307e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
308a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pembertonstruct nidio_board {
309a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton
310e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int dev_id;
311e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	const char *name;
312e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int n_8255;
313e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int is_diodaq:1;
314e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int uses_firmware:1;
315a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton};
316a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton
317a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pembertonstatic const struct nidio_board nidio_boards[] = {
318e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1150,
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-32hs",
3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
324e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1320,
3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6533",
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
330e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x12b0,
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6534",
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .uses_firmware = 1,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
337e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x0160,
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-96",
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
343e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1630,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-96b",
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
349e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x13c0,
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6508",
3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
355e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x0400,
3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503",
3580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
361e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1250,
3630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503b",
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
367e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x17d0,
3690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503x",
3700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
373e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1800,
3750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6503",
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
379e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
380e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
381b6ac161364eccce1bea4a23a9de395883e90d7abStoyan Gaydarov#define n_nidio_boards ARRAY_SIZE(nidio_boards)
382a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton#define this_board ((const struct nidio_board *)dev->board_ptr)
383e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
384e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
3854e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150)},
3864e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320)},
3874e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0)},
3884e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160)},
3894e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630)},
3904e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0)},
3914e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400)},
3924e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250)},
3934e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0)},
3944e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800)},
3954e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{0}
396e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
397e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
398e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefMODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
399e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4002e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pembertonstruct nidio96_private {
401e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite;
402e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int boardtype;
403e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int dio;
404e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned short OpModeBits;
405e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_channel *di_mite_chan;
406e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_dma_descriptor_ring *di_mite_ring;
407e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	spinlock_t mite_channel_lock;
4082e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pemberton};
4092e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pemberton#define devpriv ((struct nidio96_private *)dev->private)
410e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmdtest(struct comedi_device *dev,
4120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
4130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_cmd *cmd);
414da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
4150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_inttrig(struct comedi_device *dev,
4160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, unsigned int trignum);
417da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_find_device(struct comedi_device *dev, int bus, int slot);
418e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
4190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int setup_mite_dma(struct comedi_device *dev,
4200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
421e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
422e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG_FLAGS
423e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_flags(unsigned int flags);
424e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_status(unsigned int status);
425e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
426e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ni_pcidio_print_flags(x)
427e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ni_pcidio_print_status(x)
428e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
429e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
430da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
431e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
432e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned long flags;
433e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4345f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
435e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	BUG_ON(devpriv->di_mite_chan);
436e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	devpriv->di_mite_chan =
4370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    mite_request_channel_in_range(devpriv->mite,
4380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  devpriv->di_mite_ring, 1, 2);
439e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan == NULL) {
4405f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
441e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		comedi_error(dev, "failed to reserve mite dma channel.");
442e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EBUSY;
443e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
444e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	devpriv->di_mite_chan->dir = COMEDI_INPUT;
445e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
4470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
448e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mmiowb();
4495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
450e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
451e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
452e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
453da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
454e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
455e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned long flags;
456e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4575f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
458e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan) {
459e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_dma_disarm(devpriv->di_mite_chan);
460e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_dma_reset(devpriv->di_mite_chan);
461e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_release_channel(devpriv->di_mite_chan);
462e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->di_mite_chan = NULL;
463e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(primary_DMAChannel_bits(0) |
4640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       secondary_DMAChannel_bits(0),
4650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
466e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mmiowb();
467e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
4685f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
469e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
470e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
471e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
472e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
473e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dir) {
474e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(data, (void *)(iobase + port));
475e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 0;
476e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
477e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return readb((void *)(iobase + port));
478e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
479e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
480e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
481da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonvoid ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
482e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	if (s->
4840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     COMEDI_CB_OVERFLOW)) {
486e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ni_pcidio_cancel(dev, s);
487e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
488e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	comedi_event(dev, s);
489e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
490e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
49102f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbottstatic int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
49202f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott{
49302f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	unsigned long irq_flags;
49402f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	int count;
49502f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott
49602f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_lock_irqsave(&dev->spinlock, irq_flags);
49702f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_lock(&devpriv->mite_channel_lock);
49802f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	if (devpriv->di_mite_chan)
49902f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott		mite_sync_input_dma(devpriv->di_mite_chan, s->async);
50002f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_unlock(&devpriv->mite_channel_lock);
50102f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	count = s->async->buf_write_count - s->async->buf_read_count;
50202f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
50302f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	return count;
50402f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott}
50502f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott
50670265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t nidio_interrupt(int irq, void *d)
507e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
50871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
50934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices;
510d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
511e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite = devpriv->mite;
512e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
51356e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* int i, j; */
514e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	long int AuxData = 0;
515790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short data1 = 0;
516790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short data2 = 0;
517e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int flags;
518e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int status;
519e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int work = 0;
520e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int m_status = 0;
521e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
52256e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* interrupcions parasites */
523e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dev->attached == 0) {
52456e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* assume it's from another card */
525e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return IRQ_NONE;
526e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
527e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
52802f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	/* Lock to avoid race with comedi_poll */
52902f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_lock(&dev->spinlock);
53002f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott
531e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	status = readb(devpriv->mite->daq_io_addr +
5320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Interrupt_And_Window_Status);
533e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
534e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
535e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n",
536e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		status, flags);
537e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_print_flags(flags);
538e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_print_status(status);
539e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
54056e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
5412d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* printk("buf[4096]=%08x\n",
5422d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       *(unsigned int *)(async->prealloc_buf+4096)); */
543e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
54402f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_lock(&devpriv->mite_channel_lock);
545e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan)
546e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		m_status = mite_get_status(devpriv->di_mite_chan);
547e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef MITE_DEBUG
548e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_print_chsr(m_status);
549e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
5502d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* printk("mite_bytes_transferred: %d\n",
5512d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       mite_bytes_transferred(mite,DI_DMA_CHAN)); */
5522d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
55356e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* mite_dump_regs(mite); */
554e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (m_status & CHSR_INT) {
555e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (m_status & CHSR_LINKC) {
556e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writel(CHOR_CLRLC,
5570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       mite->mite_io_addr +
5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       MITE_CHOR(devpriv->di_mite_chan->channel));
559e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_sync_input_dma(devpriv->di_mite_chan, s->async);
560e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			/* XXX need to byteswap */
561e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
562e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY |
5630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 CHSR_DRQ1 | CHSR_MRDY)) {
564e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("unknown mite interrupt, disabling IRQ\n");
565e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
566e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			disable_irq(dev->irq);
567e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
568e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
56902f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_unlock(&devpriv->mite_channel_lock);
570e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
571e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	while (status & DataLeft) {
572e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		work++;
573e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (work > 20) {
574e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("too much work in interrupt\n");
575e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00,
5760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
5770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Master_DMA_And_Interrupt_Control);
578e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
579e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
580e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
581e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		flags &= IntEn;
582e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
583e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (flags & TransferReady) {
58456e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* DPRINTK("TransferReady\n"); */
585e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			while (flags & TransferReady) {
586e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				work++;
587e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				if (work > 100) {
588e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					DPRINTK("too much work in interrupt\n");
589e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					writeb(0x00,
5900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       devpriv->mite->daq_io_addr +
5912d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi					       Master_DMA_And_Interrupt_Control
5922d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi					      );
593e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					goto out;
594e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				}
595e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				AuxData =
5960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    readl(devpriv->mite->daq_io_addr +
5970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  Group_1_FIFO);
598e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				data1 = AuxData & 0xffff;
599e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				data2 = (AuxData & 0xffff0000) >> 16;
600e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				comedi_buf_put(async, data1);
601e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				comedi_buf_put(async, data2);
60256e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton				/* DPRINTK("read:%d, %d\n",data1,data2); */
603e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				flags = readb(devpriv->mite->daq_io_addr +
6040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					      Group_1_Flags);
605e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			}
6062d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			/* DPRINTK("buf_int_count: %d\n",
6072d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi				async->buf_int_count); */
6082d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",
6092d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi				IntEn,flags,status); */
61056e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* ni_pcidio_print_flags(flags); */
61156e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* ni_pcidio_print_status(status); */
612e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_BLOCK;
613e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
614e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
615e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (flags & CountExpired) {
616e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("CountExpired\n");
617e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearExpired,
6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_Second_Clear);
620e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
621e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
622e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00, devpriv->mite->daq_io_addr + OpMode);
623e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
624e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & Waited) {
625e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("Waited\n");
626e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearWaited,
6270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
629e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
630e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
631e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & PrimaryTC) {
632e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("PrimaryTC\n");
633e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearPrimaryTC,
6340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
636e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
637e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & SecondaryTC) {
638e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("SecondaryTC\n");
639e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearSecondaryTC,
6400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
642e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
643e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
644e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#if 0
645e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		else {
646e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk("ni_pcidio: unknown interrupt\n");
647e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
648e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00,
6490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Master_DMA_And_Interrupt_Control);
651e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
652e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
653e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
654e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		status = readb(devpriv->mite->daq_io_addr +
6550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Interrupt_And_Window_Status);
6562d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,"
6572d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			"status=0x%02x\n", IntEn, flags, status); */
65856e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* ni_pcidio_print_flags(flags); */
65956e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* ni_pcidio_print_status(status); */
660e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
661e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
6620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralout:
663e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_event(dev, s);
664e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#if 0
665e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!tag) {
666e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x03,
6670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr +
6680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Master_DMA_And_Interrupt_Control);
669e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
670e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
67102f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott
67202f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott	spin_unlock(&dev->spinlock);
673e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return IRQ_HANDLED;
674e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
675e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
676e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG_FLAGS
677e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic const char *const flags_strings[] = {
678e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"TransferReady", "CountExpired", "2", "3",
679e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"4", "Waited", "PrimaryTC", "SecondaryTC",
680e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
6810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
682e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_flags(unsigned int flags)
683e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
684e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
685e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
6862d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "group_1_flags:");
687e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 7; i >= 0; i--) {
6882d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (flags & (1 << i))
689e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk(" %s", flags_strings[i]);
690e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
691e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
692e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
6930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
694e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic char *status_strings[] = {
695e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"DataLeft1", "Reserved1", "Req1", "StopTrig1",
696e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"DataLeft2", "Reserved2", "Req2", "StopTrig2",
697e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
6980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
699e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_status(unsigned int flags)
700e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
701e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
702e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7032d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "group_status:");
704e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 7; i >= 0; i--) {
7052d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (flags & (1 << i))
706e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk(" %s", status_strings[i]);
707e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
708e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
709e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
710e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
711e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
712e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef unused
7130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void debug_int(struct comedi_device *dev)
714e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
715e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int a, b;
71613a9e03c0c209b59f07b72c5388845a5f55eda2aBojan Prtvar	static int n_int;
717e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct timeval tv;
718e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
719e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	do_gettimeofday(&tv);
720e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	a = readb(devpriv->mite->daq_io_addr + Group_Status);
721e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
722e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
723e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (n_int < 10) {
724e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		DPRINTK("status 0x%02x flags 0x%02x time %06d\n", a, b,
725e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			(int)tv.tv_usec);
726e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
727e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
728e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	while (b & 1) {
729e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0xff, devpriv->mite->daq_io_addr + Group_1_FIFO);
730e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
731e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
732e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
733e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
734e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
735e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (n_int < 10) {
736e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		DPRINTK("new status 0x%02x\n", b);
737e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_int++;
738e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
739e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
740e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
741e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_insn_config(struct comedi_device *dev,
7430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
7440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data)
745e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
746e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (insn->n != 1)
747e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
748e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	switch (data[0]) {
749e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
750e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->io_bits |= 1 << CR_CHAN(insn->chanspec);
751e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
752e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_INPUT:
753e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
754e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
755e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_QUERY:
756e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		data[1] =
7570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->
7580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
7590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    COMEDI_INPUT;
760e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return insn->n;
761e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
762e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	default:
763e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
764e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
765e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
766e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
767e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 1;
768e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
769e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_insn_bits(struct comedi_device *dev,
7710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
7720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_insn *insn, unsigned int *data)
773e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
774e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (insn->n != 2)
775e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
776e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (data[0]) {
777e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->state &= ~data[0];
778e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->state |= (data[0] & data[1]);
779e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
780e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
781e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
782e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
783e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 2;
784e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
785e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmdtest(struct comedi_device *dev,
7870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
788e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
789e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int err = 0;
790e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int tmp;
791e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
792e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
793e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
794e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->start_src;
795e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->start_src &= TRIG_NOW | TRIG_INT;
796e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
797e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
798e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
799e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->scan_begin_src;
800e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
801e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
802e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
803e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
804e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->convert_src;
805e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->convert_src &= TRIG_NOW;
806e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
807e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
808e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
809e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->scan_end_src;
810e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
811e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
812e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
813e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
814e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->stop_src;
815e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
816e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
817e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
818e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
819e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
820e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 1;
821e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
8222d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* step 2: make sure trigger sources are unique and mutually
8232d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	compatible */
824e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
825828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
826e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
827e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
828e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
8290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
830e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
831e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
832e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
833e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 2;
834e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
835e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 3: make sure arguments are trivially compatible */
836e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
837e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_arg != 0) {
838e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* same for both TRIG_INT and TRIG_NOW */
839e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->start_arg = 0;
840e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
841e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
842e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define MAX_SPEED	(TIMER_BASE)	/* in nanoseconds */
843e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
844e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
845e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
846e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
847e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
848e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
84925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* no minimum speed */
850e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
851e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_EXT */
852e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* should be level/edge, hi/lo specification here */
85322494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott		if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) {
85422494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott			cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
855e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
856e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
857e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
858e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->convert_arg != 0) {
859e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->convert_arg = 0;
860e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
861e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
862e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
863e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
864e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
865e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
866e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
867e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
868e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* no limit */
869e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
870e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_NONE */
871e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (cmd->stop_arg != 0) {
872e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			cmd->stop_arg = 0;
873e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
874e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
875e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
876e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
877e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
878e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 3;
879e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
880e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 4: fix up any arguments */
881e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
882e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
883e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		tmp = cmd->scan_begin_arg;
884e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
8850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      cmd->flags & TRIG_ROUND_MASK);
886e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (tmp != cmd->scan_begin_arg)
887e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
888e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
889e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
890e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
891e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 4;
892e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
893e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
894e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
895e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
896e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
897e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
898e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int divider, base;
899e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
900e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	base = TIMER_BASE;
901e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
902e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	switch (round_mode) {
903e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_NEAREST:
904e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	default:
905e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec + base / 2) / base;
906e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
907e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_DOWN:
908e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec) / base;
909e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
910e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_UP:
911e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec + base - 1) / base;
912e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
913e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
914e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
915e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	*nanosec = base * divider;
916e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return divider;
917e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
918e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
9190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
920e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
921ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
922e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
923e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* XXX configure ports for input */
924e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
925e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
926e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (1) {
927e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* enable fifos A B C D */
928e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path);
929e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
930e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* set transfer width a 32 bits */
931e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(TransferWidth(0) | TransferLength(0),
9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
933e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
934e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x03, devpriv->mite->daq_io_addr + Data_Path);
935e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(TransferWidth(3) | TransferLength(0),
9360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
937e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
938e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
939e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* protocol configuration */
940e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
941e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* page 4-5, "input with internal REQs" */
942e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + OpMode);
943e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
944e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + Sequence);
945e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x04, devpriv->mite->daq_io_addr + ReqReg);
946e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
947e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(3, devpriv->mite->daq_io_addr + LinePolarities);
948e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0xc0, devpriv->mite->daq_io_addr + AckSer);
949e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
9500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     TRIG_ROUND_NEAREST),
9510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + StartDelay);
952e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
953e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
954e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
955e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay);
956e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay);
957e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* manual, page 4-5: ClockSpeed comment is incorrectly listed
958e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		 * on DAQOptions */
959e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
960e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + DAQOptions);
961e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
962e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_EXT */
963e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* page 4-5, "input with external REQs" */
964e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + OpMode);
965e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
966e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + Sequence);
967e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ReqReg);
968e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
96922494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott		if (!(cmd->scan_begin_arg & CR_INVERT)) {
97022494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott			/* Leading Edge pulse mode */
97122494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott			writeb(0, devpriv->mite->daq_io_addr + LinePolarities);
97222494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott		} else {
97322494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott			/* Trailing Edge pulse mode */
97422494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott			writeb(2, devpriv->mite->daq_io_addr + LinePolarities);
97522494ed9b8e9404d6646f85c835bcd7b37d3f562Ian Abbott		}
976e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + AckSer);
977e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(1, devpriv->mite->daq_io_addr + StartDelay);
978e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
979e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
980e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
981e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay);
982e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay);
983e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
984e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions);
985e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
986e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
987e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
988e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(cmd->stop_arg,
9890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Count);
990e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
991e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* XXX */
992e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
993e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
994e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef USE_DMA
995e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(ClearPrimaryTC | ClearSecondaryTC,
9960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Group_1_First_Clear);
997e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
998e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
999e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		int retval = setup_mite_dma(dev, s);
1000e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (retval)
1001e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return retval;
1002e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1003e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
1004e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
1005e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
1006e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2);
1007e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1008e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* clear and enable interrupts */
1009e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
10102d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* writeb(ClearExpired,
10112d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
1012e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1013e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
1014e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x03,
10150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
1016e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1017e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_NONE) {
1018e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->OpModeBits = DataLatching(0) | RunMode(7);
101956e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	} else {		/* TRIG_TIMER */
1020e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->OpModeBits = Numbered | RunMode(7);
1021e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1022e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_src == TRIG_NOW) {
1023e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* start */
1024e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(devpriv->OpModeBits,
10250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + OpMode);
1026e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async->inttrig = NULL;
1027e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
1028e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_INT */
1029e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async->inttrig = ni_pcidio_inttrig;
1030e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1031e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1032e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	DPRINTK("ni_pcidio: command started\n");
1033e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1034e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1035e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1037e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1038e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int retval;
1039e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	unsigned long flags;
1040e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1041e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	retval = ni_pcidio_request_di_mite_channel(dev);
1042e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (retval)
1043e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return retval;
1044e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
104541add2e84bff0c887949698e01dab28105f11a6bIan Abbott	/* write alloc the entire buffer */
104641add2e84bff0c887949698e01dab28105f11a6bIan Abbott	comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
104741add2e84bff0c887949698e01dab28105f11a6bIan Abbott
1048e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
1049e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	if (devpriv->di_mite_chan) {
1050e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott		mite_prep_dma(devpriv->di_mite_chan, 32, 32);
1051e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott		mite_dma_arm(devpriv->di_mite_chan);
1052e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	} else
1053e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott		retval = -EIO;
1054e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
1055e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1056e3794b52f56ac20947a2dbdd505e9ad29013c555Ian Abbott	return retval;
1057e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1058e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_inttrig(struct comedi_device *dev,
10600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, unsigned int trignum)
1061e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1062e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (trignum != 0)
1063e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
1064e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1065e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode);
1066e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	s->async->inttrig = NULL;
1067e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1068e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 1;
1069e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1070e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cancel(struct comedi_device *dev,
10720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
1073e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1074e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00,
10750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
1076e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_release_di_mite_channel(dev);
1077e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1078e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1079e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1080e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_change(struct comedi_device *dev,
10820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s, unsigned long new_size)
1083e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1084e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1085e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1086e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = mite_buf_change(devpriv->di_mite_ring, s->async);
1087e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1088e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1089e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1090e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
1091e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1092e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1093e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1094e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
10962d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			      u8 *data, int data_len)
1097e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1098e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	static const int timeout = 1000;
1099e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i, j;
1100e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x80 | fpga_index,
11010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1102e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0xc0 | fpga_index,
11030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1104e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0;
11050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     (readw(devpriv->mite->daq_io_addr +
11060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) {
1107e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		udelay(1);
1108e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1109e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (i == timeout) {
11102d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
11112d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		       "waiting for status 0x2\n", fpga_index);
1112e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EIO;
1113e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1114e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x80 | fpga_index,
11150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1116e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0;
11170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) !=
11180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     0x3 && i < timeout; ++i) {
1119e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		udelay(1);
1120e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1121e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (i == timeout) {
11222d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
11232d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		       "waiting for status 0x3\n", fpga_index);
1124e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EIO;
1125e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1126e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (j = 0; j + 1 < data_len;) {
1127e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		unsigned int value = data[j++];
1128e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		value |= data[j++] << 8;
1129e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(value,
11300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Firmware_Data_Register);
1131e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0;
11320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     (readw(devpriv->mite->daq_io_addr +
11330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    Firmware_Status_Register) & 0x2) == 0
11340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     && i < timeout; ++i) {
1135e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			udelay(1);
1136e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1137e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (i == timeout) {
1138e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk("ni_pcidio: failed to load word into fpga %i\n",
11390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       fpga_index);
1140e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return -EIO;
1141e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1142e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (need_resched())
1143e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			schedule();
1144e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1145e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1146e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1147e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1148e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
1150e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1151e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return pci_6534_load_fpga(dev, fpga_index, NULL, 0);
1152e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1153e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_reset_fpgas(struct comedi_device *dev)
1155e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1156e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1157e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1158e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1159e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0; i < 3; ++i) {
1160e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ret = pci_6534_reset_fpga(dev, i);
1161e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (ret < 0)
1162e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
1163e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1164e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register);
1165e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return ret;
1166e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1167e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci_6534_init_main_fpga(struct comedi_device *dev)
1169e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1170e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
1171e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
1172e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
1173e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register);
1174e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register);
1175e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
1176e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1177e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
1179e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1180e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1181e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	void *main_fpga_data, *scarab_a_data, *scarab_b_data;
1182e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len;
1183e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1184e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0)
1185e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 0;
1186e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_reset_fpgas(dev);
1187e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1188e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1189e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	main_fpga_data = comedi_aux_data(options, 0);
1190e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
1191e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len);
1192e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1193e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1194e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	pci_6534_init_main_fpga(dev);
1195e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_a_data = comedi_aux_data(options, 1);
1196e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
1197e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len);
1198e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1199e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1200e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_b_data = comedi_aux_data(options, 2);
1201e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
1202e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len);
1203e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1204e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1205e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1206e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1207e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1209e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
121034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
1211e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1212e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1213e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int n_subdevices;
1214e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int irq;
1215e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12162d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "comedi%d: nidio:", dev->minor);
1217e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12182d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	ret = alloc_private(dev, sizeof(struct nidio96_private));
12192d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (ret < 0)
1220e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1221e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	spin_lock_init(&devpriv->mite_channel_lock);
1222e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1223e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = nidio_find_device(dev, it->options[0], it->options[1]);
1224e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1225e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1226e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1227e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = mite_setup(devpriv->mite);
1228e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0) {
12292d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "error setting up mite\n");
1230e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1231e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1232e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
1233e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
1234e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_ring == NULL)
1235e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -ENOMEM;
1236e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1237e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	dev->board_name = this_board->name;
1238e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	irq = mite_irq(devpriv->mite);
12392d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO " %s", dev->board_name);
1240e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (this_board->uses_firmware) {
1241e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ret = pci_6534_upload_firmware(dev, it->options);
1242e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (ret < 0)
1243e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return ret;
1244e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
12452d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (!this_board->is_diodaq)
1246e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_subdevices = this_board->n_8255;
12472d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	else
1248e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_subdevices = 1;
12492d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
12502d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	ret = alloc_subdevices(dev, n_subdevices);
12512d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (ret < 0)
1252e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1253e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1254e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!this_board->is_diodaq) {
1255e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0; i < this_board->n_8255; i++) {
1256e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			subdev_8255_init(dev, dev->subdevices + i,
12570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 nidio96_8255_cb,
12580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 (unsigned long)(devpriv->mite->
12590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							 daq_io_addr +
12600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							 NIDIO_8255_BASE(i)));
1261e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1262e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
1263e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12642d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_INFO " rev=%d",
12650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       readb(devpriv->mite->daq_io_addr + Chip_Version));
1266e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1267e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s = dev->subdevices + 0;
1268e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1269e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		dev->read_subdev = s;
1270e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->type = COMEDI_SUBD_DIO;
1271e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->subdev_flags =
12720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
12730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    SDF_CMD_READ;
1274e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->n_chan = 32;
1275e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->range_table = &range_digital;
1276e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->maxdata = 1;
1277e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->insn_config = &ni_pcidio_insn_config;
1278e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->insn_bits = &ni_pcidio_insn_bits;
1279e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->do_cmd = &ni_pcidio_cmd;
1280e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->do_cmdtest = &ni_pcidio_cmdtest;
1281e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->cancel = &ni_pcidio_cancel;
1282e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->len_chanlist = 32;	/* XXX */
1283e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->buf_change = &ni_pcidio_change;
1284e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async_dma_dir = DMA_BIDIRECTIONAL;
128502f69d67684b77f7f04e281a026a790f0e08b3a3Ian Abbott		s->poll = &ni_pcidio_poll;
1286e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1287e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
1288e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
1289e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0));
1290e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1291e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* disable interrupts on board */
1292e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00,
12930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr +
12940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Master_DMA_And_Interrupt_Control);
1295e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
12975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman				  "ni_pcidio", dev);
12982d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (ret < 0)
12992d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			printk(KERN_WARNING " irq not available");
13002d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
1301e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		dev->irq = irq;
1302e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1303e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1304e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
1305e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1306e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1307e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1308e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
13090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_detach(struct comedi_device *dev)
1310e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1311e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1312e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1313e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (this_board && !this_board->is_diodaq) {
13142d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		for (i = 0; i < this_board->n_8255; i++)
1315e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			subdev_8255_cleanup(dev, dev->subdevices + i);
1316e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1317e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1318e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dev->irq)
13195f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
1320e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1321e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv) {
1322e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (devpriv->di_mite_ring) {
1323e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_free_ring(devpriv->di_mite_ring);
1324e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			devpriv->di_mite_ring = NULL;
1325e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1326e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (devpriv->mite)
1327e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_unsetup(devpriv->mite);
1328e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1329e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1330e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1331e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
13320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_find_device(struct comedi_device *dev, int bus, int slot)
1333e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1334e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite;
1335e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1336e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1337e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (mite = mite_devices; mite; mite = mite->next) {
1338e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (mite->used)
1339e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			continue;
1340e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (bus || slot) {
1341e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			if (bus != mite->pcidev->bus->number ||
13420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    slot != PCI_SLOT(mite->pcidev->devfn))
1343e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				continue;
1344e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1345e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0; i < n_nidio_boards; i++) {
1346e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			if (mite_device_id(mite) == nidio_boards[i].dev_id) {
1347e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				dev->board_ptr = nidio_boards + i;
1348e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				devpriv->mite = mite;
1349e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1350e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				return 0;
1351e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			}
1352e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1353e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
13542d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_WARNING "no device found\n");
1355e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_list_devices();
1356e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return -EIO;
1357e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1358e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1359727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_pcidio_pci_probe(struct pci_dev *dev,
1360727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					     const struct pci_device_id *ent)
1361727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1362727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_pcidio.driver_name);
1363727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1364727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1365727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_pcidio_pci_remove(struct pci_dev *dev)
1366727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1367727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
1368727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1369727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1370727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_pcidio_pci_driver = {
1371727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = ni_pcidio_pci_table,
1372727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_pcidio_pci_probe,
1373727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_pcidio_pci_remove)
1374727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
1375727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1376727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_pcidio_init_module(void)
1377727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1378727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
1379727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1380727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_pcidio);
1381727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
1382727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
1383727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1384727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_pcidio_pci_driver.name = (char *)driver_pcidio.driver_name;
1385727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_pcidio_pci_driver);
1386727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1387727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1388727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_pcidio_cleanup_module(void)
1389727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1390727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_pcidio_pci_driver);
1391727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_pcidio);
1392727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1393727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1394727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_pcidio_init_module);
1395727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_pcidio_cleanup_module);
13963c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian Abbott
13973c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_AUTHOR("Comedi http://www.comedi.org");
13983c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_DESCRIPTION("Comedi low-level driver");
13993c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_LICENSE("GPL");
1400