1dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
2dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   comedi/drivers/pcl816.c
3dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
4dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   Author:  Juan Grigera <juan@grigera.com.ar>
54c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	    based on pcl818 by Michal Dobes <dobes@tesnet.cz> and bits of pcl812
6dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   hardware driver for Advantech cards:
8dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    card:   PCL-816, PCL814B
9dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    driver: pcl816
10dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
11dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
12dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraDriver: pcl816
13dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraDescription: Advantech PCL-816 cards, PCL-814
14dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraAuthor: Juan Grigera <juan@grigera.com.ar>
15dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraDevices: [Advantech] PCL-816 (pcl816), PCL-814B (pcl814b)
16dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraStatus: works
17dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraUpdated: Tue,  2 Apr 2002 23:15:21 -0800
18dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
19dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraPCL 816 and 814B have 16 SE/DIFF ADCs, 16 DACs, 16 DI and 16 DO.
20dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraDifferences are at resolution (16 vs 12 bits).
21dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
22dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraThe driver support AI command mode, other subdevices not written.
23dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
24dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraAnalog output and digital input and output are not supported.
25dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
26dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan GrigeraConfiguration Options:
27dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  [0] - IO Base
28dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  [1] - IRQ	(0=disable, 2, 3, 4, 5, 6, 7)
29dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  [2] - DMA	(0=disable, 1, 3)
30dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  [3] - 0, 10=10MHz clock for 8254
314c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	    1= 1MHz clock for 8254
32dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
33dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
34dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
35dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include "../comedidev.h"
36dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
37dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include <linux/ioport.h>
38dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include <linux/mc146818rtc.h>
395a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
40dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include <linux/delay.h>
41845d131e2b363717d8ac8db2c6b4417de8cf10b5Greg Kroah-Hartman#include <linux/io.h>
42dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include <asm/dma.h>
43dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
44dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#include "8253.h"
45dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
46dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define DEBUG(x) x
47dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
4858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* boards constants */
4958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* IO space len */
50dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCLx1x_RANGE 16
51dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* #define outb(x,y)  printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y) */
53dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* INTEL 8254 counters */
55dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CTR0 4
56dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CTR1 5
57dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CTR2 6
5858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: counter read-back register W: counter control */
59dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CTRCTL 7
60dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
6158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: A/D high byte W: A/D range control */
62dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_RANGE 9
6358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* W: clear INT request */
64dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CLRINT 10
6558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: next mux scan channel W: mux scan channel & range control pointer */
66dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_MUX 11
6758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R/W: operation control register */
68dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_CONTROL 12
69dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: return status byte  W: set DMA/IRQ */
71dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_STATUS 13
72dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_STATUS_DRDY_MASK 0x80
73dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: low byte of A/D W: soft A/D trigger */
75dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_AD_LO 8
7658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* R: high byte of A/D W: A/D range control */
77dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define PCL816_AD_HI 9
78dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* type of interrupt handler */
80dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI1_INT 1
81dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI1_DMA 2
82dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI3_INT 4
83dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI3_DMA 5
84dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
85dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI1_DMA_RTC 9
86dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define INT_TYPE_AI3_DMA_RTC 10
87dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
8858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* RTC stuff... */
894c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva#define RTC_IRQ		8
90dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define RTC_IO_EXTENT	0x10
91dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
92dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
93dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#define MAGIC_DMA_WORD 0x5a5a
94dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
959ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_pcl816 = { 8, {
960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       BIP_RANGE(10),
970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       BIP_RANGE(5),
980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       BIP_RANGE(2.5),
990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       BIP_RANGE(1.25),
1000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       UNI_RANGE(10),
1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       UNI_RANGE(5),
1020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       UNI_RANGE(2.5),
1030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       UNI_RANGE(1.25),
1040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       }
105dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera};
1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
1071c7f40d91b99e73ae11056708225058afd0278d7Bill Pembertonstruct pcl816_board {
1081c7f40d91b99e73ae11056708225058afd0278d7Bill Pemberton
10958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	const char *name;	/*  board name */
11058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int n_ranges;		/*  len of range list */
11158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int n_aichan;		/*  num of A/D chans in diferencial mode */
1128c7f9ae856348d75fe79c179fa5c66e1f9717a20Justin P. Mattock	unsigned int ai_ns_min;	/*  minimal allowed delay between samples (in ns) */
11358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int n_aochan;		/*  num of D/A chans */
11458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int n_dichan;		/*  num of DI chans */
11558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int n_dochan;		/*  num of DO chans */
11658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
117bbc9a9916bc1cd997f3bf303e7930d5f3c804d37André Goddard Rosa	const struct comedi_lrange *ao_range_type;	/*  default D/A rangelist */
11858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int io_range;	/*  len of IO space */
11958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int IRQbits;	/*  allowed interrupts */
12058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int DMAbits;	/*  allowed DMA chans */
12158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int ai_maxdata;		/*  maxdata for A/D */
12258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int ao_maxdata;		/*  maxdata for D/A */
12358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int ai_chanlist;	/*  allowed len of channel list A/D */
12458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int ao_chanlist;	/*  allowed len of channel list D/A */
12558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int i8254_osc_base;	/*  1/frequency of on board oscilator in ns */
1261c7f40d91b99e73ae11056708225058afd0278d7Bill Pemberton};
1271c7f40d91b99e73ae11056708225058afd0278d7Bill Pemberton
1281c7f40d91b99e73ae11056708225058afd0278d7Bill Pembertonstatic const struct pcl816_board boardtypes[] = {
129dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	{"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 &range_pcl816, PCLx1x_RANGE,
1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x00fc,		/*  IRQ mask */
1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x0a,			/*  DMA mask */
1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0xffff,		/*  16-bit card */
1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0xffff,		/*  D/A maxdata */
1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 1024,
1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 1,			/*  ao chan list */
1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 100},
138dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	{"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 &range_pcl816, PCLx1x_RANGE,
1400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x00fc,
1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x0a,
1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x3fff,		/* 14 bit card */
1430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 0x3fff,
1440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 1024,
1450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 1,
1460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 100},
147dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera};
148dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1491c7f40d91b99e73ae11056708225058afd0278d7Bill Pemberton#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl816_board))
150fe0ff175329a83de8f9aac7c0b759cde15cb2247Bill Pemberton#define devpriv ((struct pcl816_private *)dev->private)
1511c7f40d91b99e73ae11056708225058afd0278d7Bill Pemberton#define this_board ((const struct pcl816_board *)dev->board_ptr)
152dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_attach(struct comedi_device *dev,
1540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			 struct comedi_devconfig *it);
155da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_detach(struct comedi_device *dev);
156dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
157dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
158b147ed60775ff976f2a0724fa643f9b508bc8652Ravishankar karkala Mallikarjunayyastatic int RTC_lock;	/* RTC lock */
159b147ed60775ff976f2a0724fa643f9b508bc8652Ravishankar karkala Mallikarjunayyastatic int RTC_timer_lock;	/* RTC int lock */
160dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
161dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
162139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_pcl816 = {
16368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "pcl816",
16468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
16568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pcl816_attach,
16668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pcl816_detach,
16768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &boardtypes[0].name,
16868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.num_names = n_boardtypes,
16968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct pcl816_board),
170dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera};
171dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1727114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_pcl816_init_module(void)
1737114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
1747114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_pcl816);
1757114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
1767114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
1777114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_pcl816_cleanup_module(void)
1787114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
1797114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_pcl816);
1807114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
1817114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
1827114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_pcl816_init_module);
1837114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_pcl816_cleanup_module);
184dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
185fe0ff175329a83de8f9aac7c0b759cde15cb2247Bill Pembertonstruct pcl816_private {
186fe0ff175329a83de8f9aac7c0b759cde15cb2247Bill Pemberton
18758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int dma;	/*  used DMA, 0=don't use DMA */
18858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int dma_rtc;		/*  1=RTC used with DMA, 0=no RTC alloc */
189dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
19058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned long rtc_iobase;	/*  RTC port region */
191dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int rtc_iosize;
192dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int rtc_irq;
193dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
19458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
19558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
19658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
19758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
19858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int dmasamplsize;	/*  size in samples hwdmasize[0]/2 */
19958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int last_top_dma;	/*  DMA pointer in last RTC int */
20058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int next_dma_buf;	/*  which DMA buffer will be used next round */
20158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
20258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
20358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton
20458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int ai_scans;	/*  len of scanlist */
20558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned char ai_neverending;	/*  if=1, then we do neverending record (you must use cancel()) */
20658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int irq_free;		/*  1=have allocated IRQ */
20758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int irq_blocked;	/*  1=IRQ now uses any subdev */
208dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
20958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int rtc_irq_blocked;	/*  1=we now do AI with DMA&RTC */
210dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
21158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int irq_was_now_closed;	/*  when IRQ finish, there's stored int816_mode for last interrupt */
21258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int int816_mode;	/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
21358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
21458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	int ai_act_scan;	/*  how many scans we finished */
21558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int ai_act_chanlist[16];	/*  MUX setting for actual AI operations */
21658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int ai_act_chanlist_len;	/*  how long is actual MUX list */
21758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int ai_act_chanlist_pos;	/*  actual position in MUX list */
21813de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott	unsigned int ai_n_chan;		/*  how many channels per scan */
21958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
22058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
221dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
22258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	struct timer_list rtc_irq_timer;	/*  timer for RTC sanity check */
22358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	unsigned long rtc_freq;	/*  RTC int freq */
224dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
225fe0ff175329a83de8f9aac7c0b759cde15cb2247Bill Pemberton};
226fe0ff175329a83de8f9aac7c0b759cde15cb2247Bill Pemberton
227dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
228dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
229dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
23064a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbottstatic int check_channel_list(struct comedi_device *dev,
23164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott			      struct comedi_subdevice *s,
23264a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott			      unsigned int *chanlist, unsigned int chanlen);
23364a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbottstatic void setup_channel_list(struct comedi_device *dev,
23464a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott			       struct comedi_subdevice *s,
23564a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott			       unsigned int *chanlist, unsigned int seglen);
2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_ai_cancel(struct comedi_device *dev,
2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void start_pacer(struct comedi_device *dev, int mode,
2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			unsigned int divisor1, unsigned int divisor2);
240dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
241dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic int set_rtc_irq_bit(unsigned char bit);
242dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
243dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
2440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_ai_cmdtest(struct comedi_device *dev,
2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_cmd *cmd);
247da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
248dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
249dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
250dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
251dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   ANALOG INPUT MODE0, 816 cards, slow version
252dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
2530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_ai_insn_read(struct comedi_device *dev,
2540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
2550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_insn *insn, unsigned int *data)
256dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
257dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int n;
258dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int timeout;
259dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
260dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	DPRINTK("mode 0 analog input\n");
26158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/*  software trigger, DMA and INT off */
262dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CONTROL);
26358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/*  clear INT (conversion end) flag */
264dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CLRINT);
265dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
26658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/*  Set the input channel */
267dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(CR_CHAN(insn->chanspec) & 0xf, dev->iobase + PCL816_MUX);
2684c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/* select gain */
2694c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE);
270dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
271dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	for (n = 0; n < insn->n; n++) {
272dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
273dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb(0, dev->iobase + PCL816_AD_LO);	/* start conversion */
274dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
275dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		timeout = 100;
276dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		while (timeout--) {
277dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (!(inb(dev->iobase + PCL816_STATUS) &
2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      PCL816_STATUS_DRDY_MASK)) {
27958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton				/*  return read value */
280dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				data[n] =
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    ((inb(dev->iobase +
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  PCL816_AD_HI) << 8) |
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     (inb(dev->iobase + PCL816_AD_LO)));
2844c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				/* clear INT (conversion end) flag */
2854c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				outb(0, dev->iobase + PCL816_CLRINT);
286dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				break;
287dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
2885f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
289dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
29058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		/*  Return timeout error */
291dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!timeout) {
292dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			comedi_error(dev, "A/D insn timeout\n");
293dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			data[0] = 0;
2944c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/* clear INT (conversion end) flag */
2954c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			outb(0, dev->iobase + PCL816_CLRINT);
296dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return -EIO;
297dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
298dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
299dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
300dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return n;
301dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
302dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
303dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
304dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
305dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   analog input interrupt mode 1 & 3, 818 cards
306dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   one sample per interrupt version
307dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
308dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
309dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
31071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
31134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 0;
312dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int low, hi;
313dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int timeout = 50;	/* wait max 50us */
314dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
315dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	while (timeout--) {
316dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!(inb(dev->iobase + PCL816_STATUS) &
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      PCL816_STATUS_DRDY_MASK))
318dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			break;
3195f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
320dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
32158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	if (!timeout) {		/*  timeout, bail error */
322dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
323dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
324dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		pcl816_ai_cancel(dev, s);
325dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
326dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_event(dev, s);
327dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return IRQ_HANDLED;
328dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
329dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
330dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
33158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/*  get the sample */
332dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	low = inb(dev->iobase + PCL816_AD_LO);
333dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	hi = inb(dev->iobase + PCL816_AD_HI);
334dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
335dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	comedi_buf_put(s->async, (hi << 8) | low);
336dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
337dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
338dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
339dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len)
340dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_act_chanlist_pos = 0;
341dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
34213de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott	s->async->cur_chan++;
34313de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott	if (s->async->cur_chan >= devpriv->ai_n_chan) {
34413de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott		s->async->cur_chan = 0;
345dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_act_scan++;
346dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
347dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
348dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!devpriv->ai_neverending)
3494c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva					/* all data sampled */
3504c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		if (devpriv->ai_act_scan >= devpriv->ai_scans) {
351dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			/* all data sampled */
352dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			pcl816_ai_cancel(dev, s);
353dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			s->async->events |= COMEDI_CB_EOA;
354dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
355dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	comedi_event(dev, s);
356dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return IRQ_HANDLED;
357dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
358dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
359dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
360dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
361dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   analog input dma mode 1 & 3, 816 cards
362dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
3630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void transfer_from_dma_buf(struct comedi_device *dev,
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_subdevice *s, short *ptr,
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  unsigned int bufptr, unsigned int len)
366dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
367dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int i;
368dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
369dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->async->events = 0;
370dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
371dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	for (i = 0; i < len; i++) {
372dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
373dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_buf_put(s->async, ptr[bufptr++]);
374dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
375dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (++devpriv->ai_act_chanlist_pos >=
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    devpriv->ai_act_chanlist_len) {
377dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->ai_act_chanlist_pos = 0;
37813de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott		}
37913de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott
38013de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott		s->async->cur_chan++;
38113de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott		if (s->async->cur_chan >= devpriv->ai_n_chan) {
38213de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott			s->async->cur_chan = 0;
383dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->ai_act_scan++;
384dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
385dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
386dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!devpriv->ai_neverending)
3874c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva						/*  all data sampled */
3884c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			if (devpriv->ai_act_scan >= devpriv->ai_scans) {
389dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				pcl816_ai_cancel(dev, s);
390dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				s->async->events |= COMEDI_CB_EOA;
391dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				s->async->events |= COMEDI_CB_BLOCK;
392dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				break;
393dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
394dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
395dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
396dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	comedi_event(dev, s);
397dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
398dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
399dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
400dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
40171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
40234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 0;
403dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int len, bufptr, this_dma_buf;
404dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned long dma_flags;
405790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *ptr;
406dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
407dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	disable_dma(devpriv->dma);
408dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	this_dma_buf = devpriv->next_dma_buf;
409dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
4104c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*  switch dma bufs */
4114c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) {
412dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
413dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
414dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		set_dma_mode(devpriv->dma, DMA_MODE_READ);
415dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		dma_flags = claim_dma_lock();
41658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* clear_dma_ff (devpriv->dma); */
417dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		set_dma_addr(devpriv->dma,
4180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     devpriv->hwdmaptr[devpriv->next_dma_buf]);
419dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->dma_runs_to_end) {
420dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			set_dma_count(devpriv->dma,
4210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      devpriv->hwdmasize[devpriv->
4220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							 next_dma_buf]);
423dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		} else {
424dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			set_dma_count(devpriv->dma, devpriv->last_dma_run);
425dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
426dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		release_dma_lock(dma_flags);
427dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		enable_dma(devpriv->dma);
428dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
429dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
430dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->dma_runs_to_end--;
431dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
432dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
4330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	ptr = (short *)devpriv->dmabuf[this_dma_buf];
434dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
435dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr;
436dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	bufptr = devpriv->ai_poll_ptr;
437dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->ai_poll_ptr = 0;
438dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
439dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	transfer_from_dma_buf(dev, s, ptr, bufptr, len);
440dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return IRQ_HANDLED;
441dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
442dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
443dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
444dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
445dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    INT procedure
446dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
44770265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_pcl816(int irq, void *d)
448dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
44971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
450dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	DPRINTK("<I>");
451dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
452dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!dev->attached) {
453dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_error(dev, "premature interrupt");
454dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return IRQ_HANDLED;
455dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
456dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
457dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	switch (devpriv->int816_mode) {
458dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	case INT_TYPE_AI1_DMA:
459dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	case INT_TYPE_AI3_DMA:
460dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return interrupt_pcl816_ai_mode13_dma(irq, d);
461dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	case INT_TYPE_AI1_INT:
462dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	case INT_TYPE_AI3_INT:
463dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return interrupt_pcl816_ai_mode13_int(irq, d);
464dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
465dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
466dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
467dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if ((!dev->irq) | (!devpriv->irq_free) | (!devpriv->irq_blocked) |
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (!devpriv->int816_mode)) {
469dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->irq_was_now_closed) {
470dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->irq_was_now_closed = 0;
47158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton			/*  comedi_error(dev,"last IRQ.."); */
472dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return IRQ_HANDLED;
473dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
474dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_error(dev, "bad IRQ!");
475dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return IRQ_NONE;
476dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
477bbc9a9916bc1cd997f3bf303e7930d5f3c804d37André Goddard Rosa	comedi_error(dev, "IRQ from unknown source!");
478dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return IRQ_NONE;
479dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
480dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
481dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
482dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
483dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   COMMAND MODE
484dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
485da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd)
486dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
4874c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	printk(KERN_INFO "pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
4894c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	printk(KERN_INFO "pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
4914c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	printk(KERN_INFO "pcl816 e=%d stopsrc=%x scanend=%x\n", e,
4924c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	       cmd->stop_src, cmd->scan_end_src);
4934c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	printk(KERN_INFO "pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
4944c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	       e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
495dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
496dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
497dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
498dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
499dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
5000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_ai_cmdtest(struct comedi_device *dev,
5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
502dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
503dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int err = 0;
50448b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott	int tmp, divisor1 = 0, divisor2 = 0;
505dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5064c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	DEBUG(printk(KERN_INFO "pcl816 pcl812_ai_cmdtest\n");
5074c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	      pcl816_cmdtest_out(-1, cmd);
5084c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	     );
509dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
510dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* step 1: make sure trigger sources are trivially valid */
511dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	tmp = cmd->start_src;
512dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	cmd->start_src &= TRIG_NOW;
513dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!cmd->start_src || tmp != cmd->start_src)
514dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
515dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
516dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	tmp = cmd->scan_begin_src;
517dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	cmd->scan_begin_src &= TRIG_FOLLOW;
518dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
519dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
520dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
521efdf83c1763156220a74c8f2755c1a6fa1e1c26bIan Abbott	tmp = cmd->convert_src;
522efdf83c1763156220a74c8f2755c1a6fa1e1c26bIan Abbott	cmd->convert_src &= TRIG_EXT | TRIG_TIMER;
523efdf83c1763156220a74c8f2755c1a6fa1e1c26bIan Abbott	if (!cmd->convert_src || tmp != cmd->convert_src)
524dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
525dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
526dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	tmp = cmd->scan_end_src;
527dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	cmd->scan_end_src &= TRIG_COUNT;
528dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
529dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
530dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
531dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	tmp = cmd->stop_src;
532dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
533dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!cmd->stop_src || tmp != cmd->stop_src)
534dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
535dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5364c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (err)
537dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 1;
538dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5394c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
5404c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*
5414c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	 * step 2: make sure trigger sources
5424c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	 * are unique and mutually compatible
5434c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	 */
544dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
545dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->start_src != TRIG_NOW) {
546dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->start_src = TRIG_NOW;
547dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
548dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
549dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
550dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_begin_src != TRIG_FOLLOW) {
551dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->scan_begin_src = TRIG_FOLLOW;
552dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
553dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
554dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
555dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_TIMER) {
556dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->convert_src = TRIG_TIMER;
557dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
558dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
559dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
560dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_end_src != TRIG_COUNT) {
561dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->scan_end_src = TRIG_COUNT;
562dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
563dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
564dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
565dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
566dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
567dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
5684c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (err)
569dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 2;
5704c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
571dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
572dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* step 3: make sure arguments are trivially compatible */
573dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->start_arg != 0) {
574dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->start_arg = 0;
575dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
576dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
577dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
578dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_begin_arg != 0) {
579dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->scan_begin_arg = 0;
580dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
581dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
582dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->convert_src == TRIG_TIMER) {
583dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (cmd->convert_arg < this_board->ai_ns_min) {
584dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->convert_arg = this_board->ai_ns_min;
585dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			err++;
586dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
587dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {		/* TRIG_EXT */
588dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (cmd->convert_arg != 0) {
589dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->convert_arg = 0;
590dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			err++;
591dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
592dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
593dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
594dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_end_arg != cmd->chanlist_len) {
595dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		cmd->scan_end_arg = cmd->chanlist_len;
596dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		err++;
597dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
598dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->stop_src == TRIG_COUNT) {
599dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!cmd->stop_arg) {
600dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->stop_arg = 1;
601dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			err++;
602dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
603dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {		/* TRIG_NONE */
604dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (cmd->stop_arg != 0) {
605dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->stop_arg = 0;
606dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			err++;
607dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
608dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
609dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
6104c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (err)
611dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 3;
6124c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
613dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
614dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* step 4: fix up any arguments */
615dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->convert_src == TRIG_TIMER) {
616dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		tmp = cmd->convert_arg;
617dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		i8253_cascade_ns_to_timer(this_board->i8254_osc_base,
6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &divisor1, &divisor2,
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &cmd->convert_arg,
6200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
621dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (cmd->convert_arg < this_board->ai_ns_min)
622dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->convert_arg = this_board->ai_ns_min;
623dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (tmp != cmd->convert_arg)
624dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			err++;
625dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
626dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
6274c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (err)
628dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 4;
6294c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
630dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
63164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	/* step 5: complain about special chanlist considerations */
63264a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott
63364a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	if (cmd->chanlist) {
63464a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott		if (!check_channel_list(dev, s, cmd->chanlist,
63564a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott					cmd->chanlist_len))
63664a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott			return 5;	/*  incorrect channels list */
63764a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	}
63864a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott
639dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return 0;
640dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
641dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
642da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
643dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
644dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
645ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
64664a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	unsigned int seglen;
647dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
648dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->start_src != TRIG_NOW)
649dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EINVAL;
650dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_begin_src != TRIG_FOLLOW)
651dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EINVAL;
652dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_end_src != TRIG_COUNT)
653dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EINVAL;
654dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->scan_end_arg != cmd->chanlist_len)
655dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EINVAL;
65658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL; */
657dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (devpriv->irq_blocked)
658dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EBUSY;
659dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
660dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->convert_src == TRIG_TIMER) {
661dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (cmd->convert_arg < this_board->ai_ns_min)
662dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			cmd->convert_arg = this_board->ai_ns_min;
663dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
664dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1,
6650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  &divisor2, &cmd->convert_arg,
6660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  cmd->flags & TRIG_ROUND_MASK);
6674c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
6684c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  PCL816 crash if any divisor is set to 1 */
6694c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		if (divisor1 == 1) {
670dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			divisor1 = 2;
671dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			divisor2 /= 2;
672dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
673dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (divisor2 == 1) {
674dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			divisor2 = 2;
675dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			divisor1 /= 2;
676dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
677dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
678dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
67958c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
680dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
68164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
68264a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	if (seglen < 1)
683dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EINVAL;
68464a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	setup_channel_list(dev, s, cmd->chanlist, seglen);
6855f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
686dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
68713de4f000ec491b16a820e4ed59de2c98b7807beIan Abbott	devpriv->ai_n_chan = cmd->chanlist_len;
688dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->ai_act_scan = 0;
689dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->async->cur_chan = 0;
690dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->irq_blocked = 1;
691dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->ai_poll_ptr = 0;
692dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->irq_was_now_closed = 0;
693dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
694dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (cmd->stop_src == TRIG_COUNT) {
695dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_scans = cmd->stop_arg;
696dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_neverending = 0;
697dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {
698dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_scans = 0;
699dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_neverending = 1;
700dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
701dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7024c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*  don't we want wake up every scan? */
7034c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if ((cmd->flags & TRIG_WAKE_EOS)) {
7044c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		printk(KERN_INFO
7054c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		       "pl816: You wankt WAKE_EOS but I dont want handle it");
70658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		/*               devpriv->ai_eos=1; */
70758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		/* if (devpriv->ai_n_chan==1) */
70858c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		/*       devpriv->dma=0; // DMA is useless for this situation */
709dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
710dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
711dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (devpriv->dma) {
712dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		bytes = devpriv->hwdmasize[0];
713dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!devpriv->ai_neverending) {
7144c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/*  how many */
7154c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			bytes = s->async->cmd.chanlist_len *
7164c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			s->async->cmd.chanlist_len *
7174c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			sizeof(short);
7184c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7194c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/*  how many DMA pages we must fill */
7204c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			devpriv->dma_runs_to_end = bytes /
7214c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			devpriv->hwdmasize[0];
7224c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7234c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/* on last dma transfer must be moved */
7244c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];
725dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->dma_runs_to_end--;
726dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (devpriv->dma_runs_to_end >= 0)
727dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				bytes = devpriv->hwdmasize[0];
728dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		} else
729dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->dma_runs_to_end = -1;
730dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
731dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->next_dma_buf = 0;
732dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		set_dma_mode(devpriv->dma, DMA_MODE_READ);
733dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		dma_flags = claim_dma_lock();
734dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		clear_dma_ff(devpriv->dma);
735dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
736dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		set_dma_count(devpriv->dma, bytes);
737dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		release_dma_lock(dma_flags);
738dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		enable_dma(devpriv->dma);
739dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
740dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
741dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	start_pacer(dev, 1, divisor1, divisor2);
742dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	dmairq = ((devpriv->dma & 0x3) << 4) | (dev->irq & 0x7);
743dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
744dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	switch (cmd->convert_src) {
745dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	case TRIG_TIMER:
746dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->int816_mode = INT_TYPE_AI1_DMA;
7474c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7484c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  Pacer+IRQ+DMA */
7494c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		outb(0x32, dev->iobase + PCL816_CONTROL);
7504c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7514c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  write irq and DMA to card */
7524c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		outb(dmairq, dev->iobase + PCL816_STATUS);
753dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		break;
754dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
755dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	default:
756dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->int816_mode = INT_TYPE_AI3_DMA;
7574c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7584c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  Ext trig+IRQ+DMA */
7594c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		outb(0x34, dev->iobase + PCL816_CONTROL);
7604c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
7614c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  write irq to card */
7624c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		outb(dmairq, dev->iobase + PCL816_STATUS);
763dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		break;
764dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
765dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
766dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	DPRINTK("pcl816 END: pcl812_ai_cmd()\n");
767dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return 0;
768dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
769dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
770da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
771dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
772dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned long flags;
773dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int top1, top2, i;
774dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
775dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!devpriv->dma)
77658c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		return 0;	/*  poll is valid only for DMA transfer */
777dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7785f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
779dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
780dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	for (i = 0; i < 20; i++) {
78158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		top1 = get_dma_residue(devpriv->dma);	/*  where is now DMA */
782dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		top2 = get_dma_residue(devpriv->dma);
783dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (top1 == top2)
784dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			break;
785dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
786dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (top1 != top2) {
7875f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
788dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 0;
789dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
790dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
7914c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*  where is now DMA in buffer */
7924c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	top1 = devpriv->hwdmasize[0] - top1;
79358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	top1 >>= 1;		/*  sample position */
794dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	top2 = top1 - devpriv->ai_poll_ptr;
79558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	if (top2 < 1) {		/*  no new samples */
7965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
797dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 0;
798dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
799dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
800dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	transfer_from_dma_buf(dev, s,
8010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      (short *)devpriv->dmabuf[devpriv->next_dma_buf],
8020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      devpriv->ai_poll_ptr, top2);
803dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
80458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	devpriv->ai_poll_ptr = top1;	/*  new buffer position */
8055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
806dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
807dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return s->async->buf_write_count - s->async->buf_read_count;
808dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
809dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
810dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
811dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
812dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera cancel any mode 1-4 AI
813dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
8140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl816_ai_cancel(struct comedi_device *dev,
8150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
816dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
8175f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman/* DEBUG(printk("pcl816_ai_cancel()\n");) */
818dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
819dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (devpriv->irq_blocked > 0) {
820dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		switch (devpriv->int816_mode) {
821dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
822dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI1_DMA_RTC:
823dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI3_DMA_RTC:
82458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton			set_rtc_irq_bit(0);	/*  stop RTC */
825dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			del_timer(&devpriv->rtc_irq_timer);
826dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
827dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI1_DMA:
828dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI3_DMA:
829dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			disable_dma(devpriv->dma);
830dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI1_INT:
831dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		case INT_TYPE_AI3_INT:
8324c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			outb(inb(dev->iobase + PCL816_CONTROL) & 0x73,
8334c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			     dev->iobase + PCL816_CONTROL);	/* Stop A/D */
8345f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			udelay(1);
835dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			outb(0, dev->iobase + PCL816_CONTROL);	/* Stop A/D */
8364c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
8374c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/* Stop pacer */
8384c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			outb(0xb0, dev->iobase + PCL816_CTRCTL);
839dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			outb(0x70, dev->iobase + PCL816_CTRCTL);
840dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			outb(0, dev->iobase + PCL816_AD_LO);
841dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			inb(dev->iobase + PCL816_AD_LO);
842dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			inb(dev->iobase + PCL816_AD_HI);
8434c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
8444c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/* clear INT request */
8454c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			outb(0, dev->iobase + PCL816_CLRINT);
8464c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
8474c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/* Stop A/D */
8484c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			outb(0, dev->iobase + PCL816_CONTROL);
849dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->irq_blocked = 0;
850dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->irq_was_now_closed = devpriv->int816_mode;
851dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->int816_mode = 0;
852dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->last_int_sub = s;
85358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* s->busy = 0; */
854dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			break;
855dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
856dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
857dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
8580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	DEBUG(printk("comedi: pcl816_ai_cancel() successful\n");)
8590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    return 0;
860dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
861dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
862dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
863dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
864dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera chech for PCL816
865dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
866dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic int pcl816_check(unsigned long iobase)
867dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
868dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x00, iobase + PCL816_MUX);
8695f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
870dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (inb(iobase + PCL816_MUX) != 0x00)
87158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		return 1;	/* there isn't card */
872dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x55, iobase + PCL816_MUX);
8735f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
874dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (inb(iobase + PCL816_MUX) != 0x55)
87558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		return 1;	/* there isn't card */
876dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x00, iobase + PCL816_MUX);
8775f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
878dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x18, iobase + PCL816_CONTROL);
8795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
880dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (inb(iobase + PCL816_CONTROL) != 0x18)
88158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		return 1;	/* there isn't card */
88258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	return 0;		/*  ok, card exist */
883dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
884dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
885dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
886dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
887dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera reset whole PCL-816 cards
888dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
889da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pcl816_reset(struct comedi_device *dev)
890dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
89158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* outb (0, dev->iobase + PCL818_DA_LO);         DAC=0V */
89258c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* outb (0, dev->iobase + PCL818_DA_HI); */
8935f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman/* udelay (1); */
89458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* outb (0, dev->iobase + PCL818_DO_HI);        DO=$0000 */
89558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* outb (0, dev->iobase + PCL818_DO_LO); */
8965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman/* udelay (1); */
897dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CONTROL);
898dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_MUX);
899dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_CLRINT);
900dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0xb0, dev->iobase + PCL816_CTRCTL);	/* Stop pacer */
901dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x70, dev->iobase + PCL816_CTRCTL);
902dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x30, dev->iobase + PCL816_CTRCTL);
903dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0, dev->iobase + PCL816_RANGE);
904dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
905dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
906dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
907dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
908dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera Start/stop pacer onboard pacer
909dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
910dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic void
911da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstart_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
9120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    unsigned int divisor2)
913dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
914dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x32, dev->iobase + PCL816_CTRCTL);
915dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0xff, dev->iobase + PCL816_CTR0);
916dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	outb(0x00, dev->iobase + PCL816_CTR0);
9175f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
9184c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
9194c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*  set counter 2 as mode 3 */
9204c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	outb(0xb4, dev->iobase + PCL816_CTRCTL);
9214c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/*  set counter 1 as mode 3 */
9224c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	outb(0x74, dev->iobase + PCL816_CTRCTL);
9235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
924dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
925dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (mode == 1) {
926dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		DPRINTK("mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1,
927dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			divisor2);
928dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2);
929dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2);
930dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb(divisor1 & 0xff, dev->iobase + PCL816_CTR1);
931dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL816_CTR1);
932dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
933dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
934dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* clear pending interrupts (just in case) */
93558c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton/* outb(0, dev->iobase + PCL816_CLRINT); */
936dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
937dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
938dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
939dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
940dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera Check if channel list from user is builded correctly
94164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott If it's ok, then return non-zero length of repeated segment of channel list
942dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
943dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic int
94464a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbottcheck_channel_list(struct comedi_device *dev,
94564a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott		   struct comedi_subdevice *s, unsigned int *chanlist,
94664a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott		   unsigned int chanlen)
947dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
948dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int chansegment[16];
949dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int i, nowmustbechan, seglen, segpos;
950dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
95158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/*  correct channel and range number check itself comedi/range.c */
952dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (chanlen < 1) {
953dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		comedi_error(dev, "range/channel list is empty!");
954dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return 0;
955dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
956dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
957dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (chanlen > 1) {
95825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/*  first channel is every time ok */
9594c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		chansegment[0] = chanlist[0];
960dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
96158c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton			/*  build part of chanlist */
9624c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			DEBUG(printk(KERN_INFO "%d. %d %d\n", i,
9634c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				     CR_CHAN(chanlist[i]),
9640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     CR_RANGE(chanlist[i]));)
9654c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
9664c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/*  we detect loop, this must by finish */
9670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    if (chanlist[0] == chanlist[i])
9684c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				break;
969dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			nowmustbechan =
9700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
971dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (nowmustbechan != CR_CHAN(chanlist[i])) {
97225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi				/*  channel list isn't continuous :-( */
9734c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				printk(KERN_WARNING
9744c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       "comedi%d: pcl816: channel list must "
97525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi				       "be continuous! chanlist[%i]=%d but "
9764c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       "must be %d or %d!\n", dev->minor,
9774c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       i, CR_CHAN(chanlist[i]), nowmustbechan,
9784c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_CHAN(chanlist[0]));
979dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				return 0;
980dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
9814c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/*  well, this is next correct channel in list */
9824c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			chansegment[i] = chanlist[i];
983dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
984dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
9854c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/*  check whole chanlist */
9864c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		for (i = 0, segpos = 0; i < chanlen; i++) {
9875f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			DEBUG(printk("%d %d=%d %d\n",
9880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     CR_CHAN(chansegment[i % seglen]),
9890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     CR_RANGE(chansegment[i % seglen]),
9900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     CR_CHAN(chanlist[i]),
9910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     CR_RANGE(chanlist[i]));)
9920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    if (chanlist[i] != chansegment[i % seglen]) {
9934c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				printk(KERN_WARNING
9944c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       "comedi%d: pcl816: bad channel or range"
9954c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       " number! chanlist[%i]=%d,%d,%d and not"
9964c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       " %d,%d,%d!\n", dev->minor, i,
9974c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_CHAN(chansegment[i]),
9984c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_RANGE(chansegment[i]),
9994c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_AREF(chansegment[i]),
10004c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_CHAN(chanlist[i % seglen]),
10014c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_RANGE(chanlist[i % seglen]),
10024c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       CR_AREF(chansegment[i % seglen]));
100358c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton				return 0;	/*  chan/gain list is strange */
1004dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
1005dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1006dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {
1007dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		seglen = 1;
1008dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1009dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
101064a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	return seglen;	/*  we can serve this with MUX logic */
101164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott}
101264a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott
101364a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott/*
101464a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott==============================================================================
101564a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott Program scan/gain logic with channel list.
101664a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott*/
101764a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbottstatic void
101864a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbottsetup_channel_list(struct comedi_device *dev,
101964a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott		   struct comedi_subdevice *s, unsigned int *chanlist,
102064a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott		   unsigned int seglen)
102164a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott{
102264a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott	unsigned int i;
102364a1f7bd56e0f26bd4dd621805facffde9fbb0a3Ian Abbott
1024dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->ai_act_chanlist_len = seglen;
1025dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->ai_act_chanlist_pos = 0;
1026dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
102758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	for (i = 0; i < seglen; i++) {	/*  store range list to card */
1028dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]);
1029dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX);
10304c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		/* select gain */
10314c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE);
1032dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1033dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
10345f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
10354c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	/* select channel interval to scan */
10364c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	outb(devpriv->ai_act_chanlist[0] |
10374c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	     (devpriv->ai_act_chanlist[seglen - 1] << 4),
10384c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	     dev->iobase + PCL816_MUX);
1039dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
1040dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1041dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
1042dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
1043dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
1044dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  Enable(1)/disable(0) periodic interrupts from RTC
1045dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
1046dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigerastatic int set_rtc_irq_bit(unsigned char bit)
1047dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
1048dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned char val;
1049dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned long flags;
1050dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1051dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (bit == 1) {
1052dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		RTC_timer_lock++;
1053dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (RTC_timer_lock > 1)
1054dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return 0;
1055dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {
1056dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		RTC_timer_lock--;
1057dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (RTC_timer_lock < 0)
1058dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			RTC_timer_lock = 0;
1059dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (RTC_timer_lock > 0)
1060dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return 0;
1061dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1062dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1063dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	save_flags(flags);
1064dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	cli();
1065dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	val = CMOS_READ(RTC_CONTROL);
10664c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (bit)
1067dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		val |= RTC_PIE;
10684c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	else
1069dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		val &= ~RTC_PIE;
10704c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
1071dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	CMOS_WRITE(val, RTC_CONTROL);
1072dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	CMOS_READ(RTC_INTR_FLAGS);
1073dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	restore_flags(flags);
1074dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return 0;
1075dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
1076dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1077dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1078dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
1079dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
1080dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  Free any resources that we have claimed
1081dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
1082da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void free_resources(struct comedi_device *dev)
1083dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
10845f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	/* printk("free_resource()\n"); */
1085dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (dev->private) {
1086dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		pcl816_ai_cancel(dev, devpriv->sub_ai);
1087dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		pcl816_reset(dev);
1088dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->dma)
1089dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			free_dma(devpriv->dma);
1090dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->dmabuf[0])
1091dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1092dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->dmabuf[1])
1093dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1094dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
1095dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (devpriv->rtc_irq)
10965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			free_irq(devpriv->rtc_irq, dev);
1097dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1098dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (devpriv->rtc_iobase)
1099dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				release_region(devpriv->rtc_iobase,
11000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       devpriv->rtc_iosize);
1101dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1102dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1103dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1104dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1105dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (dev->irq)
1106dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		free_irq(dev->irq, dev);
1107dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (dev->iobase)
1108dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		release_region(dev->iobase, this_board->io_range);
11095f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	/* printk("free_resource() end\n"); */
1110dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
1111dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1112dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
1113dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
1114dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1115dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera   Initialization
1116dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1117dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
1118da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1119dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
1120dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	int ret;
1121dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned long iobase;
1122dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned int irq, dma;
1123dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	unsigned long pages;
112458c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	/* int i; */
112534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
1126dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1127dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* claim our I/O space */
1128dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	iobase = it->options[0];
1129dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	printk("comedi%d: pcl816:  board=%s, ioport=0x%03lx", dev->minor,
11300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       this_board->name, iobase);
1131dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1132dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (!request_region(iobase, this_board->io_range, "pcl816")) {
11335f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		printk("I/O port conflict\n");
1134dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EIO;
1135dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1136dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1137dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	dev->iobase = iobase;
1138dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1139dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (pcl816_check(iobase)) {
11404c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		printk(KERN_ERR ", I cann't detect board. FAIL!\n");
1141dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return -EIO;
1142dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1143dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1144c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	ret = alloc_private(dev, sizeof(struct pcl816_private));
1145c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (ret < 0)
1146dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return ret;	/* Can't alloc mem */
1147dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1148dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* set up some name stuff */
1149dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	dev->board_name = this_board->name;
1150dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1151dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* grab our IRQ */
1152dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	irq = 0;
1153dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (this_board->IRQbits != 0) {	/* board support IRQ */
1154dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		irq = it->options[1];
1155dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (irq) {	/* we want to use IRQ */
1156dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (((1 << irq) & this_board->IRQbits) == 0) {
11575f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman				printk
11584c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				    (", IRQ %u is out of allowed range, "
11594c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				     "DISABLING IT", irq);
1160dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				irq = 0;	/* Bad IRQ */
1161dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			} else {
11620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				if (request_irq
11630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    (irq, interrupt_pcl816, 0, "pcl816", dev)) {
11645f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman					printk
11654c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva					    (", unable to allocate IRQ %u, "
11664c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva					     "DISABLING IT", irq);
1167dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera					irq = 0;	/* Can't use IRQ */
1168dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				} else {
11694c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva					printk(KERN_INFO ", irq=%u", irq);
1170dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				}
1171dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
1172dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1173dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1174dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1175dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	dev->irq = irq;
11764c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	if (irq)	/* 1=we have allocated irq */
1177dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->irq_free = 1;
11784c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	else
1179dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->irq_free = 0;
11804c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva
1181dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
1182dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->int816_mode = 0;	/* mode of irq */
1183dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1184dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
1185dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* grab RTC for DMA operations */
1186dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->dma_rtc = 0;
118758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton	if (it->options[2] > 0) {	/*  we want to use DMA */
1188dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (RTC_lock == 0) {
1189dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
11900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    "pcl816 (RTC)"))
1191dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				goto no_rtc;
1192dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1193dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->rtc_iobase = RTC_PORT(0);
1194dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->rtc_iosize = RTC_IO_EXTENT;
1195dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		RTC_lock++;
1196dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef UNTESTED_CODE
11975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (!request_irq(RTC_IRQ, interrupt_pcl816_ai_mode13_dma_rtc, 0,
11980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 "pcl816 DMA (RTC)", dev)) {
1199dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->dma_rtc = 1;
1200dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->rtc_irq = RTC_IRQ;
12015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			printk(", dma_irq=%u", devpriv->rtc_irq);
1202dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		} else {
1203dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			RTC_lock--;
1204dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (RTC_lock == 0) {
1205dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				if (devpriv->rtc_iobase)
1206dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera					release_region(devpriv->rtc_iobase,
12070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       devpriv->rtc_iosize);
1208dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
1209dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->rtc_iobase = 0;
1210dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->rtc_iosize = 0;
1211dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1212dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#else
1213dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		printk("pcl816: RTC code missing");
1214dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1215dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1216dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1217dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
12180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralno_rtc:
1219dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1220dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	/* grab our DMA */
1221dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	dma = 0;
1222dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	devpriv->dma = dma;
1223dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1224dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
1225dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1226dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (this_board->DMAbits != 0) {	/* board support DMA */
1227dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		dma = it->options[2];
1228dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (dma < 1)
1229dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			goto no_dma;	/* DMA disabled */
1230dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1231dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (((1 << dma) & this_board->DMAbits) == 0) {
12325f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			printk(", DMA is out of allowed range, FAIL!\n");
1233dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return -EINVAL;	/* Bad DMA */
1234dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1235dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		ret = request_dma(dma, "pcl816");
1236dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (ret) {
12374c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			printk(KERN_ERR
12384c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			       ", unable to allocate DMA %u, FAIL!\n", dma);
1239dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return -EBUSY;	/* DMA isn't free */
1240dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1241dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1242dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->dma = dma;
12434c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva		printk(KERN_INFO ", dma=%u", dma);
1244dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		pages = 2;	/* we need 16KB */
1245dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1246dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1247dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		if (!devpriv->dmabuf[0]) {
12485f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			printk(", unable to allocate DMA buffer, FAIL!\n");
12494c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			/*
12504c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			 * maybe experiment with try_to_free_pages()
12514c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			 * will help ....
12524c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva			 */
1253dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			return -EBUSY;	/* no buffer :-( */
1254dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1255dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->dmapages[0] = pages;
1256dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1257dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
12585f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		/* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1259dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
126058c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
1261dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1262dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			if (!devpriv->dmabuf[1]) {
12634c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				printk(KERN_ERR
12644c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       ", unable to allocate DMA buffer, "
12654c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva				       "FAIL!\n");
1266dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera				return -EBUSY;
1267dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			}
1268dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->dmapages[1] = pages;
1269dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->hwdmaptr[1] =
12700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    virt_to_bus((void *)devpriv->dmabuf[1]);
1271dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera			devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1272dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		}
1273dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1274dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
12750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralno_dma:
1276dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1277dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*  if (this_board->n_aochan > 0)
1278dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    subdevs[1] = COMEDI_SUBD_AO;
1279dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  if (this_board->n_dichan > 0)
1280dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    subdevs[2] = COMEDI_SUBD_DI;
1281dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  if (this_board->n_dochan > 0)
1282dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera    subdevs[3] = COMEDI_SUBD_DO;
1283dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera*/
1284c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
1285c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	ret = alloc_subdevices(dev, 1);
1286c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (ret < 0)
1287dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		return ret;
1288dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1289dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s = dev->subdevices + 0;
1290dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (this_board->n_aichan > 0) {
1291dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->type = COMEDI_SUBD_AI;
1292dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		devpriv->sub_ai = s;
1293dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		dev->read_subdev = s;
1294dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1295dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->n_chan = this_board->n_aichan;
1296dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->subdev_flags |= SDF_DIFF;
129758c0576eea94298e698e03114c4d3d0179c5ef66Bill Pemberton		/* printk (", %dchans DIFF DAC - %d", s->n_chan, i); */
1298dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->maxdata = this_board->ai_maxdata;
1299dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->len_chanlist = this_board->ai_chanlist;
1300dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->range_table = this_board->ai_range_type;
1301dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->cancel = pcl816_ai_cancel;
1302dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->do_cmdtest = pcl816_ai_cmdtest;
1303dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->do_cmd = pcl816_ai_cmd;
1304dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->poll = pcl816_ai_poll;
1305dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->insn_read = pcl816_ai_insn_read;
1306dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	} else {
1307dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		s->type = COMEDI_SUBD_UNUSED;
1308dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	}
1309dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1310dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#if 0
1311dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigeracase COMEDI_SUBD_AO:
1312dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1313dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->n_chan = this_board->n_aochan;
1314dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->maxdata = this_board->ao_maxdata;
1315dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->len_chanlist = this_board->ao_chanlist;
1316dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->range_table = this_board->ao_range_type;
1317dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	break;
1318dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1319dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigeracase COMEDI_SUBD_DI:
1320dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->subdev_flags = SDF_READABLE;
1321dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->n_chan = this_board->n_dichan;
1322dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->maxdata = 1;
1323dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->len_chanlist = this_board->n_dichan;
1324dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->range_table = &range_digital;
1325dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	break;
1326dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1327dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigeracase COMEDI_SUBD_DO:
1328dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->subdev_flags = SDF_WRITABLE;
1329dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->n_chan = this_board->n_dochan;
1330dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->maxdata = 1;
1331dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->len_chanlist = this_board->n_dochan;
1332dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	s->range_table = &range_digital;
1333dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	break;
1334dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1335dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1336dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	pcl816_reset(dev);
1337dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
13385f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("\n");
1339dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1340dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return 0;
1341dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
1342dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera
1343dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera/*
1344dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera==============================================================================
1345dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera  Removes device
1346dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera */
1347da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl816_detach(struct comedi_device *dev)
1348dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera{
13494c68fb42c2a39b89daca2b7175eb93ffe6860da4Gustavo Silva	DEBUG(printk(KERN_INFO "comedi%d: pcl816: remove\n", dev->minor);)
13500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    free_resources(dev);
1351dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#ifdef unused
1352dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	if (devpriv->dma_rtc)
1353dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera		RTC_lock--;
1354dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera#endif
1355dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera	return 0;
1356dd2996b38be848c5f19a5e92a9be84069f09ebd3Juan Grigera}
135790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
135890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
135990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
136090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1361