ni_pcidio.c revision 2d2facda0b71609be294aa1fd5f56d2cdbcbb794
1/*
2    comedi/drivers/ni_pcidio.c
3    driver for National Instruments PCI-DIO-96/PCI-6508
4		National Instruments PCI-DIO-32HS
5		National Instruments PCI-6503
6
7    COMEDI - Linux Control and Measurement Device Interface
8    Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24*/
25/*
26Driver: ni_pcidio
27Description: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503
28Author: ds
29Status: works
30Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533,
31  PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,
32  PXI-6503, PCI-6533, PCI-6534
33Updated: Sun, 21 Apr 2002 21:03:38 -0700
34
35The DIO-96 appears as four 8255 subdevices.  See the 8255
36driver notes for details.
37
38The DIO32HS board appears as one subdevice, with 32 channels.
39Each channel is individually I/O configurable.  The channel order
40is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0.  The driver only
41supports simple digital I/O; no handshaking is supported.
42
43DMA mostly works for the PCI-DIO32HS, but only in timed input mode.
44
45This driver could be easily modified to support AT-MIO32HS and
46AT-MIO96.
47
48The PCI-6534 requires a firmware upload after power-up to work, the
49firmware data and instructions for loading it with comedi_config
50it are contained in the
51comedi_nonfree_firmware tarball available from http://www.comedi.org
52*/
53
54/*
55   This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96,
56   which have very different architectures.  But, since the '96 is
57   so simple, it is included here.
58
59   Manuals (available from ftp://ftp.natinst.com/support/manuals)
60
61	320938c.pdf	PCI-DIO-96/PXI-6508/PCI-6503 User Manual
62	321464b.pdf	AT/PCI-DIO-32HS User Manual
63	341329A.pdf	PCI-6533 Register-Level Programmer Manual
64	341330A.pdf	DAQ-DIO Technical Reference Manual
65
66 */
67
68#define USE_DMA
69/* #define DEBUG 1 */
70/* #define DEBUG_FLAGS */
71
72#include <linux/interrupt.h>
73#include <linux/sched.h>
74#include "../comedidev.h"
75
76#include "mite.h"
77#include "8255.h"
78
79#undef DPRINTK
80#ifdef DEBUG
81#define DPRINTK(format, args...)	printk(format, ## args)
82#else
83#define DPRINTK(format, args...)
84#endif
85
86#define PCI_VENDOR_ID_NATINST	0x1093
87
88#define PCI_DIO_SIZE 4096
89#define PCI_MITE_SIZE 4096
90
91/* defines for the PCI-DIO-96 */
92
93#define NIDIO_8255_BASE(x)	((x)*4)
94#define NIDIO_A 0
95#define NIDIO_B 4
96#define NIDIO_C 8
97#define NIDIO_D 12
98
99/* defines for the PCI-DIO-32HS */
100
101#define Window_Address			4	/* W */
102#define Interrupt_And_Window_Status	4	/* R */
103#define IntStatus1				(1<<0)
104#define IntStatus2				(1<<1)
105#define WindowAddressStatus_mask		0x7c
106
107#define Master_DMA_And_Interrupt_Control 5	/* W */
108#define InterruptLine(x)			((x)&3)
109#define OpenInt				(1<<2)
110#define Group_Status			5	/* R */
111#define DataLeft				(1<<0)
112#define Req					(1<<2)
113#define StopTrig				(1<<3)
114
115#define Group_1_Flags			6	/* R */
116#define Group_2_Flags			7	/* R */
117#define TransferReady				(1<<0)
118#define CountExpired				(1<<1)
119#define Waited				(1<<5)
120#define PrimaryTC				(1<<6)
121#define SecondaryTC				(1<<7)
122  /* #define SerialRose */
123  /* #define ReqRose */
124  /* #define Paused */
125
126#define Group_1_First_Clear		6	/* W */
127#define Group_2_First_Clear		7	/* W */
128#define ClearWaited				(1<<3)
129#define ClearPrimaryTC			(1<<4)
130#define ClearSecondaryTC			(1<<5)
131#define DMAReset				(1<<6)
132#define FIFOReset				(1<<7)
133#define ClearAll				0xf8
134
135#define Group_1_FIFO			8	/* W */
136#define Group_2_FIFO			12	/* W */
137
138#define Transfer_Count			20
139#define Chip_ID_D			24
140#define Chip_ID_I			25
141#define Chip_ID_O			26
142#define Chip_Version			27
143#define Port_IO(x)			(28+(x))
144#define Port_Pin_Directions(x)		(32+(x))
145#define Port_Pin_Mask(x)		(36+(x))
146#define Port_Pin_Polarities(x)		(40+(x))
147
148#define Master_Clock_Routing		45
149#define RTSIClocking(x)			(((x)&3)<<4)
150
151#define Group_1_Second_Clear		46	/* W */
152#define Group_2_Second_Clear		47	/* W */
153#define ClearExpired				(1<<0)
154
155#define Port_Pattern(x)			(48+(x))
156
157#define Data_Path			64
158#define FIFOEnableA		(1<<0)
159#define FIFOEnableB		(1<<1)
160#define FIFOEnableC		(1<<2)
161#define FIFOEnableD		(1<<3)
162#define Funneling(x)		(((x)&3)<<4)
163#define GroupDirection	(1<<7)
164
165#define Protocol_Register_1		65
166#define OpMode				Protocol_Register_1
167#define RunMode(x)		((x)&7)
168#define Numbered		(1<<3)
169
170#define Protocol_Register_2		66
171#define ClockReg			Protocol_Register_2
172#define ClockLine(x)		(((x)&3)<<5)
173#define InvertStopTrig	(1<<7)
174#define DataLatching(x)       (((x)&3)<<5)
175
176#define Protocol_Register_3		67
177#define Sequence			Protocol_Register_3
178
179#define Protocol_Register_14		68	/* 16 bit */
180#define ClockSpeed			Protocol_Register_14
181
182#define Protocol_Register_4		70
183#define ReqReg				Protocol_Register_4
184#define ReqConditioning(x)	(((x)&7)<<3)
185
186#define Protocol_Register_5		71
187#define BlockMode			Protocol_Register_5
188
189#define FIFO_Control			72
190#define ReadyLevel(x)		((x)&7)
191
192#define Protocol_Register_6		73
193#define LinePolarities			Protocol_Register_6
194#define InvertAck		(1<<0)
195#define InvertReq		(1<<1)
196#define InvertClock		(1<<2)
197#define InvertSerial		(1<<3)
198#define OpenAck		(1<<4)
199#define OpenClock		(1<<5)
200
201#define Protocol_Register_7		74
202#define AckSer				Protocol_Register_7
203#define AckLine(x)		(((x)&3)<<2)
204#define ExchangePins		(1<<7)
205
206#define Interrupt_Control		75
207  /* bits same as flags */
208
209#define DMA_Line_Control_Group1		76
210#define DMA_Line_Control_Group2		108
211/* channel zero is none */
212static inline unsigned primary_DMAChannel_bits(unsigned channel)
213{
214	return channel & 0x3;
215}
216
217static inline unsigned secondary_DMAChannel_bits(unsigned channel)
218{
219	return (channel << 2) & 0xc;
220}
221
222#define Transfer_Size_Control		77
223#define TransferWidth(x)	((x)&3)
224#define TransferLength(x)	(((x)&3)<<3)
225#define RequireRLevel		(1<<5)
226
227#define Protocol_Register_15		79
228#define DAQOptions			Protocol_Register_15
229#define StartSource(x)			((x)&0x3)
230#define InvertStart				(1<<2)
231#define StopSource(x)				(((x)&0x3)<<3)
232#define ReqStart				(1<<6)
233#define PreStart				(1<<7)
234
235#define Pattern_Detection		81
236#define DetectionMethod			(1<<0)
237#define InvertMatch				(1<<1)
238#define IE_Pattern_Detection			(1<<2)
239
240#define Protocol_Register_9		82
241#define ReqDelay			Protocol_Register_9
242
243#define Protocol_Register_10		83
244#define ReqNotDelay			Protocol_Register_10
245
246#define Protocol_Register_11		84
247#define AckDelay			Protocol_Register_11
248
249#define Protocol_Register_12		85
250#define AckNotDelay			Protocol_Register_12
251
252#define Protocol_Register_13		86
253#define Data1Delay			Protocol_Register_13
254
255#define Protocol_Register_8		88	/* 32 bit */
256#define StartDelay			Protocol_Register_8
257
258enum pci_6534_firmware_registers {	/* 16 bit */
259	Firmware_Control_Register = 0x100,
260	Firmware_Status_Register = 0x104,
261	Firmware_Data_Register = 0x108,
262	Firmware_Mask_Register = 0x10c,
263	Firmware_Debug_Register = 0x110,
264};
265/* main fpga registers (32 bit)*/
266enum pci_6534_fpga_registers {
267	FPGA_Control1_Register = 0x200,
268	FPGA_Control2_Register = 0x204,
269	FPGA_Irq_Mask_Register = 0x208,
270	FPGA_Status_Register = 0x20c,
271	FPGA_Signature_Register = 0x210,
272	FPGA_SCALS_Counter_Register = 0x280,	/*write-clear */
273	FPGA_SCAMS_Counter_Register = 0x284,	/*write-clear */
274	FPGA_SCBLS_Counter_Register = 0x288,	/*write-clear */
275	FPGA_SCBMS_Counter_Register = 0x28c,	/*write-clear */
276	FPGA_Temp_Control_Register = 0x2a0,
277	FPGA_DAR_Register = 0x2a8,
278	FPGA_ELC_Read_Register = 0x2b8,
279	FPGA_ELC_Write_Register = 0x2bc,
280};
281enum FPGA_Control_Bits {
282	FPGA_Enable_Bit = 0x8000,
283};
284
285#define TIMER_BASE 50		/* nanoseconds */
286
287#ifdef USE_DMA
288#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC)
289#else
290#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
291#endif
292
293static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
294static int nidio_detach(struct comedi_device *dev);
295static int ni_pcidio_cancel(struct comedi_device *dev,
296			    struct comedi_subdevice *s);
297
298static struct comedi_driver driver_pcidio = {
299	.driver_name = "ni_pcidio",
300	.module = THIS_MODULE,
301	.attach = nidio_attach,
302	.detach = nidio_detach,
303};
304
305struct nidio_board {
306
307	int dev_id;
308	const char *name;
309	int n_8255;
310	unsigned int is_diodaq:1;
311	unsigned int uses_firmware:1;
312};
313
314static const struct nidio_board nidio_boards[] = {
315	{
316	 .dev_id = 0x1150,
317	 .name = "pci-dio-32hs",
318	 .n_8255 = 0,
319	 .is_diodaq = 1,
320	 },
321	{
322	 .dev_id = 0x1320,
323	 .name = "pxi-6533",
324	 .n_8255 = 0,
325	 .is_diodaq = 1,
326	 },
327	{
328	 .dev_id = 0x12b0,
329	 .name = "pci-6534",
330	 .n_8255 = 0,
331	 .is_diodaq = 1,
332	 .uses_firmware = 1,
333	 },
334	{
335	 .dev_id = 0x0160,
336	 .name = "pci-dio-96",
337	 .n_8255 = 4,
338	 .is_diodaq = 0,
339	 },
340	{
341	 .dev_id = 0x1630,
342	 .name = "pci-dio-96b",
343	 .n_8255 = 4,
344	 .is_diodaq = 0,
345	 },
346	{
347	 .dev_id = 0x13c0,
348	 .name = "pxi-6508",
349	 .n_8255 = 4,
350	 .is_diodaq = 0,
351	 },
352	{
353	 .dev_id = 0x0400,
354	 .name = "pci-6503",
355	 .n_8255 = 1,
356	 .is_diodaq = 0,
357	 },
358	{
359	 .dev_id = 0x1250,
360	 .name = "pci-6503b",
361	 .n_8255 = 1,
362	 .is_diodaq = 0,
363	 },
364	{
365	 .dev_id = 0x17d0,
366	 .name = "pci-6503x",
367	 .n_8255 = 1,
368	 .is_diodaq = 0,
369	 },
370	{
371	 .dev_id = 0x1800,
372	 .name = "pxi-6503",
373	 .n_8255 = 1,
374	 .is_diodaq = 0,
375	 },
376};
377
378#define n_nidio_boards ARRAY_SIZE(nidio_boards)
379#define this_board ((const struct nidio_board *)dev->board_ptr)
380
381static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
382	{
383	PCI_VENDOR_ID_NATINST, 0x1150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
384	PCI_VENDOR_ID_NATINST, 0x1320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
385	PCI_VENDOR_ID_NATINST, 0x12b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
386	PCI_VENDOR_ID_NATINST, 0x0160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
387	PCI_VENDOR_ID_NATINST, 0x1630, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
388	PCI_VENDOR_ID_NATINST, 0x13c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
389	PCI_VENDOR_ID_NATINST, 0x0400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
390	PCI_VENDOR_ID_NATINST, 0x1250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
391	PCI_VENDOR_ID_NATINST, 0x17d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
392	PCI_VENDOR_ID_NATINST, 0x1800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
393	0}
394};
395
396MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
397
398struct nidio96_private {
399	struct mite_struct *mite;
400	int boardtype;
401	int dio;
402	unsigned short OpModeBits;
403	struct mite_channel *di_mite_chan;
404	struct mite_dma_descriptor_ring *di_mite_ring;
405	spinlock_t mite_channel_lock;
406};
407#define devpriv ((struct nidio96_private *)dev->private)
408
409static int ni_pcidio_cmdtest(struct comedi_device *dev,
410			     struct comedi_subdevice *s,
411			     struct comedi_cmd *cmd);
412static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
413static int ni_pcidio_inttrig(struct comedi_device *dev,
414			     struct comedi_subdevice *s, unsigned int trignum);
415static int nidio_find_device(struct comedi_device *dev, int bus, int slot);
416static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
417static int setup_mite_dma(struct comedi_device *dev,
418			  struct comedi_subdevice *s);
419
420#ifdef DEBUG_FLAGS
421static void ni_pcidio_print_flags(unsigned int flags);
422static void ni_pcidio_print_status(unsigned int status);
423#else
424#define ni_pcidio_print_flags(x)
425#define ni_pcidio_print_status(x)
426#endif
427
428static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
429{
430	unsigned long flags;
431
432	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
433	BUG_ON(devpriv->di_mite_chan);
434	devpriv->di_mite_chan =
435	    mite_request_channel_in_range(devpriv->mite,
436					  devpriv->di_mite_ring, 1, 2);
437	if (devpriv->di_mite_chan == NULL) {
438		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
439		comedi_error(dev, "failed to reserve mite dma channel.");
440		return -EBUSY;
441	}
442	writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
443	       secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
444	       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
445	mmiowb();
446	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
447	return 0;
448}
449
450static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
451{
452	unsigned long flags;
453
454	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
455	if (devpriv->di_mite_chan) {
456		mite_dma_disarm(devpriv->di_mite_chan);
457		mite_dma_reset(devpriv->di_mite_chan);
458		mite_release_channel(devpriv->di_mite_chan);
459		devpriv->di_mite_chan = NULL;
460		writeb(primary_DMAChannel_bits(0) |
461		       secondary_DMAChannel_bits(0),
462		       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
463		mmiowb();
464	}
465	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
466}
467
468static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
469{
470	if (dir) {
471		writeb(data, (void *)(iobase + port));
472		return 0;
473	} else {
474		return readb((void *)(iobase + port));
475	}
476}
477
478void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
479{
480	if (s->
481	    async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
482			     COMEDI_CB_OVERFLOW)) {
483		ni_pcidio_cancel(dev, s);
484	}
485	comedi_event(dev, s);
486}
487
488static irqreturn_t nidio_interrupt(int irq, void *d)
489{
490	struct comedi_device *dev = d;
491	struct comedi_subdevice *s = dev->subdevices;
492	struct comedi_async *async = s->async;
493	struct mite_struct *mite = devpriv->mite;
494
495	/* int i, j; */
496	long int AuxData = 0;
497	short data1 = 0;
498	short data2 = 0;
499	int flags;
500	int status;
501	int work = 0;
502	unsigned int m_status = 0;
503	unsigned long irq_flags;
504
505	/* interrupcions parasites */
506	if (dev->attached == 0) {
507		/* assume it's from another card */
508		return IRQ_NONE;
509	}
510
511	status = readb(devpriv->mite->daq_io_addr +
512		       Interrupt_And_Window_Status);
513	flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
514
515	DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n",
516		status, flags);
517	ni_pcidio_print_flags(flags);
518	ni_pcidio_print_status(status);
519
520	/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
521	/* printk("buf[4096]=%08x\n",
522	       *(unsigned int *)(async->prealloc_buf+4096)); */
523
524	spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
525	if (devpriv->di_mite_chan)
526		m_status = mite_get_status(devpriv->di_mite_chan);
527#ifdef MITE_DEBUG
528	mite_print_chsr(m_status);
529#endif
530	/* printk("mite_bytes_transferred: %d\n",
531	       mite_bytes_transferred(mite,DI_DMA_CHAN)); */
532
533	/* mite_dump_regs(mite); */
534	if (m_status & CHSR_INT) {
535		if (m_status & CHSR_LINKC) {
536			writel(CHOR_CLRLC,
537			       mite->mite_io_addr +
538			       MITE_CHOR(devpriv->di_mite_chan->channel));
539			mite_sync_input_dma(devpriv->di_mite_chan, s->async);
540			/* XXX need to byteswap */
541		}
542		if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY |
543				 CHSR_DRQ1 | CHSR_MRDY)) {
544			DPRINTK("unknown mite interrupt, disabling IRQ\n");
545			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
546			disable_irq(dev->irq);
547		}
548	}
549	spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags);
550
551	while (status & DataLeft) {
552		work++;
553		if (work > 20) {
554			DPRINTK("too much work in interrupt\n");
555			writeb(0x00,
556			       devpriv->mite->daq_io_addr +
557			       Master_DMA_And_Interrupt_Control);
558			break;
559		}
560
561		flags &= IntEn;
562
563		if (flags & TransferReady) {
564			/* DPRINTK("TransferReady\n"); */
565			while (flags & TransferReady) {
566				work++;
567				if (work > 100) {
568					DPRINTK("too much work in interrupt\n");
569					writeb(0x00,
570					       devpriv->mite->daq_io_addr +
571					       Master_DMA_And_Interrupt_Control
572					      );
573					goto out;
574				}
575				AuxData =
576				    readl(devpriv->mite->daq_io_addr +
577					  Group_1_FIFO);
578				data1 = AuxData & 0xffff;
579				data2 = (AuxData & 0xffff0000) >> 16;
580				comedi_buf_put(async, data1);
581				comedi_buf_put(async, data2);
582				/* DPRINTK("read:%d, %d\n",data1,data2); */
583				flags = readb(devpriv->mite->daq_io_addr +
584					      Group_1_Flags);
585			}
586			/* DPRINTK("buf_int_count: %d\n",
587				async->buf_int_count); */
588			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",
589				IntEn,flags,status); */
590			/* ni_pcidio_print_flags(flags); */
591			/* ni_pcidio_print_status(status); */
592			async->events |= COMEDI_CB_BLOCK;
593		}
594
595		if (flags & CountExpired) {
596			DPRINTK("CountExpired\n");
597			writeb(ClearExpired,
598			       devpriv->mite->daq_io_addr +
599			       Group_1_Second_Clear);
600			async->events |= COMEDI_CB_EOA;
601
602			writeb(0x00, devpriv->mite->daq_io_addr + OpMode);
603			break;
604		} else if (flags & Waited) {
605			DPRINTK("Waited\n");
606			writeb(ClearWaited,
607			       devpriv->mite->daq_io_addr +
608			       Group_1_First_Clear);
609			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
610			break;
611		} else if (flags & PrimaryTC) {
612			DPRINTK("PrimaryTC\n");
613			writeb(ClearPrimaryTC,
614			       devpriv->mite->daq_io_addr +
615			       Group_1_First_Clear);
616			async->events |= COMEDI_CB_EOA;
617		} else if (flags & SecondaryTC) {
618			DPRINTK("SecondaryTC\n");
619			writeb(ClearSecondaryTC,
620			       devpriv->mite->daq_io_addr +
621			       Group_1_First_Clear);
622			async->events |= COMEDI_CB_EOA;
623		}
624#if 0
625		else {
626			printk("ni_pcidio: unknown interrupt\n");
627			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
628			writeb(0x00,
629			       devpriv->mite->daq_io_addr +
630			       Master_DMA_And_Interrupt_Control);
631		}
632#endif
633		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
634		status = readb(devpriv->mite->daq_io_addr +
635			       Interrupt_And_Window_Status);
636		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,"
637			"status=0x%02x\n", IntEn, flags, status); */
638		/* ni_pcidio_print_flags(flags); */
639		/* ni_pcidio_print_status(status); */
640	}
641
642out:
643	ni_pcidio_event(dev, s);
644#if 0
645	if (!tag) {
646		writeb(0x03,
647		       devpriv->mite->daq_io_addr +
648		       Master_DMA_And_Interrupt_Control);
649	}
650#endif
651	return IRQ_HANDLED;
652}
653
654#ifdef DEBUG_FLAGS
655static const char *const flags_strings[] = {
656	"TransferReady", "CountExpired", "2", "3",
657	"4", "Waited", "PrimaryTC", "SecondaryTC",
658};
659
660static void ni_pcidio_print_flags(unsigned int flags)
661{
662	int i;
663
664	printk(KERN_INFO "group_1_flags:");
665	for (i = 7; i >= 0; i--) {
666		if (flags & (1 << i))
667			printk(" %s", flags_strings[i]);
668	}
669	printk("\n");
670}
671
672static char *status_strings[] = {
673	"DataLeft1", "Reserved1", "Req1", "StopTrig1",
674	"DataLeft2", "Reserved2", "Req2", "StopTrig2",
675};
676
677static void ni_pcidio_print_status(unsigned int flags)
678{
679	int i;
680
681	printk(KERN_INFO "group_status:");
682	for (i = 7; i >= 0; i--) {
683		if (flags & (1 << i))
684			printk(" %s", status_strings[i]);
685	}
686	printk("\n");
687}
688#endif
689
690#ifdef unused
691static void debug_int(struct comedi_device *dev)
692{
693	int a, b;
694	static int n_int = 0;
695	struct timeval tv;
696
697	do_gettimeofday(&tv);
698	a = readb(devpriv->mite->daq_io_addr + Group_Status);
699	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
700
701	if (n_int < 10) {
702		DPRINTK("status 0x%02x flags 0x%02x time %06d\n", a, b,
703			(int)tv.tv_usec);
704	}
705
706	while (b & 1) {
707		writew(0xff, devpriv->mite->daq_io_addr + Group_1_FIFO);
708		b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
709	}
710
711	b = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
712
713	if (n_int < 10) {
714		DPRINTK("new status 0x%02x\n", b);
715		n_int++;
716	}
717}
718#endif
719
720static int ni_pcidio_insn_config(struct comedi_device *dev,
721				 struct comedi_subdevice *s,
722				 struct comedi_insn *insn, unsigned int *data)
723{
724	if (insn->n != 1)
725		return -EINVAL;
726	switch (data[0]) {
727	case INSN_CONFIG_DIO_OUTPUT:
728		s->io_bits |= 1 << CR_CHAN(insn->chanspec);
729		break;
730	case INSN_CONFIG_DIO_INPUT:
731		s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
732		break;
733	case INSN_CONFIG_DIO_QUERY:
734		data[1] =
735		    (s->
736		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
737		    COMEDI_INPUT;
738		return insn->n;
739		break;
740	default:
741		return -EINVAL;
742	}
743	writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
744
745	return 1;
746}
747
748static int ni_pcidio_insn_bits(struct comedi_device *dev,
749			       struct comedi_subdevice *s,
750			       struct comedi_insn *insn, unsigned int *data)
751{
752	if (insn->n != 2)
753		return -EINVAL;
754	if (data[0]) {
755		s->state &= ~data[0];
756		s->state |= (data[0] & data[1]);
757		writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
758	}
759	data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
760
761	return 2;
762}
763
764static int ni_pcidio_cmdtest(struct comedi_device *dev,
765			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
766{
767	int err = 0;
768	int tmp;
769
770	/* step 1: make sure trigger sources are trivially valid */
771
772	tmp = cmd->start_src;
773	cmd->start_src &= TRIG_NOW | TRIG_INT;
774	if (!cmd->start_src || tmp != cmd->start_src)
775		err++;
776
777	tmp = cmd->scan_begin_src;
778	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
779	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
780		err++;
781
782	tmp = cmd->convert_src;
783	cmd->convert_src &= TRIG_NOW;
784	if (!cmd->convert_src || tmp != cmd->convert_src)
785		err++;
786
787	tmp = cmd->scan_end_src;
788	cmd->scan_end_src &= TRIG_COUNT;
789	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
790		err++;
791
792	tmp = cmd->stop_src;
793	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
794	if (!cmd->stop_src || tmp != cmd->stop_src)
795		err++;
796
797	if (err)
798		return 1;
799
800	/* step 2: make sure trigger sources are unique and mutually
801	compatible */
802
803	/* note that mutual compatibility is not an issue here */
804	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
805		err++;
806	if (cmd->scan_begin_src != TRIG_TIMER &&
807	    cmd->scan_begin_src != TRIG_EXT)
808		err++;
809
810	if (err)
811		return 2;
812
813	/* step 3: make sure arguments are trivially compatible */
814
815	if (cmd->start_arg != 0) {
816		/* same for both TRIG_INT and TRIG_NOW */
817		cmd->start_arg = 0;
818		err++;
819	}
820#define MAX_SPEED	(TIMER_BASE)	/* in nanoseconds */
821
822	if (cmd->scan_begin_src == TRIG_TIMER) {
823		if (cmd->scan_begin_arg < MAX_SPEED) {
824			cmd->scan_begin_arg = MAX_SPEED;
825			err++;
826		}
827		/* no minumum speed */
828	} else {
829		/* TRIG_EXT */
830		/* should be level/edge, hi/lo specification here */
831		if (cmd->scan_begin_arg != 0) {
832			cmd->scan_begin_arg = 0;
833			err++;
834		}
835	}
836	if (cmd->convert_arg != 0) {
837		cmd->convert_arg = 0;
838		err++;
839	}
840
841	if (cmd->scan_end_arg != cmd->chanlist_len) {
842		cmd->scan_end_arg = cmd->chanlist_len;
843		err++;
844	}
845	if (cmd->stop_src == TRIG_COUNT) {
846		/* no limit */
847	} else {
848		/* TRIG_NONE */
849		if (cmd->stop_arg != 0) {
850			cmd->stop_arg = 0;
851			err++;
852		}
853	}
854
855	if (err)
856		return 3;
857
858	/* step 4: fix up any arguments */
859
860	if (cmd->scan_begin_src == TRIG_TIMER) {
861		tmp = cmd->scan_begin_arg;
862		ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
863				      cmd->flags & TRIG_ROUND_MASK);
864		if (tmp != cmd->scan_begin_arg)
865			err++;
866	}
867
868	if (err)
869		return 4;
870
871	return 0;
872}
873
874static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
875{
876	int divider, base;
877
878	base = TIMER_BASE;
879
880	switch (round_mode) {
881	case TRIG_ROUND_NEAREST:
882	default:
883		divider = (*nanosec + base / 2) / base;
884		break;
885	case TRIG_ROUND_DOWN:
886		divider = (*nanosec) / base;
887		break;
888	case TRIG_ROUND_UP:
889		divider = (*nanosec + base - 1) / base;
890		break;
891	}
892
893	*nanosec = base * divider;
894	return divider;
895}
896
897static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
898{
899	struct comedi_cmd *cmd = &s->async->cmd;
900
901	/* XXX configure ports for input */
902	writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
903
904	if (1) {
905		/* enable fifos A B C D */
906		writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path);
907
908		/* set transfer width a 32 bits */
909		writeb(TransferWidth(0) | TransferLength(0),
910		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
911	} else {
912		writeb(0x03, devpriv->mite->daq_io_addr + Data_Path);
913		writeb(TransferWidth(3) | TransferLength(0),
914		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
915	}
916
917	/* protocol configuration */
918	if (cmd->scan_begin_src == TRIG_TIMER) {
919		/* page 4-5, "input with internal REQs" */
920		writeb(0, devpriv->mite->daq_io_addr + OpMode);
921		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
922		writeb(1, devpriv->mite->daq_io_addr + Sequence);
923		writeb(0x04, devpriv->mite->daq_io_addr + ReqReg);
924		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
925		writeb(3, devpriv->mite->daq_io_addr + LinePolarities);
926		writeb(0xc0, devpriv->mite->daq_io_addr + AckSer);
927		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
928					     TRIG_ROUND_NEAREST),
929		       devpriv->mite->daq_io_addr + StartDelay);
930		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
931		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
932		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
933		writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay);
934		writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay);
935		/* manual, page 4-5: ClockSpeed comment is incorrectly listed
936		 * on DAQOptions */
937		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
938		writeb(0, devpriv->mite->daq_io_addr + DAQOptions);
939	} else {
940		/* TRIG_EXT */
941		/* page 4-5, "input with external REQs" */
942		writeb(0, devpriv->mite->daq_io_addr + OpMode);
943		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
944		writeb(0, devpriv->mite->daq_io_addr + Sequence);
945		writeb(0x00, devpriv->mite->daq_io_addr + ReqReg);
946		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
947		writeb(0, devpriv->mite->daq_io_addr + LinePolarities);
948		writeb(0x00, devpriv->mite->daq_io_addr + AckSer);
949		writel(1, devpriv->mite->daq_io_addr + StartDelay);
950		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
951		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
952		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
953		writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay);
954		writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay);
955		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
956		writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions);
957	}
958
959	if (cmd->stop_src == TRIG_COUNT) {
960		writel(cmd->stop_arg,
961		       devpriv->mite->daq_io_addr + Transfer_Count);
962	} else {
963		/* XXX */
964	}
965
966#ifdef USE_DMA
967	writeb(ClearPrimaryTC | ClearSecondaryTC,
968	       devpriv->mite->daq_io_addr + Group_1_First_Clear);
969
970	{
971		int retval = setup_mite_dma(dev, s);
972		if (retval)
973			return retval;
974	}
975#else
976	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
977#endif
978	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2);
979
980	/* clear and enable interrupts */
981	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
982	/* writeb(ClearExpired,
983	       devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
984
985	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
986	writeb(0x03,
987	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
988
989	if (cmd->stop_src == TRIG_NONE) {
990		devpriv->OpModeBits = DataLatching(0) | RunMode(7);
991	} else {		/* TRIG_TIMER */
992		devpriv->OpModeBits = Numbered | RunMode(7);
993	}
994	if (cmd->start_src == TRIG_NOW) {
995		/* start */
996		writeb(devpriv->OpModeBits,
997		       devpriv->mite->daq_io_addr + OpMode);
998		s->async->inttrig = NULL;
999	} else {
1000		/* TRIG_INT */
1001		s->async->inttrig = ni_pcidio_inttrig;
1002	}
1003
1004	DPRINTK("ni_pcidio: command started\n");
1005	return 0;
1006}
1007
1008static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1009{
1010	int retval;
1011
1012	retval = ni_pcidio_request_di_mite_channel(dev);
1013	if (retval)
1014		return retval;
1015
1016	devpriv->di_mite_chan->dir = COMEDI_INPUT;
1017
1018	mite_prep_dma(devpriv->di_mite_chan, 32, 32);
1019
1020	mite_dma_arm(devpriv->di_mite_chan);
1021	return 0;
1022}
1023
1024static int ni_pcidio_inttrig(struct comedi_device *dev,
1025			     struct comedi_subdevice *s, unsigned int trignum)
1026{
1027	if (trignum != 0)
1028		return -EINVAL;
1029
1030	writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode);
1031	s->async->inttrig = NULL;
1032
1033	return 1;
1034}
1035
1036static int ni_pcidio_cancel(struct comedi_device *dev,
1037			    struct comedi_subdevice *s)
1038{
1039	writeb(0x00,
1040	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
1041	ni_pcidio_release_di_mite_channel(dev);
1042
1043	return 0;
1044}
1045
1046static int ni_pcidio_change(struct comedi_device *dev,
1047			    struct comedi_subdevice *s, unsigned long new_size)
1048{
1049	int ret;
1050
1051	ret = mite_buf_change(devpriv->di_mite_ring, s->async);
1052	if (ret < 0)
1053		return ret;
1054
1055	memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
1056
1057	return 0;
1058}
1059
1060static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
1061			      u8 *data, int data_len)
1062{
1063	static const int timeout = 1000;
1064	int i, j;
1065	writew(0x80 | fpga_index,
1066	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1067	writew(0xc0 | fpga_index,
1068	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1069	for (i = 0;
1070	     (readw(devpriv->mite->daq_io_addr +
1071		    Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) {
1072		udelay(1);
1073	}
1074	if (i == timeout) {
1075		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
1076		       "waiting for status 0x2\n", fpga_index);
1077		return -EIO;
1078	}
1079	writew(0x80 | fpga_index,
1080	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
1081	for (i = 0;
1082	     readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) !=
1083	     0x3 && i < timeout; ++i) {
1084		udelay(1);
1085	}
1086	if (i == timeout) {
1087		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
1088		       "waiting for status 0x3\n", fpga_index);
1089		return -EIO;
1090	}
1091	for (j = 0; j + 1 < data_len;) {
1092		unsigned int value = data[j++];
1093		value |= data[j++] << 8;
1094		writew(value,
1095		       devpriv->mite->daq_io_addr + Firmware_Data_Register);
1096		for (i = 0;
1097		     (readw(devpriv->mite->daq_io_addr +
1098			    Firmware_Status_Register) & 0x2) == 0
1099		     && i < timeout; ++i) {
1100			udelay(1);
1101		}
1102		if (i == timeout) {
1103			printk("ni_pcidio: failed to load word into fpga %i\n",
1104			       fpga_index);
1105			return -EIO;
1106		}
1107		if (need_resched())
1108			schedule();
1109	}
1110	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1111	return 0;
1112}
1113
1114static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
1115{
1116	return pci_6534_load_fpga(dev, fpga_index, NULL, 0);
1117}
1118
1119static int pci_6534_reset_fpgas(struct comedi_device *dev)
1120{
1121	int ret;
1122	int i;
1123	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
1124	for (i = 0; i < 3; ++i) {
1125		ret = pci_6534_reset_fpga(dev, i);
1126		if (ret < 0)
1127			break;
1128	}
1129	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register);
1130	return ret;
1131}
1132
1133static void pci_6534_init_main_fpga(struct comedi_device *dev)
1134{
1135	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
1136	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
1137	writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
1138	writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register);
1139	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register);
1140	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
1141}
1142
1143static int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
1144{
1145	int ret;
1146	void *main_fpga_data, *scarab_a_data, *scarab_b_data;
1147	int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len;
1148
1149	if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0)
1150		return 0;
1151	ret = pci_6534_reset_fpgas(dev);
1152	if (ret < 0)
1153		return ret;
1154	main_fpga_data = comedi_aux_data(options, 0);
1155	main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
1156	ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len);
1157	if (ret < 0)
1158		return ret;
1159	pci_6534_init_main_fpga(dev);
1160	scarab_a_data = comedi_aux_data(options, 1);
1161	scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
1162	ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len);
1163	if (ret < 0)
1164		return ret;
1165	scarab_b_data = comedi_aux_data(options, 2);
1166	scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
1167	ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len);
1168	if (ret < 0)
1169		return ret;
1170	return 0;
1171}
1172
1173static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1174{
1175	struct comedi_subdevice *s;
1176	int i;
1177	int ret;
1178	int n_subdevices;
1179	unsigned int irq;
1180
1181	printk(KERN_INFO "comedi%d: nidio:", dev->minor);
1182
1183	ret = alloc_private(dev, sizeof(struct nidio96_private));
1184	if (ret < 0)
1185		return ret;
1186	spin_lock_init(&devpriv->mite_channel_lock);
1187
1188	ret = nidio_find_device(dev, it->options[0], it->options[1]);
1189	if (ret < 0)
1190		return ret;
1191
1192	ret = mite_setup(devpriv->mite);
1193	if (ret < 0) {
1194		printk(KERN_WARNING "error setting up mite\n");
1195		return ret;
1196	}
1197	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
1198	devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
1199	if (devpriv->di_mite_ring == NULL)
1200		return -ENOMEM;
1201
1202	dev->board_name = this_board->name;
1203	irq = mite_irq(devpriv->mite);
1204	printk(KERN_INFO " %s", dev->board_name);
1205	if (this_board->uses_firmware) {
1206		ret = pci_6534_upload_firmware(dev, it->options);
1207		if (ret < 0)
1208			return ret;
1209	}
1210	if (!this_board->is_diodaq)
1211		n_subdevices = this_board->n_8255;
1212	else
1213		n_subdevices = 1;
1214
1215	ret = alloc_subdevices(dev, n_subdevices);
1216	if (ret < 0)
1217		return ret;
1218
1219	if (!this_board->is_diodaq) {
1220		for (i = 0; i < this_board->n_8255; i++) {
1221			subdev_8255_init(dev, dev->subdevices + i,
1222					 nidio96_8255_cb,
1223					 (unsigned long)(devpriv->mite->
1224							 daq_io_addr +
1225							 NIDIO_8255_BASE(i)));
1226		}
1227	} else {
1228
1229		printk(KERN_INFO " rev=%d",
1230		       readb(devpriv->mite->daq_io_addr + Chip_Version));
1231
1232		s = dev->subdevices + 0;
1233
1234		dev->read_subdev = s;
1235		s->type = COMEDI_SUBD_DIO;
1236		s->subdev_flags =
1237		    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
1238		    SDF_CMD_READ;
1239		s->n_chan = 32;
1240		s->range_table = &range_digital;
1241		s->maxdata = 1;
1242		s->insn_config = &ni_pcidio_insn_config;
1243		s->insn_bits = &ni_pcidio_insn_bits;
1244		s->do_cmd = &ni_pcidio_cmd;
1245		s->do_cmdtest = &ni_pcidio_cmdtest;
1246		s->cancel = &ni_pcidio_cancel;
1247		s->len_chanlist = 32;	/* XXX */
1248		s->buf_change = &ni_pcidio_change;
1249		s->async_dma_dir = DMA_BIDIRECTIONAL;
1250
1251		writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
1252		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
1253		writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0));
1254
1255		/* disable interrupts on board */
1256		writeb(0x00,
1257		       devpriv->mite->daq_io_addr +
1258		       Master_DMA_And_Interrupt_Control);
1259
1260		ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
1261				  "ni_pcidio", dev);
1262		if (ret < 0)
1263			printk(KERN_WARNING " irq not available");
1264
1265		dev->irq = irq;
1266	}
1267
1268	printk("\n");
1269
1270	return 0;
1271}
1272
1273static int nidio_detach(struct comedi_device *dev)
1274{
1275	int i;
1276
1277	if (this_board && !this_board->is_diodaq) {
1278		for (i = 0; i < this_board->n_8255; i++)
1279			subdev_8255_cleanup(dev, dev->subdevices + i);
1280	}
1281
1282	if (dev->irq)
1283		free_irq(dev->irq, dev);
1284
1285	if (devpriv) {
1286		if (devpriv->di_mite_ring) {
1287			mite_free_ring(devpriv->di_mite_ring);
1288			devpriv->di_mite_ring = NULL;
1289		}
1290		if (devpriv->mite)
1291			mite_unsetup(devpriv->mite);
1292	}
1293	return 0;
1294}
1295
1296static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
1297{
1298	struct mite_struct *mite;
1299	int i;
1300
1301	for (mite = mite_devices; mite; mite = mite->next) {
1302		if (mite->used)
1303			continue;
1304		if (bus || slot) {
1305			if (bus != mite->pcidev->bus->number ||
1306			    slot != PCI_SLOT(mite->pcidev->devfn))
1307				continue;
1308		}
1309		for (i = 0; i < n_nidio_boards; i++) {
1310			if (mite_device_id(mite) == nidio_boards[i].dev_id) {
1311				dev->board_ptr = nidio_boards + i;
1312				devpriv->mite = mite;
1313
1314				return 0;
1315			}
1316		}
1317	}
1318	printk(KERN_WARNING "no device found\n");
1319	mite_list_devices();
1320	return -EIO;
1321}
1322
1323COMEDI_PCI_INITCLEANUP(driver_pcidio, ni_pcidio_pci_table);
1324