staging: comedi: adv_pci_dio: remove 'main_pci_region' boardinfo
[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.
74409905 7 */
ebd127c3 8
74409905
HS
9/*
10 * Driver: adv_pci_dio
11 * Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
12 * PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752,
13 * PCI-1753/E, PCI-1754, PCI-1756, PCI-1762
14 * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
15 * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750,
16 * PCI-1751, PCI-1752, PCI-1753,
17 * PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
18 * PCI-1762
19 * Author: Michal Dobes <dobes@tesnet.cz>
20 * Updated: Mon, 09 Jan 2012 12:40:46 +0000
21 * Status: untested
22 *
23 * Configuration Options: not applicable, uses PCI auto config
24 */
ebd127c3 25
ce157f80 26#include <linux/module.h>
ebd127c3
MD
27#include <linux/delay.h>
28
5f22dadd 29#include "../comedi_pci.h"
33782dd5 30
ebd127c3 31#include "8255.h"
1e1fe085 32#include "comedi_8254.h"
ebd127c3 33
a8f1152e
BP
34/* hardware types of the cards */
35enum hw_cards_id {
d4da77a7 36 TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
9e77e6b6 37 TYPE_PCI1739,
ebd127c3
MD
38 TYPE_PCI1750,
39 TYPE_PCI1751,
40 TYPE_PCI1752,
41 TYPE_PCI1753, TYPE_PCI1753E,
42 TYPE_PCI1754, TYPE_PCI1756,
ebd127c3 43 TYPE_PCI1762
a8f1152e 44};
ebd127c3 45
a8f1152e
BP
46/* which I/O instructions to use */
47enum hw_io_access {
ebd127c3 48 IO_8b, IO_16b
a8f1152e 49};
ebd127c3
MD
50
51#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
52#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
3afbe13c
M
53#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
54 * card */
ebd127c3 55
ebd127c3 56/* Register offset definitions */
ba23095c 57/* Advantech PCI-1730/3/4 */
ebd127c3
MD
58#define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */
59#define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */
60#define PCI1730_DI 2 /* R: Digital input 0-15 */
61#define PCI1730_DO 2 /* W: Digital output 0-15 */
62#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
63#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
3afbe13c
M
64#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for
65 * interrupts */
ebd127c3
MD
66#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
67#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
68#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
69
d4da77a7
IA
70/* Advantech PCI-1735U */
71#define PCI1735_DI 0 /* R: Digital input 0-31 */
72#define PCI1735_DO 0 /* W: Digital output 0-31 */
73#define PCI1735_C8254 4 /* R/W: 8254 counter */
74#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */
75
ba23095c 76/* Advantech PCI-1736UP */
0a85b6f0
MT
77#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
78#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
79#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
3afbe13c
M
80#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for
81 * interrupts */
0a85b6f0
MT
82#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
83#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */
ebd127c3 84
9e77e6b6
IA
85/* Advantech PCI-1739U */
86#define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */
87#define PCI1739_ICR 32 /* W: Interrupt control register */
88#define PCI1739_ISR 32 /* R: Interrupt status register */
89#define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */
90
ba23095c 91/* Advantech PCI-1750 */
ebd127c3
MD
92#define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */
93#define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */
94#define PCI1750_ICR 32 /* W: Interrupt control register */
95#define PCI1750_ISR 32 /* R: Interrupt status register */
96
ba23095c 97/* Advantech PCI-1751/3/3E */
ebd127c3 98#define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */
cfe3cffd 99#define PCI1751_CNT 24 /* R/W: begin of 8254 registers block */
ebd127c3
MD
100#define PCI1751_ICR 32 /* W: Interrupt control register */
101#define PCI1751_ISR 32 /* R: Interrupt status register */
102#define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */
103#define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */
104#define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */
105#define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */
106#define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */
107#define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */
108#define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */
109#define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */
110#define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */
111#define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */
112
ba23095c 113/* Advantech PCI-1752/4/6 */
ebd127c3
MD
114#define PCI1752_IDO 0 /* R/W: Digital output 0-31 */
115#define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */
116#define PCI1754_IDI 0 /* R: Digital input 0-31 */
117#define PCI1754_IDI2 4 /* R: Digital input 32-64 */
118#define PCI1756_IDI 0 /* R: Digital input 0-31 */
119#define PCI1756_IDO 4 /* R/W: Digital output 0-31 */
120#define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */
121#define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */
122#define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */
123#define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */
124#define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */
125#define PCI175x_BOARDID 0x10 /* R: Board I/D switch for 1752/4/6 */
126
ba23095c 127/* Advantech PCI-1762 registers */
ebd127c3
MD
128#define PCI1762_RO 0 /* R/W: Relays status/output */
129#define PCI1762_IDI 2 /* R: Isolated input status */
130#define PCI1762_BOARDID 4 /* R: Board I/D switch */
131#define PCI1762_ICR 6 /* W: Interrupt control register */
132#define PCI1762_ISR 6 /* R: Interrupt status register */
133
673bc56a 134struct diosubd_data {
ba23095c
BP
135 int chans; /* num of chans */
136 int addr; /* PCI address ofset */
d4da77a7 137 int regs; /* number of registers to read or 8255
0275299f 138 subdevices */
ba23095c 139 unsigned int specflags; /* addon subdevice flags */
673bc56a 140};
ebd127c3 141
dea1776a 142struct dio_boardtype {
ba23095c 143 const char *name; /* board name */
a8f1152e 144 enum hw_cards_id cardtype;
4bf75257 145 int nsubdevs;
ba23095c
BP
146 struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */
147 struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
148 struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
149 struct diosubd_data boardid; /* card supports board ID switch */
0275299f 150 unsigned long timer_regbase;
a8f1152e 151 enum hw_io_access io_access;
dea1776a 152};
ebd127c3 153
dea1776a 154static const struct dio_boardtype boardtypes[] = {
87f6991b 155 [TYPE_PCI1730] = {
59bd6752 156 .name = "pci1730",
59bd6752 157 .cardtype = TYPE_PCI1730,
4bf75257 158 .nsubdevs = 5,
59bd6752
HS
159 .sdi[0] = { 16, PCI1730_DI, 2, 0, },
160 .sdi[1] = { 16, PCI1730_IDI, 2, 0, },
161 .sdo[0] = { 16, PCI1730_DO, 2, 0, },
162 .sdo[1] = { 16, PCI1730_IDO, 2, 0, },
59bd6752 163 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 164 .io_access = IO_8b,
c0a0e0ca 165 },
87f6991b 166 [TYPE_PCI1733] = {
59bd6752 167 .name = "pci1733",
59bd6752 168 .cardtype = TYPE_PCI1733,
4bf75257 169 .nsubdevs = 2,
59bd6752 170 .sdi[1] = { 32, PCI1733_IDI, 4, 0, },
59bd6752 171 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 172 .io_access = IO_8b,
c0a0e0ca 173 },
87f6991b 174 [TYPE_PCI1734] = {
59bd6752 175 .name = "pci1734",
59bd6752 176 .cardtype = TYPE_PCI1734,
4bf75257 177 .nsubdevs = 2,
59bd6752 178 .sdo[1] = { 32, PCI1734_IDO, 4, 0, },
59bd6752 179 .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 180 .io_access = IO_8b,
c0a0e0ca 181 },
87f6991b 182 [TYPE_PCI1735] = {
59bd6752 183 .name = "pci1735",
59bd6752 184 .cardtype = TYPE_PCI1735,
4bf75257 185 .nsubdevs = 4,
59bd6752 186 .sdi[0] = { 32, PCI1735_DI, 4, 0, },
59bd6752 187 .sdo[0] = { 32, PCI1735_DO, 4, 0, },
59bd6752 188 .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
0275299f 189 .timer_regbase = PCI1735_C8254,
59bd6752 190 .io_access = IO_8b,
c0a0e0ca 191 },
87f6991b 192 [TYPE_PCI1736] = {
59bd6752 193 .name = "pci1736",
59bd6752 194 .cardtype = TYPE_PCI1736,
4bf75257 195 .nsubdevs = 3,
59bd6752 196 .sdi[1] = { 16, PCI1736_IDI, 2, 0, },
59bd6752 197 .sdo[1] = { 16, PCI1736_IDO, 2, 0, },
59bd6752 198 .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
59bd6752 199 .io_access = IO_8b,
c0a0e0ca 200 },
87f6991b 201 [TYPE_PCI1739] = {
59bd6752 202 .name = "pci1739",
59bd6752 203 .cardtype = TYPE_PCI1739,
4bf75257 204 .nsubdevs = 2,
59bd6752 205 .sdio[0] = { 48, PCI1739_DIO, 2, 0, },
59bd6752 206 .io_access = IO_8b,
c0a0e0ca 207 },
87f6991b 208 [TYPE_PCI1750] = {
59bd6752 209 .name = "pci1750",
59bd6752 210 .cardtype = TYPE_PCI1750,
4bf75257 211 .nsubdevs = 2,
59bd6752 212 .sdi[1] = { 16, PCI1750_IDI, 2, 0, },
59bd6752 213 .sdo[1] = { 16, PCI1750_IDO, 2, 0, },
59bd6752 214 .io_access = IO_8b,
c0a0e0ca 215 },
87f6991b 216 [TYPE_PCI1751] = {
59bd6752 217 .name = "pci1751",
59bd6752 218 .cardtype = TYPE_PCI1751,
4bf75257 219 .nsubdevs = 3,
59bd6752 220 .sdio[0] = { 48, PCI1751_DIO, 2, 0, },
0275299f 221 .timer_regbase = PCI1751_CNT,
59bd6752 222 .io_access = IO_8b,
c0a0e0ca 223 },
87f6991b 224 [TYPE_PCI1752] = {
59bd6752 225 .name = "pci1752",
59bd6752 226 .cardtype = TYPE_PCI1752,
4bf75257 227 .nsubdevs = 3,
59bd6752
HS
228 .sdo[0] = { 32, PCI1752_IDO, 2, 0, },
229 .sdo[1] = { 32, PCI1752_IDO2, 2, 0, },
59bd6752 230 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 231 .io_access = IO_16b,
c0a0e0ca 232 },
87f6991b 233 [TYPE_PCI1753] = {
59bd6752 234 .name = "pci1753",
59bd6752 235 .cardtype = TYPE_PCI1753,
4bf75257 236 .nsubdevs = 4,
59bd6752 237 .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
59bd6752 238 .io_access = IO_8b,
87f6991b
IA
239 },
240 [TYPE_PCI1753E] = {
59bd6752 241 .name = "pci1753e",
59bd6752 242 .cardtype = TYPE_PCI1753E,
4bf75257 243 .nsubdevs = 8,
59bd6752
HS
244 .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
245 .sdio[1] = { 96, PCI1753E_DIO, 4, 0, },
59bd6752 246 .io_access = IO_8b,
c0a0e0ca 247 },
87f6991b 248 [TYPE_PCI1754] = {
59bd6752 249 .name = "pci1754",
59bd6752 250 .cardtype = TYPE_PCI1754,
4bf75257 251 .nsubdevs = 3,
59bd6752
HS
252 .sdi[0] = { 32, PCI1754_IDI, 2, 0, },
253 .sdi[1] = { 32, PCI1754_IDI2, 2, 0, },
59bd6752 254 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 255 .io_access = IO_16b,
c0a0e0ca 256 },
87f6991b 257 [TYPE_PCI1756] = {
59bd6752 258 .name = "pci1756",
59bd6752 259 .cardtype = TYPE_PCI1756,
4bf75257 260 .nsubdevs = 3,
59bd6752 261 .sdi[1] = { 32, PCI1756_IDI, 2, 0, },
59bd6752 262 .sdo[1] = { 32, PCI1756_IDO, 2, 0, },
59bd6752 263 .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
59bd6752 264 .io_access = IO_16b,
c0a0e0ca 265 },
87f6991b 266 [TYPE_PCI1762] = {
59bd6752 267 .name = "pci1762",
59bd6752 268 .cardtype = TYPE_PCI1762,
4bf75257 269 .nsubdevs = 3,
59bd6752 270 .sdi[1] = { 16, PCI1762_IDI, 1, 0, },
59bd6752 271 .sdo[1] = { 16, PCI1762_RO, 1, 0, },
59bd6752 272 .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, },
59bd6752
HS
273 .io_access = IO_16b,
274 },
ebd127c3
MD
275};
276
0a85b6f0
MT
277static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
278 struct comedi_subdevice *s,
279 struct comedi_insn *insn, unsigned int *data)
ebd127c3 280{
673bc56a 281 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
282 int i;
283
284 data[1] = 0;
402a01ae 285 for (i = 0; i < d->regs; i++)
ebd127c3 286 data[1] |= inb(dev->iobase + d->addr + i) << (8 * i);
402a01ae 287
a2714e3e 288 return insn->n;
ebd127c3
MD
289}
290
0a85b6f0
MT
291static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
292 struct comedi_subdevice *s,
293 struct comedi_insn *insn, unsigned int *data)
ebd127c3 294{
673bc56a 295 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
296 int i;
297
298 data[1] = 0;
299 for (i = 0; i < d->regs; i++)
300 data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i);
301
a2714e3e 302 return insn->n;
ebd127c3
MD
303}
304
0a85b6f0
MT
305static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
306 struct comedi_subdevice *s,
97f4289a
HS
307 struct comedi_insn *insn,
308 unsigned int *data)
ebd127c3 309{
673bc56a 310 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
311 int i;
312
97f4289a 313 if (comedi_dio_update_state(s, data)) {
ebd127c3
MD
314 for (i = 0; i < d->regs; i++)
315 outb((s->state >> (8 * i)) & 0xff,
0a85b6f0 316 dev->iobase + d->addr + i);
ebd127c3 317 }
97f4289a 318
ebd127c3
MD
319 data[1] = s->state;
320
a2714e3e 321 return insn->n;
ebd127c3
MD
322}
323
0a85b6f0
MT
324static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
325 struct comedi_subdevice *s,
97f4289a
HS
326 struct comedi_insn *insn,
327 unsigned int *data)
ebd127c3 328{
673bc56a 329 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
ebd127c3
MD
330 int i;
331
97f4289a 332 if (comedi_dio_update_state(s, data)) {
ebd127c3
MD
333 for (i = 0; i < d->regs; i++)
334 outw((s->state >> (16 * i)) & 0xffff,
0a85b6f0 335 dev->iobase + d->addr + 2 * i);
ebd127c3 336 }
97f4289a 337
ebd127c3
MD
338 data[1] = s->state;
339
a2714e3e 340 return insn->n;
ebd127c3
MD
341}
342
da91b269 343static int pci_dio_reset(struct comedi_device *dev)
ebd127c3 344{
1a127f31 345 const struct dio_boardtype *board = dev->board_ptr;
242f5223 346
1a127f31 347 switch (board->cardtype) {
ebd127c3 348 case TYPE_PCI1730:
ba23095c 349 outb(0, dev->iobase + PCI1730_DO); /* clear outputs */
ebd127c3
MD
350 outb(0, dev->iobase + PCI1730_DO + 1);
351 outb(0, dev->iobase + PCI1730_IDO);
352 outb(0, dev->iobase + PCI1730_IDO + 1);
de33276b 353 /* fallthrough */
ebd127c3 354 case TYPE_PCI1733:
3afbe13c
M
355 /* disable interrupts */
356 outb(0, dev->iobase + PCI1730_3_INT_EN);
357 /* clear interrupts */
358 outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);
359 /* set rising edge trigger */
360 outb(0, dev->iobase + PCI1730_3_INT_RF);
ebd127c3
MD
361 break;
362 case TYPE_PCI1734:
ba23095c 363 outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
ebd127c3
MD
364 outb(0, dev->iobase + PCI1734_IDO + 1);
365 outb(0, dev->iobase + PCI1734_IDO + 2);
366 outb(0, dev->iobase + PCI1734_IDO + 3);
367 break;
d4da77a7
IA
368 case TYPE_PCI1735:
369 outb(0, dev->iobase + PCI1735_DO); /* clear outputs */
370 outb(0, dev->iobase + PCI1735_DO + 1);
371 outb(0, dev->iobase + PCI1735_DO + 2);
372 outb(0, dev->iobase + PCI1735_DO + 3);
d4da77a7 373 break;
ebd127c3
MD
374
375 case TYPE_PCI1736:
0a85b6f0
MT
376 outb(0, dev->iobase + PCI1736_IDO);
377 outb(0, dev->iobase + PCI1736_IDO + 1);
3afbe13c
M
378 /* disable interrupts */
379 outb(0, dev->iobase + PCI1736_3_INT_EN);
380 /* clear interrupts */
381 outb(0x0f, dev->iobase + PCI1736_3_INT_CLR);
382 /* set rising edge trigger */
383 outb(0, dev->iobase + PCI1736_3_INT_RF);
ebd127c3
MD
384 break;
385
9e77e6b6
IA
386 case TYPE_PCI1739:
387 /* disable & clear interrupts */
388 outb(0x88, dev->iobase + PCI1739_ICR);
389 break;
390
ebd127c3
MD
391 case TYPE_PCI1750:
392 case TYPE_PCI1751:
3afbe13c
M
393 /* disable & clear interrupts */
394 outb(0x88, dev->iobase + PCI1750_ICR);
ebd127c3
MD
395 break;
396 case TYPE_PCI1752:
3afbe13c
M
397 outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
398 * function */
ba23095c 399 outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */
ebd127c3
MD
400 outw(0, dev->iobase + PCI1752_IDO + 2);
401 outw(0, dev->iobase + PCI1752_IDO2);
402 outw(0, dev->iobase + PCI1752_IDO2 + 2);
403 break;
404 case TYPE_PCI1753E:
3afbe13c
M
405 outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear
406 * interrupts */
ebd127c3
MD
407 outb(0x80, dev->iobase + PCI1753E_ICR1);
408 outb(0x80, dev->iobase + PCI1753E_ICR2);
409 outb(0x80, dev->iobase + PCI1753E_ICR3);
de33276b 410 /* fallthrough */
ebd127c3 411 case TYPE_PCI1753:
3afbe13c
M
412 outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear
413 * interrupts */
ebd127c3
MD
414 outb(0x80, dev->iobase + PCI1753_ICR1);
415 outb(0x80, dev->iobase + PCI1753_ICR2);
416 outb(0x80, dev->iobase + PCI1753_ICR3);
417 break;
418 case TYPE_PCI1754:
3afbe13c
M
419 outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
420 * interrupts */
ebd127c3
MD
421 outw(0x08, dev->iobase + PCI1754_6_ICR1);
422 outw(0x08, dev->iobase + PCI1754_ICR2);
423 outw(0x08, dev->iobase + PCI1754_ICR3);
424 break;
425 case TYPE_PCI1756:
3afbe13c
M
426 outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
427 * function */
428 outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
429 * interrupts */
ebd127c3 430 outw(0x08, dev->iobase + PCI1754_6_ICR1);
ba23095c 431 outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
ebd127c3
MD
432 outw(0, dev->iobase + PCI1756_IDO + 2);
433 break;
ebd127c3 434 case TYPE_PCI1762:
3afbe13c
M
435 outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear
436 * interrupts */
ebd127c3
MD
437 break;
438 }
439
ebd127c3
MD
440 return 0;
441}
442
9e006a70
HS
443static int pci_dio_add_di(struct comedi_device *dev,
444 struct comedi_subdevice *s,
445 const struct diosubd_data *d)
ebd127c3 446{
1a127f31 447 const struct dio_boardtype *board = dev->board_ptr;
242f5223 448
ebd127c3 449 s->type = COMEDI_SUBD_DI;
e0025918 450 s->subdev_flags = SDF_READABLE | d->specflags;
ebd127c3
MD
451 if (d->chans > 16)
452 s->subdev_flags |= SDF_LSAMPL;
453 s->n_chan = d->chans;
454 s->maxdata = 1;
455 s->len_chanlist = d->chans;
456 s->range_table = &range_digital;
1a127f31 457 switch (board->io_access) {
ebd127c3
MD
458 case IO_8b:
459 s->insn_bits = pci_dio_insn_bits_di_b;
460 break;
461 case IO_16b:
462 s->insn_bits = pci_dio_insn_bits_di_w;
463 break;
464 }
465 s->private = (void *)d;
466
467 return 0;
468}
469
9e006a70
HS
470static int pci_dio_add_do(struct comedi_device *dev,
471 struct comedi_subdevice *s,
472 const struct diosubd_data *d)
ebd127c3 473{
1a127f31 474 const struct dio_boardtype *board = dev->board_ptr;
242f5223 475
ebd127c3 476 s->type = COMEDI_SUBD_DO;
e0025918 477 s->subdev_flags = SDF_WRITABLE;
ebd127c3
MD
478 if (d->chans > 16)
479 s->subdev_flags |= SDF_LSAMPL;
480 s->n_chan = d->chans;
481 s->maxdata = 1;
482 s->len_chanlist = d->chans;
483 s->range_table = &range_digital;
484 s->state = 0;
1a127f31 485 switch (board->io_access) {
ebd127c3
MD
486 case IO_8b:
487 s->insn_bits = pci_dio_insn_bits_do_b;
488 break;
489 case IO_16b:
490 s->insn_bits = pci_dio_insn_bits_do_w;
491 break;
492 }
493 s->private = (void *)d;
494
495 return 0;
496}
497
87f6991b
IA
498static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
499 unsigned long cardtype)
500{
501 /*
502 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
503 * board available. Need to enable PCI device and request the main
504 * registers PCI BAR temporarily to perform the test.
505 */
506 if (cardtype != TYPE_PCI1753)
507 return cardtype;
508 if (pci_enable_device(pcidev) < 0)
509 return cardtype;
c1e07ea2 510 if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) {
87f6991b
IA
511 /*
512 * This test is based on Advantech's "advdaq" driver source
513 * (which declares its module licence as "GPL" although the
514 * driver source does not include a "COPYING" file).
515 */
c1e07ea2 516 unsigned long reg = pci_resource_start(pcidev, 2) + 53;
87f6991b
IA
517
518 outb(0x05, reg);
519 if ((inb(reg) & 0x07) == 0x02) {
520 outb(0x02, reg);
521 if ((inb(reg) & 0x07) == 0x05)
522 cardtype = TYPE_PCI1753E;
523 }
c1e07ea2 524 pci_release_region(pcidev, 2);
87f6991b
IA
525 }
526 pci_disable_device(pcidev);
527 return cardtype;
528}
529
a690b7e5 530static int pci_dio_auto_attach(struct comedi_device *dev,
c0a0e0ca 531 unsigned long context)
54b303c4 532{
750af5e5 533 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1a127f31 534 const struct dio_boardtype *board = NULL;
54b303c4 535 struct comedi_subdevice *s;
4bf75257 536 int ret, subdev, i, j;
54b303c4 537
c0a0e0ca 538 if (context < ARRAY_SIZE(boardtypes))
1a127f31
HS
539 board = &boardtypes[context];
540 if (!board)
e5200165 541 return -ENODEV;
1a127f31
HS
542 dev->board_ptr = board;
543 dev->board_name = board->name;
e5200165 544
818f569f 545 ret = comedi_pci_enable(dev);
242f5223
HS
546 if (ret)
547 return ret;
c1e07ea2
HS
548 if (board->cardtype == TYPE_PCI1736)
549 dev->iobase = pci_resource_start(pcidev, 0);
550 else
551 dev->iobase = pci_resource_start(pcidev, 2);
ebd127c3 552
1a127f31 553 ret = comedi_alloc_subdevices(dev, board->nsubdevs);
8b6c5694 554 if (ret)
ebd127c3 555 return ret;
ebd127c3
MD
556
557 subdev = 0;
ebd127c3 558 for (i = 0; i < MAX_DI_SUBDEVS; i++)
1a127f31 559 if (board->sdi[i].chans) {
2b36ab6c 560 s = &dev->subdevices[subdev];
1a127f31 561 pci_dio_add_di(dev, s, &board->sdi[i]);
ebd127c3
MD
562 subdev++;
563 }
564
565 for (i = 0; i < MAX_DO_SUBDEVS; i++)
1a127f31 566 if (board->sdo[i].chans) {
2b36ab6c 567 s = &dev->subdevices[subdev];
1a127f31 568 pci_dio_add_do(dev, s, &board->sdo[i]);
ebd127c3
MD
569 subdev++;
570 }
571
572 for (i = 0; i < MAX_DIO_SUBDEVG; i++)
1a127f31 573 for (j = 0; j < board->sdio[i].regs; j++) {
2b36ab6c 574 s = &dev->subdevices[subdev];
e6439a45 575 ret = subdev_8255_init(dev, s, NULL,
1a127f31 576 board->sdio[i].addr +
f0162091 577 j * I8255_SIZE);
e6439a45
HS
578 if (ret)
579 return ret;
ebd127c3
MD
580 subdev++;
581 }
582
1a127f31 583 if (board->boardid.chans) {
2b36ab6c 584 s = &dev->subdevices[subdev];
ebd127c3 585 s->type = COMEDI_SUBD_DI;
1a127f31 586 pci_dio_add_di(dev, s, &board->boardid);
ebd127c3
MD
587 subdev++;
588 }
589
1a127f31 590 if (board->timer_regbase) {
50e338b9 591 s = &dev->subdevices[subdev];
1e1fe085
HS
592
593 dev->pacer = comedi_8254_init(dev->iobase +
1a127f31 594 board->timer_regbase,
1e1fe085
HS
595 0, I8254_IO8, 0);
596 if (!dev->pacer)
597 return -ENOMEM;
598
599 comedi_8254_subdevice_init(s, dev->pacer);
600
50e338b9
HS
601 subdev++;
602 }
d4da77a7 603
ebd127c3
MD
604 pci_dio_reset(dev);
605
606 return 0;
607}
608
484ecc95 609static void pci_dio_detach(struct comedi_device *dev)
ebd127c3 610{
6ab5db9c
HS
611 if (dev->iobase)
612 pci_dio_reset(dev);
aac307f9 613 comedi_pci_detach(dev);
ebd127c3
MD
614}
615
c95dbeac
HS
616static struct comedi_driver adv_pci_dio_driver = {
617 .driver_name = "adv_pci_dio",
618 .module = THIS_MODULE,
750af5e5 619 .auto_attach = pci_dio_auto_attach,
e5200165 620 .detach = pci_dio_detach,
c95dbeac
HS
621};
622
a690b7e5 623static int adv_pci_dio_pci_probe(struct pci_dev *dev,
b8f4ac23 624 const struct pci_device_id *id)
727b286b 625{
87f6991b
IA
626 unsigned long cardtype;
627
628 cardtype = pci_dio_override_cardtype(dev, id->driver_data);
629 return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
727b286b
AT
630}
631
41e043fc 632static const struct pci_device_id adv_pci_dio_pci_table[] = {
87f6991b
IA
633 { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
634 { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
635 { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
636 { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
637 { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
638 { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
639 { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
640 { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
641 { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
642 { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
643 { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
644 { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
87f6991b 645 { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
c95dbeac 646 { 0 }
727b286b 647};
c95dbeac 648MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
727b286b 649
c95dbeac
HS
650static struct pci_driver adv_pci_dio_pci_driver = {
651 .name = "adv_pci_dio",
652 .id_table = adv_pci_dio_pci_table,
653 .probe = adv_pci_dio_pci_probe,
9901a4d7 654 .remove = comedi_pci_auto_unconfig,
c95dbeac
HS
655};
656module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
90f703d3
AT
657
658MODULE_AUTHOR("Comedi http://www.comedi.org");
659MODULE_DESCRIPTION("Comedi low-level driver");
660MODULE_LICENSE("GPL");
This page took 0.938552 seconds and 5 git commands to generate.