Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[deliverable/linux.git] / drivers / staging / comedi / drivers / adv_pci_dio.c
CommitLineData
ebd127c3
MD
1/*
2 * comedi/drivers/adv_pci_dio.c
3 *
4 * Author: Michal Dobes <dobes@tesnet.cz>
5 *
6 * Hardware driver for Advantech PCI DIO cards.
7*/
8/*
9Driver: adv_pci_dio
d4da77a7 10Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
9e77e6b6
IA
11 PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752,
12 PCI-1753/E, PCI-1754, PCI-1756, PCI-1760, PCI-1762
ebd127c3
MD
13Author: Michal Dobes <dobes@tesnet.cz>
14Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
9e77e6b6 15 PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750,
ebd127c3
MD
16 PCI-1751, PCI-1752, PCI-1753,
17 PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
18 PCI-1760, PCI-1762
19Status: untested
9e77e6b6 20Updated: Mon, 09 Jan 2012 12:40:46 +0000
ebd127c3
MD
21
22This driver supports now only insn interface for DI/DO/DIO.
23
24Configuration options:
25 [0] - PCI bus of device (optional)
26 [1] - PCI slot of device (optional)
3afbe13c
M
27 If bus/slot is not specified, the first available PCI
28 device will be used.
ebd127c3
MD
29
30*/
31
ce157f80 32#include <linux/module.h>
33782dd5 33#include <linux/pci.h>
ebd127c3
MD
34#include <linux/delay.h>
35
33782dd5
HS
36#include "../comedidev.h"
37
ebd127c3 38#include "8255.h"
d4da77a7 39#include "8253.h"
ebd127c3 40
a8f1152e
BP
41/* hardware types of the cards */
42enum hw_cards_id {
d4da77a7 43 TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
9e77e6b6 44 TYPE_PCI1739,
ebd127c3
MD
45 TYPE_PCI1750,
46 TYPE_PCI1751,
47 TYPE_PCI1752,
48 TYPE_PCI1753, TYPE_PCI1753E,
49 TYPE_PCI1754, TYPE_PCI1756,
50 TYPE_PCI1760,
51 TYPE_PCI1762
a8f1152e 52};
ebd127c3 53
a8f1152e
BP
54/* which I/O instructions to use */
55enum hw_io_access {
ebd127c3 56 IO_8b, IO_16b
a8f1152e 57};
ebd127c3
MD
58
59#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
60#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
3afbe13c
M
61#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
62 * card */
63#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per
64 * card */
65 /* (could be more than one 8254 per
66 * subdevice) */
ebd127c3 67
d4da77a7 68#define SIZE_8254 4 /* 8254 IO space length */
ebd127c3
MD
69
70#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */
71
72/* Register offset definitions */
ba23095c 73/* Advantech PCI-1730/3/4 */
ebd127c3
MD
74#define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */
75#define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */
76#define PCI1730_DI 2 /* R: Digital input 0-15 */
77#define PCI1730_DO 2 /* W: Digital output 0-15 */
78#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
79#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
3afbe13c
M
80#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for
81 * interrupts */
ebd127c3
MD
82#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
83#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
84#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
85
d4da77a7
IA
86/* Advantech PCI-1735U */
87#define PCI1735_DI 0 /* R: Digital input 0-31 */
88#define PCI1735_DO 0 /* W: Digital output 0-31 */
89#define PCI1735_C8254 4 /* R/W: 8254 counter */
90#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */
91
ba23095c 92/* Advantech PCI-1736UP */
0a85b6f0
MT
93#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
94#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
95#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
3afbe13c
M
96#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for
97 * interrupts */
0a85b6f0
MT
98#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
99#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */
100#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */
ebd127c3 101
9e77e6b6
IA
102/* Advantech PCI-1739U */
103#define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */
104#define PCI1739_ICR 32 /* W: Interrupt control register */
105#define PCI1739_ISR 32 /* R: Interrupt status register */
106#define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */
107
ba23095c 108/* Advantech PCI-1750 */
ebd127c3
MD
109#define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */
110#define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */
111#define PCI1750_ICR 32 /* W: Interrupt control register */
112#define PCI1750_ISR 32 /* R: Interrupt status register */
113
ba23095c 114/* Advantech PCI-1751/3/3E */
ebd127c3 115#define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */
cfe3cffd 116#define PCI1751_CNT 24 /* R/W: begin of 8254 registers block */
ebd127c3
MD
117#define PCI1751_ICR 32 /* W: Interrupt control register */
118#define PCI1751_ISR 32 /* R: Interrupt status register */
119#define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */
120#define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */
121#define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */
122#define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */
123#define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */
124#define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */
125#define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */
126#define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */
127#define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */
128#define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */
129
ba23095c 130/* Advantech PCI-1752/4/6 */
ebd127c3
MD
131#define PCI1752_IDO 0 /* R/W: Digital output 0-31 */
132#define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */
133#define PCI1754_IDI 0 /* R: Digital input 0-31 */
134#define PCI1754_IDI2 4 /* R: Digital input 32-64 */
135#define PCI1756_IDI 0 /* R: Digital input 0-31 */
136#define PCI1756_IDO 4 /* R/W: Digital output 0-31 */
137#define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */
138#define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */
139#define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */
140#define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */
141#define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */
142#define PCI175x_BOARDID 0x10 /* R: Board I/D switch for 1752/4/6 */
143
ba23095c 144/* Advantech PCI-1762 registers */
ebd127c3
MD
145#define PCI1762_RO 0 /* R/W: Relays status/output */
146#define PCI1762_IDI 2 /* R: Isolated input status */
147#define PCI1762_BOARDID 4 /* R: Board I/D switch */
148#define PCI1762_ICR 6 /* W: Interrupt control register */
149#define PCI1762_ISR 6 /* R: Interrupt status register */
150
ba23095c 151/* Advantech PCI-1760 registers */
ebd127c3
MD
152#define OMB0 0x0c /* W: Mailbox outgoing registers */
153#define OMB1 0x0d
154#define OMB2 0x0e
155#define OMB3 0x0f
156#define IMB0 0x1c /* R: Mailbox incoming registers */
157#define IMB1 0x1d
158#define IMB2 0x1e
159#define IMB3 0x1f
160#define INTCSR0 0x38 /* R/W: Interrupt control registers */
161#define INTCSR1 0x39
162#define INTCSR2 0x3a
163#define INTCSR3 0x3b
164
ba23095c 165/* PCI-1760 mailbox commands */
3afbe13c
M
166#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual
167 * DI status in IMB3 */
ebd127c3
MD
168#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */
169#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */
3afbe13c
M
170#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the
171 * register in OMB0, result in IMB0 */
172#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in
173 * IMB1.IMB0 */
174#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in
175 * IMB1.IMB0 */
176#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in
177 * OMB0 */
178#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on
179 * bits in OMB0 */
180#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on
181 * bits in OMB0 */
182#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in
183 * OMB0 */
184#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in
185 * OMB0 to its reset values */
186#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow
187 * interrupts based on bits in OMB0 */
188#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value
189 * interrupts based on bits in OMB0 */
190#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0
191 * - rising, =1 - falling) */
192#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current
193 * value */
194#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value
195 * 256*OMB1+OMB0 */
196#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value
197 * 256*OMB1+OMB0 */
198#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value
199 * 256*OMB1+OMB0 */
200#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value
201 * 256*OMB1+OMB0 */
202#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value
203 * 256*OMB1+OMB0 */
204#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value
205 * 256*OMB1+OMB0 */
206#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value
207 * 256*OMB1+OMB0 */
208#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value
209 * 256*OMB1+OMB0 */
210#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value
211 * 256*OMB1+OMB0 */
212#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value
213 * 256*OMB1+OMB0 */
214#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value
215 * 256*OMB1+OMB0 */
216#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value
217 * 256*OMB1+OMB0 */
218#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value
219 * 256*OMB1+OMB0 */
220#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value
221 * 256*OMB1+OMB0 */
222#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value
223 * 256*OMB1+OMB0 */
224#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value
225 * 256*OMB1+OMB0 */
ebd127c3
MD
226
227#define OMBCMD_RETRY 0x03 /* 3 times try request before error */
228
673bc56a 229struct diosubd_data {
ba23095c
BP
230 int chans; /* num of chans */
231 int addr; /* PCI address ofset */
d4da77a7
IA
232 int regs; /* number of registers to read or 8255
233 subdevices or 8254 chips */
ba23095c 234 unsigned int specflags; /* addon subdevice flags */
673bc56a 235};
ebd127c3 236
dea1776a 237struct dio_boardtype {
ba23095c 238 const char *name; /* board name */
ba23095c 239 int main_pci_region; /* main I/O PCI region */
a8f1152e 240 enum hw_cards_id cardtype;
4bf75257 241 int nsubdevs;
ba23095c
BP
242 struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */
243 struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
244 struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
245 struct diosubd_data boardid; /* card supports board ID switch */
d4da77a7 246 struct diosubd_data s8254[MAX_8254_SUBDEVS]; /* 8254 subdevices */
a8f1152e 247 enum hw_io_access io_access;
dea1776a 248};
ebd127c3 249
dea1776a 250static const struct dio_boardtype boardtypes[] = {
87f6991b 251 [TYPE_PCI1730] = {
59bd6752 252 .name = "pci1730",
59bd6752
HS
253 .main_pci_region = PCIDIO_MAINREG,
254 .cardtype = TYPE_PCI1730,
4bf75257 255 .nsubdevs = 5,
59bd6752
HS
256 .sdi[0] = { 16, PCI1730_DI, 2, 0, },
257 .sdi[1] = { 16, PCI1730_IDI, 2, 0, },
258 .sdo[0] = { 16, PCI1730_DO, 2, 0, },
259 .sdo[1] = { 16, PCI1730_IDO, 2, 0, },
59bd6752 260 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 261 .io_access = IO_8b,
c0a0e0ca 262 },
87f6991b 263 [TYPE_PCI1733] = {
59bd6752 264 .name = "pci1733",
59bd6752
HS
265 .main_pci_region = PCIDIO_MAINREG,
266 .cardtype = TYPE_PCI1733,
4bf75257 267 .nsubdevs = 2,
59bd6752 268 .sdi[1] = { 32, PCI1733_IDI, 4, 0, },
59bd6752 269 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 270 .io_access = IO_8b,
c0a0e0ca 271 },
87f6991b 272 [TYPE_PCI1734] = {
59bd6752 273 .name = "pci1734",
59bd6752
HS
274 .main_pci_region = PCIDIO_MAINREG,
275 .cardtype = TYPE_PCI1734,
4bf75257 276 .nsubdevs = 2,
59bd6752 277 .sdo[1] = { 32, PCI1734_IDO, 4, 0, },
59bd6752 278 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 279 .io_access = IO_8b,
c0a0e0ca 280 },
87f6991b 281 [TYPE_PCI1735] = {
59bd6752 282 .name = "pci1735",
59bd6752
HS
283 .main_pci_region = PCIDIO_MAINREG,
284 .cardtype = TYPE_PCI1735,
4bf75257 285 .nsubdevs = 4,
59bd6752 286 .sdi[0] = { 32, PCI1735_DI, 4, 0, },
59bd6752 287 .sdo[0] = { 32, PCI1735_DO, 4, 0, },
59bd6752
HS
288 .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
289 .s8254[0] = { 3, PCI1735_C8254, 1, 0, },
290 .io_access = IO_8b,
c0a0e0ca 291 },
87f6991b 292 [TYPE_PCI1736] = {
59bd6752 293 .name = "pci1736",
59bd6752
HS
294 .main_pci_region = PCI1736_MAINREG,
295 .cardtype = TYPE_PCI1736,
4bf75257 296 .nsubdevs = 3,
59bd6752 297 .sdi[1] = { 16, PCI1736_IDI, 2, 0, },
59bd6752 298 .sdo[1] = { 16, PCI1736_IDO, 2, 0, },
59bd6752 299 .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
59bd6752 300 .io_access = IO_8b,
c0a0e0ca 301 },
87f6991b 302 [TYPE_PCI1739] = {
59bd6752 303 .name = "pci1739",
59bd6752
HS
304 .main_pci_region = PCIDIO_MAINREG,
305 .cardtype = TYPE_PCI1739,
4bf75257 306 .nsubdevs = 2,
59bd6752 307 .sdio[0] = { 48, PCI1739_DIO, 2, 0, },
59bd6752 308 .io_access = IO_8b,
c0a0e0ca 309 },
87f6991b 310 [TYPE_PCI1750] = {
59bd6752 311 .name = "pci1750",
59bd6752
HS
312 .main_pci_region = PCIDIO_MAINREG,
313 .cardtype = TYPE_PCI1750,
4bf75257 314 .nsubdevs = 2,
59bd6752 315 .sdi[1] = { 16, PCI1750_IDI, 2, 0, },
59bd6752 316 .sdo[1] = { 16, PCI1750_IDO, 2, 0, },
59bd6752 317 .io_access = IO_8b,
c0a0e0ca 318 },
87f6991b 319 [TYPE_PCI1751] = {
59bd6752 320 .name = "pci1751",
59bd6752
HS
321 .main_pci_region = PCIDIO_MAINREG,
322 .cardtype = TYPE_PCI1751,
4bf75257 323 .nsubdevs = 3,
59bd6752 324 .sdio[0] = { 48, PCI1751_DIO, 2, 0, },
59bd6752
HS
325 .s8254[0] = { 3, PCI1751_CNT, 1, 0, },
326 .io_access = IO_8b,
c0a0e0ca 327 },
87f6991b 328 [TYPE_PCI1752] = {
59bd6752 329 .name = "pci1752",
59bd6752
HS
330 .main_pci_region = PCIDIO_MAINREG,
331 .cardtype = TYPE_PCI1752,
4bf75257 332 .nsubdevs = 3,
59bd6752
HS
333 .sdo[0] = { 32, PCI1752_IDO, 2, 0, },
334 .sdo[1] = { 32, PCI1752_IDO2, 2, 0, },
59bd6752 335 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 336 .io_access = IO_16b,
c0a0e0ca 337 },
87f6991b 338 [TYPE_PCI1753] = {
59bd6752 339 .name = "pci1753",
59bd6752
HS
340 .main_pci_region = PCIDIO_MAINREG,
341 .cardtype = TYPE_PCI1753,
4bf75257 342 .nsubdevs = 4,
59bd6752 343 .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
59bd6752 344 .io_access = IO_8b,
87f6991b
IA
345 },
346 [TYPE_PCI1753E] = {
59bd6752 347 .name = "pci1753e",
59bd6752
HS
348 .main_pci_region = PCIDIO_MAINREG,
349 .cardtype = TYPE_PCI1753E,
4bf75257 350 .nsubdevs = 8,
59bd6752
HS
351 .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
352 .sdio[1] = { 96, PCI1753E_DIO, 4, 0, },
59bd6752 353 .io_access = IO_8b,
c0a0e0ca 354 },
87f6991b 355 [TYPE_PCI1754] = {
59bd6752 356 .name = "pci1754",
59bd6752
HS
357 .main_pci_region = PCIDIO_MAINREG,
358 .cardtype = TYPE_PCI1754,
4bf75257 359 .nsubdevs = 3,
59bd6752
HS
360 .sdi[0] = { 32, PCI1754_IDI, 2, 0, },
361 .sdi[1] = { 32, PCI1754_IDI2, 2, 0, },
59bd6752 362 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 363 .io_access = IO_16b,
c0a0e0ca 364 },
87f6991b 365 [TYPE_PCI1756] = {
59bd6752 366 .name = "pci1756",
59bd6752
HS
367 .main_pci_region = PCIDIO_MAINREG,
368 .cardtype = TYPE_PCI1756,
4bf75257 369 .nsubdevs = 3,
59bd6752 370 .sdi[1] = { 32, PCI1756_IDI, 2, 0, },
59bd6752 371 .sdo[1] = { 32, PCI1756_IDO, 2, 0, },
59bd6752 372 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 373 .io_access = IO_16b,
c0a0e0ca 374 },
87f6991b 375 [TYPE_PCI1760] = {
59bd6752
HS
376 /* This card has its own 'attach' */
377 .name = "pci1760",
59bd6752
HS
378 .main_pci_region = 0,
379 .cardtype = TYPE_PCI1760,
4bf75257 380 .nsubdevs = 4,
59bd6752 381 .io_access = IO_8b,
c0a0e0ca 382 },
87f6991b 383 [TYPE_PCI1762] = {
59bd6752 384 .name = "pci1762",
59bd6752
HS
385 .main_pci_region = PCIDIO_MAINREG,
386 .cardtype = TYPE_PCI1762,
4bf75257 387 .nsubdevs = 3,
59bd6752 388 .sdi[1] = { 16, PCI1762_IDI, 1, 0, },
59bd6752 389 .sdo[1] = { 16, PCI1762_RO, 1, 0, },
59bd6752 390 .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, },
59bd6752
HS
391 .io_access = IO_16b,
392 },
ebd127c3
MD
393};
394
4cb13356 395struct pci_dio_private {
ba23095c
BP
396 char GlobalIrqEnabled; /* 1= any IRQ source is enabled */
397 /* PCI-1760 specific data */
3afbe13c
M
398 unsigned char IDICntEnable; /* counter's counting enable status */
399 unsigned char IDICntOverEnable; /* counter's overflow interrupts enable
400 * status */
401 unsigned char IDICntMatchEnable; /* counter's match interrupts
402 * enable status */
403 unsigned char IDICntEdge; /* counter's count edge value
404 * (bit=0 - rising, =1 - falling) */
ba23095c 405 unsigned short CntResValue[8]; /* counters' reset value */
3afbe13c
M
406 unsigned short CntMatchValue[8]; /* counters' match interrupt value */
407 unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
ba23095c
BP
408 unsigned char IDIPatMatchEn; /* IDI's pattern match enable status */
409 unsigned char IDIPatMatchValue; /* IDI's pattern match value */
410 unsigned short IDIFiltrLow[8]; /* IDI's filter value low signal */
411 unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */
ebd127c3
MD
412};
413
ebd127c3
MD
414/*
415==============================================================================
416*/
0a85b6f0
MT
417static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
418 struct comedi_subdevice *s,
419 struct comedi_insn *insn, unsigned int *data)
ebd127c3 420{
673bc56a 421 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
422 int i;
423
424 data[1] = 0;
402a01ae 425 for (i = 0; i < d->regs; i++)
ebd127c3 426 data[1] |= inb(dev->iobase + d->addr + i) << (8 * i);
402a01ae 427
ebd127c3 428
a2714e3e 429 return insn->n;
ebd127c3
MD
430}
431
432/*
433==============================================================================
434*/
0a85b6f0
MT
435static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
436 struct comedi_subdevice *s,
437 struct comedi_insn *insn, unsigned int *data)
ebd127c3 438{
673bc56a 439 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
440 int i;
441
442 data[1] = 0;
443 for (i = 0; i < d->regs; i++)
444 data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i);
445
a2714e3e 446 return insn->n;
ebd127c3
MD
447}
448
0a85b6f0
MT
449static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
450 struct comedi_subdevice *s,
97f4289a
HS
451 struct comedi_insn *insn,
452 unsigned int *data)
ebd127c3 453{
673bc56a 454 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
455 int i;
456
97f4289a 457 if (comedi_dio_update_state(s, data)) {
ebd127c3
MD
458 for (i = 0; i < d->regs; i++)
459 outb((s->state >> (8 * i)) & 0xff,
0a85b6f0 460 dev->iobase + d->addr + i);
ebd127c3 461 }
97f4289a 462
ebd127c3
MD
463 data[1] = s->state;
464
a2714e3e 465 return insn->n;
ebd127c3
MD
466}
467
0a85b6f0
MT
468static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
469 struct comedi_subdevice *s,
97f4289a
HS
470 struct comedi_insn *insn,
471 unsigned int *data)
ebd127c3 472{
673bc56a 473 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
474 int i;
475
97f4289a 476 if (comedi_dio_update_state(s, data)) {
ebd127c3
MD
477 for (i = 0; i < d->regs; i++)
478 outw((s->state >> (16 * i)) & 0xffff,
0a85b6f0 479 dev->iobase + d->addr + 2 * i);
ebd127c3 480 }
97f4289a 481
ebd127c3
MD
482 data[1] = s->state;
483
a2714e3e 484 return insn->n;
ebd127c3
MD
485}
486
d4da77a7
IA
487/*
488==============================================================================
489*/
490static int pci_8254_insn_read(struct comedi_device *dev,
491 struct comedi_subdevice *s,
492 struct comedi_insn *insn, unsigned int *data)
493{
494 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
495 unsigned int chan, chip, chipchan;
496 unsigned long flags;
497
498 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
499 chip = chan / 3; /* chip on subdevice */
500 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
501 spin_lock_irqsave(&s->spin_lock, flags);
502 data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
503 0, chipchan);
504 spin_unlock_irqrestore(&s->spin_lock, flags);
505 return 1;
506}
507
508/*
509==============================================================================
510*/
511static int pci_8254_insn_write(struct comedi_device *dev,
512 struct comedi_subdevice *s,
513 struct comedi_insn *insn, unsigned int *data)
514{
515 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
516 unsigned int chan, chip, chipchan;
517 unsigned long flags;
518
519 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
520 chip = chan / 3; /* chip on subdevice */
521 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
522 spin_lock_irqsave(&s->spin_lock, flags);
523 i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
524 0, chipchan, data[0]);
525 spin_unlock_irqrestore(&s->spin_lock, flags);
526 return 1;
527}
528
529/*
530==============================================================================
531*/
532static int pci_8254_insn_config(struct comedi_device *dev,
533 struct comedi_subdevice *s,
534 struct comedi_insn *insn, unsigned int *data)
535{
536 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
537 unsigned int chan, chip, chipchan;
538 unsigned long iobase;
539 int ret = 0;
540 unsigned long flags;
541
542 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
543 chip = chan / 3; /* chip on subdevice */
544 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
545 iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
546 spin_lock_irqsave(&s->spin_lock, flags);
547 switch (data[0]) {
548 case INSN_CONFIG_SET_COUNTER_MODE:
549 ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
550 if (ret < 0)
551 ret = -EINVAL;
552 break;
553 case INSN_CONFIG_8254_READ_STATUS:
554 data[1] = i8254_status(iobase, 0, chipchan);
555 break;
556 default:
557 ret = -EINVAL;
558 break;
559 }
560 spin_unlock_irqrestore(&s->spin_lock, flags);
561 return ret < 0 ? ret : insn->n;
562}
563
ebd127c3
MD
564/*
565==============================================================================
566*/
da91b269 567static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
0a85b6f0
MT
568 unsigned char *omb, unsigned char *imb,
569 int repeats)
ebd127c3
MD
570{
571 int cnt, tout, ok = 0;
572
573 for (cnt = 0; cnt < repeats; cnt++) {
574 outb(omb[0], dev->iobase + OMB0);
575 outb(omb[1], dev->iobase + OMB1);
576 outb(omb[2], dev->iobase + OMB2);
577 outb(omb[3], dev->iobase + OMB3);
578 for (tout = 0; tout < 251; tout++) {
c3744138
BP
579 imb[2] = inb(dev->iobase + IMB2);
580 if (imb[2] == omb[2]) {
ebd127c3
MD
581 imb[0] = inb(dev->iobase + IMB0);
582 imb[1] = inb(dev->iobase + IMB1);
583 imb[3] = inb(dev->iobase + IMB3);
584 ok = 1;
585 break;
586 }
5f74ea14 587 udelay(1);
ebd127c3
MD
588 }
589 if (ok)
590 return 0;
591 }
592
d1fe2cfb 593 dev_err(dev->class_dev, "PCI-1760 mailbox request timeout!\n");
ebd127c3
MD
594 return -ETIME;
595}
596
da91b269 597static int pci1760_clear_imb2(struct comedi_device *dev)
ebd127c3
MD
598{
599 unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 };
600 unsigned char imb[4];
601 /* check if imb2 is already clear */
602 if (inb(dev->iobase + IMB2) == CMD_ClearIMB2)
603 return 0;
604 return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY);
605}
606
da91b269 607static int pci1760_mbxrequest(struct comedi_device *dev,
0a85b6f0 608 unsigned char *omb, unsigned char *imb)
ebd127c3
MD
609{
610 if (omb[2] == CMD_ClearIMB2) {
d1fe2cfb
HS
611 dev_err(dev->class_dev,
612 "bug! this function should not be used for CMD_ClearIMB2 command\n");
ebd127c3
MD
613 return -EINVAL;
614 }
615 if (inb(dev->iobase + IMB2) == omb[2]) {
616 int retval;
11828ce9 617
ebd127c3
MD
618 retval = pci1760_clear_imb2(dev);
619 if (retval < 0)
620 return retval;
621 }
622 return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY);
623}
624
625/*
626==============================================================================
627*/
0a85b6f0
MT
628static int pci1760_insn_bits_di(struct comedi_device *dev,
629 struct comedi_subdevice *s,
630 struct comedi_insn *insn, unsigned int *data)
ebd127c3
MD
631{
632 data[1] = inb(dev->iobase + IMB3);
633
a2714e3e 634 return insn->n;
ebd127c3
MD
635}
636
0a85b6f0
MT
637static int pci1760_insn_bits_do(struct comedi_device *dev,
638 struct comedi_subdevice *s,
97f4289a
HS
639 struct comedi_insn *insn,
640 unsigned int *data)
ebd127c3
MD
641{
642 int ret;
643 unsigned char omb[4] = {
644 0x00,
645 0x00,
646 CMD_SetRelaysOutput,
647 0x00
648 };
649 unsigned char imb[4];
650
97f4289a 651 if (comedi_dio_update_state(s, data)) {
ebd127c3 652 omb[0] = s->state;
c3744138
BP
653 ret = pci1760_mbxrequest(dev, omb, imb);
654 if (!ret)
ebd127c3
MD
655 return ret;
656 }
97f4289a 657
ebd127c3
MD
658 data[1] = s->state;
659
a2714e3e 660 return insn->n;
ebd127c3
MD
661}
662
663/*
664==============================================================================
665*/
0a85b6f0
MT
666static int pci1760_insn_cnt_read(struct comedi_device *dev,
667 struct comedi_subdevice *s,
668 struct comedi_insn *insn, unsigned int *data)
ebd127c3
MD
669{
670 int ret, n;
671 unsigned char omb[4] = {
672 CR_CHAN(insn->chanspec) & 0x07,
673 0x00,
674 CMD_GetIDICntCurValue,
675 0x00
676 };
677 unsigned char imb[4];
678
679 for (n = 0; n < insn->n; n++) {
c3744138
BP
680 ret = pci1760_mbxrequest(dev, omb, imb);
681 if (!ret)
ebd127c3
MD
682 return ret;
683 data[n] = (imb[1] << 8) + imb[0];
684 }
685
686 return n;
687}
688
689/*
690==============================================================================
691*/
0a85b6f0
MT
692static int pci1760_insn_cnt_write(struct comedi_device *dev,
693 struct comedi_subdevice *s,
694 struct comedi_insn *insn, unsigned int *data)
ebd127c3 695{
242f5223 696 struct pci_dio_private *devpriv = dev->private;
ebd127c3
MD
697 int ret;
698 unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
699 unsigned char bitmask = 1 << chan;
700 unsigned char omb[4] = {
701 data[0] & 0xff,
702 (data[0] >> 8) & 0xff,
703 CMD_SetIDI0CntResetValue + chan,
704 0x00
705 };
706 unsigned char imb[4];
707
3afbe13c
M
708 /* Set reset value if different */
709 if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {
0a85b6f0 710 ret = pci1760_mbxrequest(dev, omb, imb);
c3744138 711 if (!ret)
ebd127c3
MD
712 return ret;
713 devpriv->CntResValue[chan] = data[0] & 0xffff;
714 }
715
ba23095c 716 omb[0] = bitmask; /* reset counter to it reset value */
ebd127c3 717 omb[2] = CMD_ResetIDICounters;
c3744138
BP
718 ret = pci1760_mbxrequest(dev, omb, imb);
719 if (!ret)
ebd127c3
MD
720 return ret;
721
3afbe13c
M
722 /* start counter if it don't run */
723 if (!(bitmask & devpriv->IDICntEnable)) {
ebd127c3
MD
724 omb[0] = bitmask;
725 omb[2] = CMD_EnableIDICounters;
c3744138
BP
726 ret = pci1760_mbxrequest(dev, omb, imb);
727 if (!ret)
ebd127c3
MD
728 return ret;
729 devpriv->IDICntEnable |= bitmask;
730 }
731 return 1;
732}
733
734/*
735==============================================================================
736*/
da91b269 737static int pci1760_reset(struct comedi_device *dev)
ebd127c3 738{
242f5223 739 struct pci_dio_private *devpriv = dev->private;
ebd127c3
MD
740 int i;
741 unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
742 unsigned char imb[4];
743
ba23095c 744 outb(0, dev->iobase + INTCSR0); /* disable IRQ */
ebd127c3
MD
745 outb(0, dev->iobase + INTCSR1);
746 outb(0, dev->iobase + INTCSR2);
747 outb(0, dev->iobase + INTCSR3);
748 devpriv->GlobalIrqEnabled = 0;
749
750 omb[0] = 0x00;
ba23095c 751 omb[2] = CMD_SetRelaysOutput; /* reset relay outputs */
ebd127c3
MD
752 pci1760_mbxrequest(dev, omb, imb);
753
754 omb[0] = 0x00;
ba23095c 755 omb[2] = CMD_EnableIDICounters; /* disable IDI up counters */
ebd127c3
MD
756 pci1760_mbxrequest(dev, omb, imb);
757 devpriv->IDICntEnable = 0;
758
759 omb[0] = 0x00;
3afbe13c
M
760 omb[2] = CMD_OverflowIDICounters; /* disable counters overflow
761 * interrupts */
ebd127c3
MD
762 pci1760_mbxrequest(dev, omb, imb);
763 devpriv->IDICntOverEnable = 0;
764
765 omb[0] = 0x00;
3afbe13c
M
766 omb[2] = CMD_MatchIntIDICounters; /* disable counters match value
767 * interrupts */
ebd127c3
MD
768 pci1760_mbxrequest(dev, omb, imb);
769 devpriv->IDICntMatchEnable = 0;
770
771 omb[0] = 0x00;
772 omb[1] = 0x80;
ba23095c 773 for (i = 0; i < 8; i++) { /* set IDI up counters match value */
ebd127c3
MD
774 omb[2] = CMD_SetIDI0CntMatchValue + i;
775 pci1760_mbxrequest(dev, omb, imb);
776 devpriv->CntMatchValue[i] = 0x8000;
777 }
778
779 omb[0] = 0x00;
780 omb[1] = 0x00;
ba23095c 781 for (i = 0; i < 8; i++) { /* set IDI up counters reset value */
ebd127c3
MD
782 omb[2] = CMD_SetIDI0CntResetValue + i;
783 pci1760_mbxrequest(dev, omb, imb);
784 devpriv->CntResValue[i] = 0x0000;
785 }
786
787 omb[0] = 0xff;
3afbe13c
M
788 omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset
789 * values */
ebd127c3
MD
790 pci1760_mbxrequest(dev, omb, imb);
791
792 omb[0] = 0x00;
ba23095c 793 omb[2] = CMD_EdgeIDICounters; /* set IDI up counters count edge */
ebd127c3
MD
794 pci1760_mbxrequest(dev, omb, imb);
795 devpriv->IDICntEdge = 0x00;
796
797 omb[0] = 0x00;
ba23095c 798 omb[2] = CMD_EnableIDIFilters; /* disable all digital in filters */
ebd127c3
MD
799 pci1760_mbxrequest(dev, omb, imb);
800 devpriv->IDIFiltersEn = 0x00;
801
802 omb[0] = 0x00;
ba23095c 803 omb[2] = CMD_EnableIDIPatternMatch; /* disable pattern matching */
ebd127c3
MD
804 pci1760_mbxrequest(dev, omb, imb);
805 devpriv->IDIPatMatchEn = 0x00;
806
807 omb[0] = 0x00;
ba23095c 808 omb[2] = CMD_SetIDIPatternMatch; /* set pattern match value */
ebd127c3
MD
809 pci1760_mbxrequest(dev, omb, imb);
810 devpriv->IDIPatMatchValue = 0x00;
811
812 return 0;
813}
814
815/*
816==============================================================================
817*/
da91b269 818static int pci_dio_reset(struct comedi_device *dev)
ebd127c3 819{
bb5c7f93 820 const struct dio_boardtype *this_board = dev->board_ptr;
242f5223 821
ebd127c3
MD
822 switch (this_board->cardtype) {
823 case TYPE_PCI1730:
ba23095c 824 outb(0, dev->iobase + PCI1730_DO); /* clear outputs */
ebd127c3
MD
825 outb(0, dev->iobase + PCI1730_DO + 1);
826 outb(0, dev->iobase + PCI1730_IDO);
827 outb(0, dev->iobase + PCI1730_IDO + 1);
de33276b 828 /* fallthrough */
ebd127c3 829 case TYPE_PCI1733:
3afbe13c
M
830 /* disable interrupts */
831 outb(0, dev->iobase + PCI1730_3_INT_EN);
832 /* clear interrupts */
833 outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);
834 /* set rising edge trigger */
835 outb(0, dev->iobase + PCI1730_3_INT_RF);
ebd127c3
MD
836 break;
837 case TYPE_PCI1734:
ba23095c 838 outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
ebd127c3
MD
839 outb(0, dev->iobase + PCI1734_IDO + 1);
840 outb(0, dev->iobase + PCI1734_IDO + 2);
841 outb(0, dev->iobase + PCI1734_IDO + 3);
842 break;
d4da77a7
IA
843 case TYPE_PCI1735:
844 outb(0, dev->iobase + PCI1735_DO); /* clear outputs */
845 outb(0, dev->iobase + PCI1735_DO + 1);
846 outb(0, dev->iobase + PCI1735_DO + 2);
847 outb(0, dev->iobase + PCI1735_DO + 3);
848 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
849 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
850 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
851 break;
ebd127c3
MD
852
853 case TYPE_PCI1736:
0a85b6f0
MT
854 outb(0, dev->iobase + PCI1736_IDO);
855 outb(0, dev->iobase + PCI1736_IDO + 1);
3afbe13c
M
856 /* disable interrupts */
857 outb(0, dev->iobase + PCI1736_3_INT_EN);
858 /* clear interrupts */
859 outb(0x0f, dev->iobase + PCI1736_3_INT_CLR);
860 /* set rising edge trigger */
861 outb(0, dev->iobase + PCI1736_3_INT_RF);
ebd127c3
MD
862 break;
863
9e77e6b6
IA
864 case TYPE_PCI1739:
865 /* disable & clear interrupts */
866 outb(0x88, dev->iobase + PCI1739_ICR);
867 break;
868
ebd127c3
MD
869 case TYPE_PCI1750:
870 case TYPE_PCI1751:
3afbe13c
M
871 /* disable & clear interrupts */
872 outb(0x88, dev->iobase + PCI1750_ICR);
ebd127c3
MD
873 break;
874 case TYPE_PCI1752:
3afbe13c
M
875 outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
876 * function */
ba23095c 877 outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */
ebd127c3
MD
878 outw(0, dev->iobase + PCI1752_IDO + 2);
879 outw(0, dev->iobase + PCI1752_IDO2);
880 outw(0, dev->iobase + PCI1752_IDO2 + 2);
881 break;
882 case TYPE_PCI1753E:
3afbe13c
M
883 outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear
884 * interrupts */
ebd127c3
MD
885 outb(0x80, dev->iobase + PCI1753E_ICR1);
886 outb(0x80, dev->iobase + PCI1753E_ICR2);
887 outb(0x80, dev->iobase + PCI1753E_ICR3);
de33276b 888 /* fallthrough */
ebd127c3 889 case TYPE_PCI1753:
3afbe13c
M
890 outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear
891 * interrupts */
ebd127c3
MD
892 outb(0x80, dev->iobase + PCI1753_ICR1);
893 outb(0x80, dev->iobase + PCI1753_ICR2);
894 outb(0x80, dev->iobase + PCI1753_ICR3);
895 break;
896 case TYPE_PCI1754:
3afbe13c
M
897 outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
898 * interrupts */
ebd127c3
MD
899 outw(0x08, dev->iobase + PCI1754_6_ICR1);
900 outw(0x08, dev->iobase + PCI1754_ICR2);
901 outw(0x08, dev->iobase + PCI1754_ICR3);
902 break;
903 case TYPE_PCI1756:
3afbe13c
M
904 outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
905 * function */
906 outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
907 * interrupts */
ebd127c3 908 outw(0x08, dev->iobase + PCI1754_6_ICR1);
ba23095c 909 outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
ebd127c3
MD
910 outw(0, dev->iobase + PCI1756_IDO + 2);
911 break;
912 case TYPE_PCI1760:
913 pci1760_reset(dev);
914 break;
915 case TYPE_PCI1762:
3afbe13c
M
916 outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear
917 * interrupts */
ebd127c3
MD
918 break;
919 }
920
ebd127c3
MD
921 return 0;
922}
923
924/*
925==============================================================================
926*/
e5200165 927static int pci1760_attach(struct comedi_device *dev)
ebd127c3 928{
34c43922 929 struct comedi_subdevice *s;
ebd127c3 930
a2b7bcac 931 s = &dev->subdevices[0];
ebd127c3
MD
932 s->type = COMEDI_SUBD_DI;
933 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
934 s->n_chan = 8;
935 s->maxdata = 1;
936 s->len_chanlist = 8;
937 s->range_table = &range_digital;
938 s->insn_bits = pci1760_insn_bits_di;
ebd127c3 939
a2b7bcac 940 s = &dev->subdevices[1];
ebd127c3
MD
941 s->type = COMEDI_SUBD_DO;
942 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
943 s->n_chan = 8;
944 s->maxdata = 1;
945 s->len_chanlist = 8;
946 s->range_table = &range_digital;
947 s->state = 0;
948 s->insn_bits = pci1760_insn_bits_do;
ebd127c3 949
a2b7bcac 950 s = &dev->subdevices[2];
ebd127c3
MD
951 s->type = COMEDI_SUBD_TIMER;
952 s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL;
953 s->n_chan = 2;
954 s->maxdata = 0xffffffff;
955 s->len_chanlist = 2;
ba23095c 956/* s->insn_config=pci1760_insn_pwm_cfg; */
ebd127c3 957
a2b7bcac 958 s = &dev->subdevices[3];
ebd127c3
MD
959 s->type = COMEDI_SUBD_COUNTER;
960 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
961 s->n_chan = 8;
962 s->maxdata = 0xffff;
963 s->len_chanlist = 8;
964 s->insn_read = pci1760_insn_cnt_read;
965 s->insn_write = pci1760_insn_cnt_write;
ba23095c 966/* s->insn_config=pci1760_insn_cnt_cfg; */
ebd127c3
MD
967
968 return 0;
969}
970
971/*
972==============================================================================
973*/
9e006a70
HS
974static int pci_dio_add_di(struct comedi_device *dev,
975 struct comedi_subdevice *s,
976 const struct diosubd_data *d)
ebd127c3 977{
bb5c7f93 978 const struct dio_boardtype *this_board = dev->board_ptr;
242f5223 979
ebd127c3
MD
980 s->type = COMEDI_SUBD_DI;
981 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
982 if (d->chans > 16)
983 s->subdev_flags |= SDF_LSAMPL;
984 s->n_chan = d->chans;
985 s->maxdata = 1;
986 s->len_chanlist = d->chans;
987 s->range_table = &range_digital;
988 switch (this_board->io_access) {
989 case IO_8b:
990 s->insn_bits = pci_dio_insn_bits_di_b;
991 break;
992 case IO_16b:
993 s->insn_bits = pci_dio_insn_bits_di_w;
994 break;
995 }
996 s->private = (void *)d;
997
998 return 0;
999}
1000
1001/*
1002==============================================================================
1003*/
9e006a70
HS
1004static int pci_dio_add_do(struct comedi_device *dev,
1005 struct comedi_subdevice *s,
1006 const struct diosubd_data *d)
ebd127c3 1007{
bb5c7f93 1008 const struct dio_boardtype *this_board = dev->board_ptr;
242f5223 1009
ebd127c3
MD
1010 s->type = COMEDI_SUBD_DO;
1011 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1012 if (d->chans > 16)
1013 s->subdev_flags |= SDF_LSAMPL;
1014 s->n_chan = d->chans;
1015 s->maxdata = 1;
1016 s->len_chanlist = d->chans;
1017 s->range_table = &range_digital;
1018 s->state = 0;
1019 switch (this_board->io_access) {
1020 case IO_8b:
1021 s->insn_bits = pci_dio_insn_bits_do_b;
1022 break;
1023 case IO_16b:
1024 s->insn_bits = pci_dio_insn_bits_do_w;
1025 break;
1026 }
1027 s->private = (void *)d;
1028
1029 return 0;
1030}
1031
d4da77a7
IA
1032/*
1033==============================================================================
1034*/
1035static int pci_dio_add_8254(struct comedi_device *dev,
3afbe13c 1036 struct comedi_subdevice *s,
9e006a70 1037 const struct diosubd_data *d)
d4da77a7
IA
1038{
1039 s->type = COMEDI_SUBD_COUNTER;
1040 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1041 s->n_chan = d->chans;
1042 s->maxdata = 65535;
1043 s->len_chanlist = d->chans;
1044 s->insn_read = pci_8254_insn_read;
1045 s->insn_write = pci_8254_insn_write;
1046 s->insn_config = pci_8254_insn_config;
1047 s->private = (void *)d;
1048
1049 return 0;
1050}
1051
87f6991b
IA
1052static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
1053 unsigned long cardtype)
1054{
1055 /*
1056 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
1057 * board available. Need to enable PCI device and request the main
1058 * registers PCI BAR temporarily to perform the test.
1059 */
1060 if (cardtype != TYPE_PCI1753)
1061 return cardtype;
1062 if (pci_enable_device(pcidev) < 0)
1063 return cardtype;
1064 if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) {
1065 /*
1066 * This test is based on Advantech's "advdaq" driver source
1067 * (which declares its module licence as "GPL" although the
1068 * driver source does not include a "COPYING" file).
1069 */
1070 unsigned long reg =
1071 pci_resource_start(pcidev, PCIDIO_MAINREG) + 53;
1072
1073 outb(0x05, reg);
1074 if ((inb(reg) & 0x07) == 0x02) {
1075 outb(0x02, reg);
1076 if ((inb(reg) & 0x07) == 0x05)
1077 cardtype = TYPE_PCI1753E;
1078 }
1079 pci_release_region(pcidev, PCIDIO_MAINREG);
1080 }
1081 pci_disable_device(pcidev);
1082 return cardtype;
1083}
1084
a690b7e5 1085static int pci_dio_auto_attach(struct comedi_device *dev,
c0a0e0ca 1086 unsigned long context)
54b303c4 1087{
750af5e5 1088 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
c0a0e0ca 1089 const struct dio_boardtype *this_board = NULL;
242f5223 1090 struct pci_dio_private *devpriv;
54b303c4 1091 struct comedi_subdevice *s;
4bf75257 1092 int ret, subdev, i, j;
54b303c4 1093
c0a0e0ca
HS
1094 if (context < ARRAY_SIZE(boardtypes))
1095 this_board = &boardtypes[context];
e5200165
HS
1096 if (!this_board)
1097 return -ENODEV;
1098 dev->board_ptr = this_board;
1099 dev->board_name = this_board->name;
1100
0bdab509 1101 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
c34fa261
HS
1102 if (!devpriv)
1103 return -ENOMEM;
54b303c4 1104
818f569f 1105 ret = comedi_pci_enable(dev);
242f5223
HS
1106 if (ret)
1107 return ret;
983ff488 1108 dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
ebd127c3 1109
4bf75257 1110 ret = comedi_alloc_subdevices(dev, this_board->nsubdevs);
8b6c5694 1111 if (ret)
ebd127c3 1112 return ret;
ebd127c3
MD
1113
1114 subdev = 0;
ebd127c3
MD
1115 for (i = 0; i < MAX_DI_SUBDEVS; i++)
1116 if (this_board->sdi[i].chans) {
2b36ab6c 1117 s = &dev->subdevices[subdev];
9e006a70 1118 pci_dio_add_di(dev, s, &this_board->sdi[i]);
ebd127c3
MD
1119 subdev++;
1120 }
1121
1122 for (i = 0; i < MAX_DO_SUBDEVS; i++)
1123 if (this_board->sdo[i].chans) {
2b36ab6c 1124 s = &dev->subdevices[subdev];
9e006a70 1125 pci_dio_add_do(dev, s, &this_board->sdo[i]);
ebd127c3
MD
1126 subdev++;
1127 }
1128
1129 for (i = 0; i < MAX_DIO_SUBDEVG; i++)
1130 for (j = 0; j < this_board->sdio[i].regs; j++) {
2b36ab6c 1131 s = &dev->subdevices[subdev];
e6439a45 1132 ret = subdev_8255_init(dev, s, NULL,
e6439a45 1133 this_board->sdio[i].addr +
f0162091 1134 j * I8255_SIZE);
e6439a45
HS
1135 if (ret)
1136 return ret;
ebd127c3
MD
1137 subdev++;
1138 }
1139
1140 if (this_board->boardid.chans) {
2b36ab6c 1141 s = &dev->subdevices[subdev];
ebd127c3 1142 s->type = COMEDI_SUBD_DI;
9e006a70 1143 pci_dio_add_di(dev, s, &this_board->boardid);
ebd127c3
MD
1144 subdev++;
1145 }
1146
d4da77a7
IA
1147 for (i = 0; i < MAX_8254_SUBDEVS; i++)
1148 if (this_board->s8254[i].chans) {
2b36ab6c 1149 s = &dev->subdevices[subdev];
9e006a70 1150 pci_dio_add_8254(dev, s, &this_board->s8254[i]);
d4da77a7
IA
1151 subdev++;
1152 }
1153
ebd127c3 1154 if (this_board->cardtype == TYPE_PCI1760)
e5200165 1155 pci1760_attach(dev);
ebd127c3 1156
ebd127c3
MD
1157 pci_dio_reset(dev);
1158
1159 return 0;
1160}
1161
484ecc95 1162static void pci_dio_detach(struct comedi_device *dev)
ebd127c3 1163{
6ab5db9c
HS
1164 if (dev->iobase)
1165 pci_dio_reset(dev);
aac307f9 1166 comedi_pci_detach(dev);
ebd127c3
MD
1167}
1168
c95dbeac
HS
1169static struct comedi_driver adv_pci_dio_driver = {
1170 .driver_name = "adv_pci_dio",
1171 .module = THIS_MODULE,
750af5e5 1172 .auto_attach = pci_dio_auto_attach,
e5200165 1173 .detach = pci_dio_detach,
c95dbeac
HS
1174};
1175
a690b7e5 1176static int adv_pci_dio_pci_probe(struct pci_dev *dev,
b8f4ac23 1177 const struct pci_device_id *id)
727b286b 1178{
87f6991b
IA
1179 unsigned long cardtype;
1180
1181 cardtype = pci_dio_override_cardtype(dev, id->driver_data);
1182 return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
727b286b
AT
1183}
1184
41e043fc 1185static const struct pci_device_id adv_pci_dio_pci_table[] = {
87f6991b
IA
1186 { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
1187 { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
1188 { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
1189 { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
1190 { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
1191 { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
1192 { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
1193 { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
1194 { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
1195 { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
1196 { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
1197 { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
1198 { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 },
1199 { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
c95dbeac 1200 { 0 }
727b286b 1201};
c95dbeac 1202MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
727b286b 1203
c95dbeac
HS
1204static struct pci_driver adv_pci_dio_pci_driver = {
1205 .name = "adv_pci_dio",
1206 .id_table = adv_pci_dio_pci_table,
1207 .probe = adv_pci_dio_pci_probe,
9901a4d7 1208 .remove = comedi_pci_auto_unconfig,
c95dbeac
HS
1209};
1210module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
90f703d3
AT
1211
1212MODULE_AUTHOR("Comedi http://www.comedi.org");
1213MODULE_DESCRIPTION("Comedi low-level driver");
1214MODULE_LICENSE("GPL");
This page took 0.735009 seconds and 5 git commands to generate.