ni_pcidio.c revision 25985edcedea6396277003854657b5f3cb31a628
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
33e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefUpdated: Sun, 21 Apr 2002 21:03:38 -0700
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
45e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThis driver could be easily modified to support AT-MIO32HS and
46e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefAT-MIO96.
47e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
48e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefThe PCI-6534 requires a firmware upload after power-up to work, the
49e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleeffirmware data and instructions for loading it with comedi_config
50e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefit are contained in the
51e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefcomedi_nonfree_firmware tarball available from http://www.comedi.org
52e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef*/
53e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
54e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/*
55e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96,
56e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   which have very different architectures.  But, since the '96 is
57e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   so simple, it is included here.
58e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
59e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef   Manuals (available from ftp://ftp.natinst.com/support/manuals)
60e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
61e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	320938c.pdf	PCI-DIO-96/PXI-6508/PCI-6503 User Manual
62e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	321464b.pdf	AT/PCI-DIO-32HS User Manual
63e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	341329A.pdf	PCI-6533 Register-Level Programmer Manual
64e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	341330A.pdf	DAQ-DIO Technical Reference Manual
65e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
66e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef */
67e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
68e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define USE_DMA
6956e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* #define DEBUG 1 */
7056e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* #define DEBUG_FLAGS */
71e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7225436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
734377a026500a3f59e9c41c23d03e55ff2e712379Greg Kroah-Hartman#include <linux/sched.h>
74e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "../comedidev.h"
75e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
76e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "mite.h"
77e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#include "8255.h"
78e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
79e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#undef DPRINTK
80e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG
81e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DPRINTK(format, args...)	printk(format, ## args)
82e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
83e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DPRINTK(format, args...)
84e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
85e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
86e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PCI_DIO_SIZE 4096
87e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PCI_MITE_SIZE 4096
88e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
89e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* defines for the PCI-DIO-96 */
90e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
91e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_8255_BASE(x)	((x)*4)
92e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_A 0
93e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_B 4
94e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_C 8
95e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define NIDIO_D 12
96e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
97e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* defines for the PCI-DIO-32HS */
98e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
99e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Window_Address			4	/* W */
100e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Interrupt_And_Window_Status	4	/* R */
101e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntStatus1				(1<<0)
102e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntStatus2				(1<<1)
103e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define WindowAddressStatus_mask		0x7c
104e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
105e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Master_DMA_And_Interrupt_Control 5	/* W */
106e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InterruptLine(x)			((x)&3)
107e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenInt				(1<<2)
108e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_Status			5	/* R */
109e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DataLeft				(1<<0)
110e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Req					(1<<2)
111e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StopTrig				(1<<3)
112e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
113e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_Flags			6	/* R */
114e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_Flags			7	/* R */
115e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferReady				(1<<0)
116e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define CountExpired				(1<<1)
117e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Waited				(1<<5)
118e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PrimaryTC				(1<<6)
119e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define SecondaryTC				(1<<7)
12056e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define SerialRose */
12156e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define ReqRose */
12256e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton  /* #define Paused */
123e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
124e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_First_Clear		6	/* W */
125e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_First_Clear		7	/* W */
126e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearWaited				(1<<3)
127e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearPrimaryTC			(1<<4)
128e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearSecondaryTC			(1<<5)
129e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMAReset				(1<<6)
130e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOReset				(1<<7)
131e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearAll				0xf8
132e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
133e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_FIFO			8	/* W */
134e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_FIFO			12	/* W */
135e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
136e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Transfer_Count			20
137e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_D			24
138e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_I			25
139e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_ID_O			26
140e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Chip_Version			27
141e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_IO(x)			(28+(x))
142e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Directions(x)		(32+(x))
143e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Mask(x)		(36+(x))
144e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pin_Polarities(x)		(40+(x))
145e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
146e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Master_Clock_Routing		45
147e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RTSIClocking(x)			(((x)&3)<<4)
148e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
149e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_1_Second_Clear		46	/* W */
150e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Group_2_Second_Clear		47	/* W */
151e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClearExpired				(1<<0)
152e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
153e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Port_Pattern(x)			(48+(x))
154e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
155e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Data_Path			64
156e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableA		(1<<0)
157e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableB		(1<<1)
158e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableC		(1<<2)
159e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFOEnableD		(1<<3)
160e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Funneling(x)		(((x)&3)<<4)
161e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define GroupDirection	(1<<7)
162e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
163e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_1		65
164e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpMode				Protocol_Register_1
165e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RunMode(x)		((x)&7)
166e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Numbered		(1<<3)
167e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
168e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_2		66
169e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockReg			Protocol_Register_2
170e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockLine(x)		(((x)&3)<<5)
171e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertStopTrig	(1<<7)
172e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DataLatching(x)       (((x)&3)<<5)
173e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
174e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_3		67
175e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Sequence			Protocol_Register_3
176e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
177e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_14		68	/* 16 bit */
178e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ClockSpeed			Protocol_Register_14
179e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
180e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_4		70
181e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqReg				Protocol_Register_4
182e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqConditioning(x)	(((x)&7)<<3)
183e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
184e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_5		71
185e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define BlockMode			Protocol_Register_5
186e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
187e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define FIFO_Control			72
188e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReadyLevel(x)		((x)&7)
189e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
190e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_6		73
191e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define LinePolarities			Protocol_Register_6
192e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertAck		(1<<0)
193e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertReq		(1<<1)
194e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertClock		(1<<2)
195e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertSerial		(1<<3)
196e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenAck		(1<<4)
197e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define OpenClock		(1<<5)
198e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
199e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_7		74
200e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckSer				Protocol_Register_7
201e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckLine(x)		(((x)&3)<<2)
202e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ExchangePins		(1<<7)
203e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
204e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Interrupt_Control		75
205e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef  /* bits same as flags */
206e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
207e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMA_Line_Control_Group1		76
208e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DMA_Line_Control_Group2		108
20956e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton/* channel zero is none */
210e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic inline unsigned primary_DMAChannel_bits(unsigned channel)
211e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
212e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return channel & 0x3;
213e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
2140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
215e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic inline unsigned secondary_DMAChannel_bits(unsigned channel)
216e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
217e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return (channel << 2) & 0xc;
218e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
219e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
220e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Transfer_Size_Control		77
221e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferWidth(x)	((x)&3)
222e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TransferLength(x)	(((x)&3)<<3)
223e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define RequireRLevel		(1<<5)
224e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
225e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_15		79
226e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DAQOptions			Protocol_Register_15
227e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StartSource(x)			((x)&0x3)
228e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertStart				(1<<2)
229e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StopSource(x)				(((x)&0x3)<<3)
230e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqStart				(1<<6)
231e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define PreStart				(1<<7)
232e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
233e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Pattern_Detection		81
234e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define DetectionMethod			(1<<0)
235e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define InvertMatch				(1<<1)
236e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IE_Pattern_Detection			(1<<2)
237e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
238e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_9		82
239e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqDelay			Protocol_Register_9
240e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
241e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_10		83
242e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ReqNotDelay			Protocol_Register_10
243e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
244e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_11		84
245e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckDelay			Protocol_Register_11
246e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
247e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_12		85
248e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define AckNotDelay			Protocol_Register_12
249e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
250e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_13		86
251e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Data1Delay			Protocol_Register_13
252e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
253e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define Protocol_Register_8		88	/* 32 bit */
254e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define StartDelay			Protocol_Register_8
255e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
256e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum pci_6534_firmware_registers {	/* 16 bit */
257e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Control_Register = 0x100,
258e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Status_Register = 0x104,
259e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Data_Register = 0x108,
260e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Mask_Register = 0x10c,
261e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	Firmware_Debug_Register = 0x110,
262e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
263e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef/* main fpga registers (32 bit)*/
264e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum pci_6534_fpga_registers {
265e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Control1_Register = 0x200,
266e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Control2_Register = 0x204,
267e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Irq_Mask_Register = 0x208,
268e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Status_Register = 0x20c,
269e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Signature_Register = 0x210,
270e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCALS_Counter_Register = 0x280,	/*write-clear */
271e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCAMS_Counter_Register = 0x284,	/*write-clear */
272e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCBLS_Counter_Register = 0x288,	/*write-clear */
273e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_SCBMS_Counter_Register = 0x28c,	/*write-clear */
274e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Temp_Control_Register = 0x2a0,
275e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_DAR_Register = 0x2a8,
276e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_ELC_Read_Register = 0x2b8,
277e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_ELC_Write_Register = 0x2bc,
278e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
279e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefenum FPGA_Control_Bits {
280e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	FPGA_Enable_Bit = 0x8000,
281e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
282e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
283e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define TIMER_BASE 50		/* nanoseconds */
284e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
285e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef USE_DMA
286e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC)
287e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
288e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
289e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
290e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
291da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
292da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_detach(struct comedi_device *dev);
2930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cancel(struct comedi_device *dev,
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
295e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
296139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_pcidio = {
29768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "ni_pcidio",
29868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
29968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = nidio_attach,
30068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = nidio_detach,
301e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
302e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
303a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pembertonstruct nidio_board {
304a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton
305e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int dev_id;
306e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	const char *name;
307e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int n_8255;
308e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int is_diodaq:1;
309e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int uses_firmware:1;
310a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton};
311a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton
312a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pembertonstatic const struct nidio_board nidio_boards[] = {
313e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1150,
3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-32hs",
3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
319e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1320,
3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6533",
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
325e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x12b0,
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6534",
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 0,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 1,
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .uses_firmware = 1,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
332e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x0160,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-96",
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
338e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1630,
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dio-96b",
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
344e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x13c0,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6508",
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 4,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
350e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x0400,
3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503",
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
356e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1250,
3580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503b",
3590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
362e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x17d0,
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-6503x",
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
368e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
3690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .dev_id = 0x1800,
3700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pxi-6503",
3710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .n_8255 = 1,
3720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .is_diodaq = 0,
3730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
374e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
375e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
376b6ac161364eccce1bea4a23a9de395883e90d7abStoyan Gaydarov#define n_nidio_boards ARRAY_SIZE(nidio_boards)
377a7195f3d92f5fc560e597598a56d9c394b65ee81Bill Pemberton#define this_board ((const struct nidio_board *)dev->board_ptr)
378e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
379e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
3804e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150)},
3814e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320)},
3824e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0)},
3834e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160)},
3844e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630)},
3854e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0)},
3864e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400)},
3874e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250)},
3884e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0)},
3894e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800)},
3904e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman	{0}
391e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
392e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
393e20903165f0f11827657e0c5d3bfbfdaed13207bDavid SchleefMODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
394e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
3952e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pembertonstruct nidio96_private {
396e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite;
397e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int boardtype;
398e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int dio;
399e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned short OpModeBits;
400e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_channel *di_mite_chan;
401e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_dma_descriptor_ring *di_mite_ring;
402e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	spinlock_t mite_channel_lock;
4032e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pemberton};
4042e93aa5b5b8050090a22e162f9af6b18ca3ec47aBill Pemberton#define devpriv ((struct nidio96_private *)dev->private)
405e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmdtest(struct comedi_device *dev,
4070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
4080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_cmd *cmd);
409da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
4100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_inttrig(struct comedi_device *dev,
4110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, unsigned int trignum);
412da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nidio_find_device(struct comedi_device *dev, int bus, int slot);
413e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
4140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int setup_mite_dma(struct comedi_device *dev,
4150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
416e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
417e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG_FLAGS
418e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_flags(unsigned int flags);
419e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_status(unsigned int status);
420e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
421e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ni_pcidio_print_flags(x)
422e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define ni_pcidio_print_status(x)
423e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
424e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
425da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
426e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
427e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned long flags;
428e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4295f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
430e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	BUG_ON(devpriv->di_mite_chan);
431e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	devpriv->di_mite_chan =
4320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    mite_request_channel_in_range(devpriv->mite,
4330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  devpriv->di_mite_ring, 1, 2);
434e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan == NULL) {
4355f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
436e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		comedi_error(dev, "failed to reserve mite dma channel.");
437e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EBUSY;
438e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
439e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
4400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
4410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
442e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mmiowb();
4435f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
444e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
445e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
446e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
447da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
448e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
449e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned long flags;
450e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
4515f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
452e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan) {
453e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_dma_disarm(devpriv->di_mite_chan);
454e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_dma_reset(devpriv->di_mite_chan);
455e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mite_release_channel(devpriv->di_mite_chan);
456e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->di_mite_chan = NULL;
457e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(primary_DMAChannel_bits(0) |
4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       secondary_DMAChannel_bits(0),
4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
460e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		mmiowb();
461e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
4625f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
463e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
464e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
465e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
466e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
467e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dir) {
468e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(data, (void *)(iobase + port));
469e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 0;
470e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
471e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return readb((void *)(iobase + port));
472e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
473e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
474e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
475da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonvoid ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
476e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
4770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	if (s->
4780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
4790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     COMEDI_CB_OVERFLOW)) {
480e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ni_pcidio_cancel(dev, s);
481e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
482e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	comedi_event(dev, s);
483e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
484e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
48570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t nidio_interrupt(int irq, void *d)
486e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
48771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
48834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices;
489d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
490e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite = devpriv->mite;
491e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
49256e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* int i, j; */
493e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	long int AuxData = 0;
494790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short data1 = 0;
495790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short data2 = 0;
496e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int flags;
497e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int status;
498e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int work = 0;
499e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int m_status = 0;
500e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned long irq_flags;
501e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
50256e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* interrupcions parasites */
503e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dev->attached == 0) {
50456e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* assume it's from another card */
505e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return IRQ_NONE;
506e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
507e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
508e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	status = readb(devpriv->mite->daq_io_addr +
5090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Interrupt_And_Window_Status);
510e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
511e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
512e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n",
513e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		status, flags);
514e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_print_flags(flags);
515e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_print_status(status);
516e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
51756e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
5182d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* printk("buf[4096]=%08x\n",
5192d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       *(unsigned int *)(async->prealloc_buf+4096)); */
520e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
5215f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
522e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_chan)
523e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		m_status = mite_get_status(devpriv->di_mite_chan);
524e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef MITE_DEBUG
525e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_print_chsr(m_status);
526e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
5272d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* printk("mite_bytes_transferred: %d\n",
5282d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       mite_bytes_transferred(mite,DI_DMA_CHAN)); */
5292d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
53056e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	/* mite_dump_regs(mite); */
531e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (m_status & CHSR_INT) {
532e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (m_status & CHSR_LINKC) {
533e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writel(CHOR_CLRLC,
5340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       mite->mite_io_addr +
5350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       MITE_CHOR(devpriv->di_mite_chan->channel));
536e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_sync_input_dma(devpriv->di_mite_chan, s->async);
537e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			/* XXX need to byteswap */
538e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
539e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY |
5400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 CHSR_DRQ1 | CHSR_MRDY)) {
541e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("unknown mite interrupt, disabling IRQ\n");
542e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
543e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			disable_irq(dev->irq);
544e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
545e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
5465f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags);
547e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
548e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	while (status & DataLeft) {
549e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		work++;
550e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (work > 20) {
551e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("too much work in interrupt\n");
552e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00,
5530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Master_DMA_And_Interrupt_Control);
555e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
556e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
557e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
558e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		flags &= IntEn;
559e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
560e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (flags & TransferReady) {
56156e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* DPRINTK("TransferReady\n"); */
562e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			while (flags & TransferReady) {
563e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				work++;
564e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				if (work > 100) {
565e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					DPRINTK("too much work in interrupt\n");
566e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					writeb(0x00,
5670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       devpriv->mite->daq_io_addr +
5682d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi					       Master_DMA_And_Interrupt_Control
5692d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi					      );
570e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef					goto out;
571e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				}
572e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				AuxData =
5730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    readl(devpriv->mite->daq_io_addr +
5740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  Group_1_FIFO);
575e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				data1 = AuxData & 0xffff;
576e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				data2 = (AuxData & 0xffff0000) >> 16;
577e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				comedi_buf_put(async, data1);
578e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				comedi_buf_put(async, data2);
57956e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton				/* DPRINTK("read:%d, %d\n",data1,data2); */
580e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				flags = readb(devpriv->mite->daq_io_addr +
5810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					      Group_1_Flags);
582e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			}
5832d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			/* DPRINTK("buf_int_count: %d\n",
5842d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi				async->buf_int_count); */
5852d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",
5862d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi				IntEn,flags,status); */
58756e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* ni_pcidio_print_flags(flags); */
58856e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton			/* ni_pcidio_print_status(status); */
589e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_BLOCK;
590e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
591e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
592e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (flags & CountExpired) {
593e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("CountExpired\n");
594e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearExpired,
5950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
5960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_Second_Clear);
597e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
598e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
599e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00, devpriv->mite->daq_io_addr + OpMode);
600e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
601e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & Waited) {
602e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("Waited\n");
603e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearWaited,
6040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
606e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
607e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
608e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & PrimaryTC) {
609e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("PrimaryTC\n");
610e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearPrimaryTC,
6110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
613e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
614e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		} else if (flags & SecondaryTC) {
615e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			DPRINTK("SecondaryTC\n");
616e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(ClearSecondaryTC,
6170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Group_1_First_Clear);
619e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_EOA;
620e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
621e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#if 0
622e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		else {
623e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk("ni_pcidio: unknown interrupt\n");
624e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
625e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			writeb(0x00,
6260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       devpriv->mite->daq_io_addr +
6270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Master_DMA_And_Interrupt_Control);
628e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
629e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
630e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
631e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		status = readb(devpriv->mite->daq_io_addr +
6320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       Interrupt_And_Window_Status);
6332d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,"
6342d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			"status=0x%02x\n", IntEn, flags, status); */
63556e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* ni_pcidio_print_flags(flags); */
63656e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton		/* ni_pcidio_print_status(status); */
637e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
638e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
6390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralout:
640e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_event(dev, s);
641e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#if 0
642e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!tag) {
643e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x03,
6440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr +
6450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Master_DMA_And_Interrupt_Control);
646e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
647e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
648e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return IRQ_HANDLED;
649e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
650e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
651e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef DEBUG_FLAGS
652e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic const char *const flags_strings[] = {
653e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"TransferReady", "CountExpired", "2", "3",
654e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"4", "Waited", "PrimaryTC", "SecondaryTC",
655e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
6560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
657e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_flags(unsigned int flags)
658e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
659e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
660e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
6612d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "group_1_flags:");
662e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 7; i >= 0; i--) {
6632d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (flags & (1 << i))
664e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk(" %s", flags_strings[i]);
665e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
666e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
667e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
6680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
669e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic char *status_strings[] = {
670e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"DataLeft1", "Reserved1", "Req1", "StopTrig1",
671e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	"DataLeft2", "Reserved2", "Req2", "StopTrig2",
672e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef};
6730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
674e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic void ni_pcidio_print_status(unsigned int flags)
675e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
676e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
677e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
6782d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "group_status:");
679e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 7; i >= 0; i--) {
6802d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (flags & (1 << i))
681e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk(" %s", status_strings[i]);
682e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
683e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
684e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
685e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
686e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
687e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef unused
6880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void debug_int(struct comedi_device *dev)
689e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
690e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int a, b;
691e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	static int n_int = 0;
692e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct timeval tv;
693e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
694e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	do_gettimeofday(&tv);
695e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	a = readb(devpriv->mite->daq_io_addr + Group_Status);
696e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
697e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
698e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (n_int < 10) {
699e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		DPRINTK("status 0x%02x flags 0x%02x time %06d\n", a, b,
700e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			(int)tv.tv_usec);
701e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
702e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
703e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	while (b & 1) {
704e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0xff, devpriv->mite->daq_io_addr + Group_1_FIFO);
705e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
706e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
707e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
708e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
709e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
710e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (n_int < 10) {
711e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		DPRINTK("new status 0x%02x\n", b);
712e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_int++;
713e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
714e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
715e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
716e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_insn_config(struct comedi_device *dev,
7180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
7190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data)
720e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
721e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (insn->n != 1)
722e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
723e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	switch (data[0]) {
724e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
725e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->io_bits |= 1 << CR_CHAN(insn->chanspec);
726e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
727e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_INPUT:
728e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
729e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
730e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case INSN_CONFIG_DIO_QUERY:
731e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		data[1] =
7320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (s->
7330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
7340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    COMEDI_INPUT;
735e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return insn->n;
736e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
737e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	default:
738e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
739e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
740e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
741e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
742e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 1;
743e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
744e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_insn_bits(struct comedi_device *dev,
7460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
7470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_insn *insn, unsigned int *data)
748e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
749e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (insn->n != 2)
750e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
751e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (data[0]) {
752e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->state &= ~data[0];
753e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->state |= (data[0] & data[1]);
754e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
755e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
756e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
757e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
758e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 2;
759e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
760e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmdtest(struct comedi_device *dev,
7620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
763e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
764e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int err = 0;
765e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int tmp;
766e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
767e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 1: make sure trigger sources are trivially valid */
768e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
769e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->start_src;
770e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->start_src &= TRIG_NOW | TRIG_INT;
771e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->start_src || tmp != cmd->start_src)
772e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
773e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
774e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->scan_begin_src;
775e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
776e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
777e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
778e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
779e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->convert_src;
780e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->convert_src &= TRIG_NOW;
781e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->convert_src || tmp != cmd->convert_src)
782e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
783e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
784e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->scan_end_src;
785e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->scan_end_src &= TRIG_COUNT;
786e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
787e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
788e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
789e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	tmp = cmd->stop_src;
790e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
791e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!cmd->stop_src || tmp != cmd->stop_src)
792e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
793e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
794e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
795e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 1;
796e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
7972d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* step 2: make sure trigger sources are unique and mutually
7982d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	compatible */
799e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
800828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
801e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
802e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
803e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src != TRIG_TIMER &&
8040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
805e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
806e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
807e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
808e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 2;
809e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
810e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 3: make sure arguments are trivially compatible */
811e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
812e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_arg != 0) {
813e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* same for both TRIG_INT and TRIG_NOW */
814e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->start_arg = 0;
815e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
816e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
817e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#define MAX_SPEED	(TIMER_BASE)	/* in nanoseconds */
818e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
819e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
820e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (cmd->scan_begin_arg < MAX_SPEED) {
821e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			cmd->scan_begin_arg = MAX_SPEED;
822e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
823e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
82425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* no minimum speed */
825e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
826e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_EXT */
827e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* should be level/edge, hi/lo specification here */
828e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (cmd->scan_begin_arg != 0) {
829e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			cmd->scan_begin_arg = 0;
830e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
831e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
832e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
833e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->convert_arg != 0) {
834e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->convert_arg = 0;
835e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
836e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
837e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
838e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_end_arg != cmd->chanlist_len) {
839e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		cmd->scan_end_arg = cmd->chanlist_len;
840e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		err++;
841e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
842e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
843e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* no limit */
844e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
845e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_NONE */
846e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (cmd->stop_arg != 0) {
847e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			cmd->stop_arg = 0;
848e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
849e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
850e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
851e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
852e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
853e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 3;
854e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
855e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* step 4: fix up any arguments */
856e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
857e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
858e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		tmp = cmd->scan_begin_arg;
859e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
8600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      cmd->flags & TRIG_ROUND_MASK);
861e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (tmp != cmd->scan_begin_arg)
862e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			err++;
863e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
864e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
865e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (err)
866e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 4;
867e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
868e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
869e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
870e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
871e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleefstatic int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
872e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
873e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int divider, base;
874e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
875e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	base = TIMER_BASE;
876e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
877e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	switch (round_mode) {
878e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_NEAREST:
879e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	default:
880e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec + base / 2) / base;
881e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
882e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_DOWN:
883e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec) / base;
884e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
885e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	case TRIG_ROUND_UP:
886e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		divider = (*nanosec + base - 1) / base;
887e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		break;
888e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
889e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
890e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	*nanosec = base * divider;
891e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return divider;
892e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
893e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
8940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
895e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
896ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
897e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
898e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* XXX configure ports for input */
899e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
900e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
901e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (1) {
902e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* enable fifos A B C D */
903e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path);
904e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
905e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* set transfer width a 32 bits */
906e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(TransferWidth(0) | TransferLength(0),
9070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
908e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
909e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x03, devpriv->mite->daq_io_addr + Data_Path);
910e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(TransferWidth(3) | TransferLength(0),
9110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
912e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
913e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
914e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* protocol configuration */
915e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->scan_begin_src == TRIG_TIMER) {
916e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* page 4-5, "input with internal REQs" */
917e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + OpMode);
918e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
919e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + Sequence);
920e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x04, devpriv->mite->daq_io_addr + ReqReg);
921e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
922e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(3, devpriv->mite->daq_io_addr + LinePolarities);
923e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0xc0, devpriv->mite->daq_io_addr + AckSer);
924e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     TRIG_ROUND_NEAREST),
9260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + StartDelay);
927e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
928e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
929e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
930e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay);
931e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay);
932e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* manual, page 4-5: ClockSpeed comment is incorrectly listed
933e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		 * on DAQOptions */
934e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
935e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + DAQOptions);
936e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
937e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_EXT */
938e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* page 4-5, "input with external REQs" */
939e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + OpMode);
940e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
941e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + Sequence);
942e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + ReqReg);
943e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
944e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0, devpriv->mite->daq_io_addr + LinePolarities);
945e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00, devpriv->mite->daq_io_addr + AckSer);
946e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(1, devpriv->mite->daq_io_addr + StartDelay);
947e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
948e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
949e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
950e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay);
951e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay);
952e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
953e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions);
954e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
955e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
956e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_COUNT) {
957e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(cmd->stop_arg,
9580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Transfer_Count);
959e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
960e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* XXX */
961e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
962e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
963e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#ifdef USE_DMA
964e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(ClearPrimaryTC | ClearSecondaryTC,
9650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Group_1_First_Clear);
966e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
967e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	{
968e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		int retval = setup_mite_dma(dev, s);
969e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (retval)
970e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return retval;
971e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
972e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#else
973e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
974e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef#endif
975e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2);
976e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
977e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	/* clear and enable interrupts */
978e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
9792d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	/* writeb(ClearExpired,
9802d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	       devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
981e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
982e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
983e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x03,
9840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
985e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
986e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->stop_src == TRIG_NONE) {
987e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->OpModeBits = DataLatching(0) | RunMode(7);
98856e9e16619a0c14dc948cf88b3a7aaa70ac92b45Bill Pemberton	} else {		/* TRIG_TIMER */
989e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		devpriv->OpModeBits = Numbered | RunMode(7);
990e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
991e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (cmd->start_src == TRIG_NOW) {
992e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* start */
993e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(devpriv->OpModeBits,
9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + OpMode);
995e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async->inttrig = NULL;
996e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
997e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* TRIG_INT */
998e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async->inttrig = ni_pcidio_inttrig;
999e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1000e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1001e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	DPRINTK("ni_pcidio: command started\n");
1002e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1003e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1004e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1006e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1007e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int retval;
1008e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1009e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	retval = ni_pcidio_request_di_mite_channel(dev);
1010e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (retval)
1011e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return retval;
1012e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1013e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	devpriv->di_mite_chan->dir = COMEDI_INPUT;
1014e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1015e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_prep_dma(devpriv->di_mite_chan, 32, 32);
1016e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1017e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_dma_arm(devpriv->di_mite_chan);
1018e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1019e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1020e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_inttrig(struct comedi_device *dev,
10220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, unsigned int trignum)
1023e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1024e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (trignum != 0)
1025e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EINVAL;
1026e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1027e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode);
1028e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	s->async->inttrig = NULL;
1029e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1030e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 1;
1031e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1032e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_cancel(struct comedi_device *dev,
10340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
1035e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1036e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writeb(0x00,
10370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
1038e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ni_pcidio_release_di_mite_channel(dev);
1039e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1040e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1041e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1042e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ni_pcidio_change(struct comedi_device *dev,
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s, unsigned long new_size)
1045e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1046e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1047e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1048e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = mite_buf_change(devpriv->di_mite_ring, s->async);
1049e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1050e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1051e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1052e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
1053e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1054e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1055e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1056e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
10570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
10582d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			      u8 *data, int data_len)
1059e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1060e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	static const int timeout = 1000;
1061e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i, j;
1062e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x80 | fpga_index,
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1064e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0xc0 | fpga_index,
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1066e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0;
10670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     (readw(devpriv->mite->daq_io_addr +
10680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) {
1069e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		udelay(1);
1070e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1071e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (i == timeout) {
10722d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
10732d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		       "waiting for status 0x2\n", fpga_index);
1074e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EIO;
1075e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1076e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x80 | fpga_index,
10770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1078e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0;
10790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) !=
10800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     0x3 && i < timeout; ++i) {
1081e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		udelay(1);
1082e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1083e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (i == timeout) {
10842d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
10852d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		       "waiting for status 0x3\n", fpga_index);
1086e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -EIO;
1087e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1088e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (j = 0; j + 1 < data_len;) {
1089e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		unsigned int value = data[j++];
1090e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		value |= data[j++] << 8;
1091e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writew(value,
10920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr + Firmware_Data_Register);
1093e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0;
10940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     (readw(devpriv->mite->daq_io_addr +
10950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    Firmware_Status_Register) & 0x2) == 0
10960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     && i < timeout; ++i) {
1097e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			udelay(1);
1098e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1099e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (i == timeout) {
1100e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			printk("ni_pcidio: failed to load word into fpga %i\n",
11010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       fpga_index);
1102e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return -EIO;
1103e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1104e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (need_resched())
1105e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			schedule();
1106e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1107e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1108e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1109e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1110e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
1112e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1113e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return pci_6534_load_fpga(dev, fpga_index, NULL, 0);
1114e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1115e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_reset_fpgas(struct comedi_device *dev)
1117e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1118e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1119e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1120e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1121e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (i = 0; i < 3; ++i) {
1122e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ret = pci_6534_reset_fpga(dev, i);
1123e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (ret < 0)
1124e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			break;
1125e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1126e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register);
1127e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return ret;
1128e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1129e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci_6534_init_main_fpga(struct comedi_device *dev)
1131e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1132e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
1133e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
1134e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
1135e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register);
1136e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register);
1137e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
1138e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1139e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
1141e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1142e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1143e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	void *main_fpga_data, *scarab_a_data, *scarab_b_data;
1144e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len;
1145e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1146e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0)
1147e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return 0;
1148e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_reset_fpgas(dev);
1149e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1150e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1151e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	main_fpga_data = comedi_aux_data(options, 0);
1152e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
1153e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len);
1154e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1155e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1156e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	pci_6534_init_main_fpga(dev);
1157e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_a_data = comedi_aux_data(options, 1);
1158e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
1159e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len);
1160e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1161e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1162e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_b_data = comedi_aux_data(options, 2);
1163e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
1164e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len);
1165e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1166e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1167e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1168e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1169e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1171e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
117234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
1173e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1174e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int ret;
1175e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int n_subdevices;
1176e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	unsigned int irq;
1177e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11782d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO "comedi%d: nidio:", dev->minor);
1179e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
11802d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	ret = alloc_private(dev, sizeof(struct nidio96_private));
11812d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (ret < 0)
1182e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1183e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	spin_lock_init(&devpriv->mite_channel_lock);
1184e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1185e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = nidio_find_device(dev, it->options[0], it->options[1]);
1186e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0)
1187e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1188e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1189e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	ret = mite_setup(devpriv->mite);
1190e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (ret < 0) {
11912d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_WARNING "error setting up mite\n");
1192e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1193e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1194e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
1195e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
1196e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv->di_mite_ring == NULL)
1197e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return -ENOMEM;
1198e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1199e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	dev->board_name = this_board->name;
1200e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	irq = mite_irq(devpriv->mite);
12012d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_INFO " %s", dev->board_name);
1202e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (this_board->uses_firmware) {
1203e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		ret = pci_6534_upload_firmware(dev, it->options);
1204e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (ret < 0)
1205e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			return ret;
1206e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
12072d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (!this_board->is_diodaq)
1208e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_subdevices = this_board->n_8255;
12092d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	else
1210e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		n_subdevices = 1;
12112d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
12122d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	ret = alloc_subdevices(dev, n_subdevices);
12132d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	if (ret < 0)
1214e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		return ret;
1215e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1216e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (!this_board->is_diodaq) {
1217e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0; i < this_board->n_8255; i++) {
1218e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			subdev_8255_init(dev, dev->subdevices + i,
12190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 nidio96_8255_cb,
12200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 (unsigned long)(devpriv->mite->
12210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							 daq_io_addr +
12220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							 NIDIO_8255_BASE(i)));
1223e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1224e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	} else {
1225e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12262d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		printk(KERN_INFO " rev=%d",
12270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       readb(devpriv->mite->daq_io_addr + Chip_Version));
1228e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1229e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s = dev->subdevices + 0;
1230e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1231e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		dev->read_subdev = s;
1232e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->type = COMEDI_SUBD_DIO;
1233e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->subdev_flags =
12340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
12350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    SDF_CMD_READ;
1236e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->n_chan = 32;
1237e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->range_table = &range_digital;
1238e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->maxdata = 1;
1239e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->insn_config = &ni_pcidio_insn_config;
1240e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->insn_bits = &ni_pcidio_insn_bits;
1241e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->do_cmd = &ni_pcidio_cmd;
1242e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->do_cmdtest = &ni_pcidio_cmdtest;
1243e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->cancel = &ni_pcidio_cancel;
1244e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->len_chanlist = 32;	/* XXX */
1245e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->buf_change = &ni_pcidio_change;
1246e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		s->async_dma_dir = DMA_BIDIRECTIONAL;
1247e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1248e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
1249e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
1250e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0));
1251e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1252e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		/* disable interrupts on board */
1253e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		writeb(0x00,
12540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       devpriv->mite->daq_io_addr +
12550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       Master_DMA_And_Interrupt_Control);
1256e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12575f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
12585f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman				  "ni_pcidio", dev);
12592d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		if (ret < 0)
12602d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi			printk(KERN_WARNING " irq not available");
12612d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi
1262e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		dev->irq = irq;
1263e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1264e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1265e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	printk("\n");
1266e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1267e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1268e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1269e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_detach(struct comedi_device *dev)
1271e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1272e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1273e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1274e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (this_board && !this_board->is_diodaq) {
12752d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi		for (i = 0; i < this_board->n_8255; i++)
1276e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			subdev_8255_cleanup(dev, dev->subdevices + i);
1277e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1278e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1279e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (dev->irq)
12805f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
1281e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1282e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	if (devpriv) {
1283e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (devpriv->di_mite_ring) {
1284e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_free_ring(devpriv->di_mite_ring);
1285e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			devpriv->di_mite_ring = NULL;
1286e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1287e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (devpriv->mite)
1288e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			mite_unsetup(devpriv->mite);
1289e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
1290e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return 0;
1291e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1292e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
12930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nidio_find_device(struct comedi_device *dev, int bus, int slot)
1294e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef{
1295e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	struct mite_struct *mite;
1296e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	int i;
1297e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1298e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	for (mite = mite_devices; mite; mite = mite->next) {
1299e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (mite->used)
1300e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			continue;
1301e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		if (bus || slot) {
1302e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			if (bus != mite->pcidev->bus->number ||
13030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    slot != PCI_SLOT(mite->pcidev->devfn))
1304e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				continue;
1305e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1306e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		for (i = 0; i < n_nidio_boards; i++) {
1307e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			if (mite_device_id(mite) == nidio_boards[i].dev_id) {
1308e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				dev->board_ptr = nidio_boards + i;
1309e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				devpriv->mite = mite;
1310e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1311e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef				return 0;
1312e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef			}
1313e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef		}
1314e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	}
13152d2facda0b71609be294aa1fd5f56d2cdbcbb794Benjamin Adolphi	printk(KERN_WARNING "no device found\n");
1316e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	mite_list_devices();
1317e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef	return -EIO;
1318e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef}
1319e20903165f0f11827657e0c5d3bfbfdaed13207bDavid Schleef
1320727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_pcidio_pci_probe(struct pci_dev *dev,
1321727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					     const struct pci_device_id *ent)
1322727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1323727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_pcidio.driver_name);
1324727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1325727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1326727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_pcidio_pci_remove(struct pci_dev *dev)
1327727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1328727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
1329727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1330727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1331727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_pcidio_pci_driver = {
1332727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = ni_pcidio_pci_table,
1333727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_pcidio_pci_probe,
1334727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_pcidio_pci_remove)
1335727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
1336727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1337727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_pcidio_init_module(void)
1338727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1339727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
1340727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1341727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_pcidio);
1342727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
1343727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
1344727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1345727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_pcidio_pci_driver.name = (char *)driver_pcidio.driver_name;
1346727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_pcidio_pci_driver);
1347727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1348727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1349727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_pcidio_cleanup_module(void)
1350727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1351727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_pcidio_pci_driver);
1352727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_pcidio);
1353727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1354727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1355727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_pcidio_init_module);
1356727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_pcidio_cleanup_module);
13573c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian Abbott
13583c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_AUTHOR("Comedi http://www.comedi.org");
13593c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_DESCRIPTION("Comedi low-level driver");
13603c323c01b6bd5fd01be21a8f0cdc11e55997aa06Ian AbbottMODULE_LICENSE("GPL");
1361