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