1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * comedi/drivers/adv_pci_dio.c
4  *
5  * Author: Michal Dobes <dobes@tesnet.cz>
6  *
7  *  Hardware driver for Advantech PCI DIO cards.
8  */
9 
10 /*
11  * Driver: adv_pci_dio
12  * Description: Advantech Digital I/O Cards
13  * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
14  *   PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750,
15  *   PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E,
16  *   PCI-1754, PCI-1756, PCI-1761, PCI-1762
17  * Author: Michal Dobes <dobes@tesnet.cz>
18  * Updated: Fri, 25 Aug 2017 07:23:06 +0300
19  * Status: untested
20  *
21  * Configuration Options: not applicable, uses PCI auto config
22  */
23 
24 #include <linux/module.h>
25 #include <linux/delay.h>
26 
27 #include "../comedi_pci.h"
28 
29 #include "8255.h"
30 #include "comedi_8254.h"
31 
32 /*
33  * Register offset definitions
34  */
35 
36 /* PCI-1730, PCI-1733, PCI-1736 interrupt control registers */
37 #define PCI173X_INT_EN_REG	0x0008	/* R/W: enable/disable */
38 #define PCI173X_INT_RF_REG	0x000c	/* R/W: falling/rising edge */
39 #define PCI173X_INT_FLAG_REG	0x0010	/* R: status */
40 #define PCI173X_INT_CLR_REG	0x0010	/* W: clear */
41 
42 #define PCI173X_INT_IDI0 0x01  /* IDI0 edge occurred */
43 #define PCI173X_INT_IDI1 0x02  /* IDI1 edge occurred */
44 #define PCI173X_INT_DI0  0x04  /* DI0 edge occurred */
45 #define PCI173X_INT_DI1  0x08  /* DI1 edge occurred */
46 
47 /* PCI-1739U, PCI-1750, PCI1751 interrupt control registers */
48 #define PCI1750_INT_REG		0x20	/* R/W: status/control */
49 
50 /* PCI-1753, PCI-1753E interrupt control registers */
51 #define PCI1753_INT_REG(x)	(0x10 + (x)) /* R/W: control group 0 to 3 */
52 #define PCI1753E_INT_REG(x)	(0x30 + (x)) /* R/W: control group 0 to 3 */
53 
54 /* PCI-1754, PCI-1756 interrupt control registers */
55 #define PCI1754_INT_REG(x)	(0x08 + (x) * 2) /* R/W: control group 0 to 3 */
56 
57 /* PCI-1752, PCI-1756 special registers */
58 #define PCI1752_CFC_REG		0x12	/* R/W: channel freeze function */
59 
60 /* PCI-1761 interrupt control registers */
61 #define PCI1761_INT_EN_REG	0x03	/* R/W: enable/disable interrupts */
62 #define PCI1761_INT_RF_REG	0x04	/* R/W: falling/rising edge */
63 #define PCI1761_INT_CLR_REG	0x05	/* R/W: clear interrupts */
64 
65 /* PCI-1762 interrupt control registers */
66 #define PCI1762_INT_REG		0x06	/* R/W: status/control */
67 
68 /* maximum number of subdevice descriptions in the boardinfo */
69 #define PCI_DIO_MAX_DI_SUBDEVS	2	/* 2 x 8/16/32 input channels max */
70 #define PCI_DIO_MAX_DO_SUBDEVS	2	/* 2 x 8/16/32 output channels max */
71 #define PCI_DIO_MAX_DIO_SUBDEVG	2	/* 2 x any number of 8255 devices max */
72 #define PCI_DIO_MAX_IRQ_SUBDEVS	4	/* 4 x 1 input IRQ channels max */
73 
74 enum pci_dio_boardid {
75 	TYPE_PCI1730,
76 	TYPE_PCI1733,
77 	TYPE_PCI1734,
78 	TYPE_PCI1735,
79 	TYPE_PCI1736,
80 	TYPE_PCI1739,
81 	TYPE_PCI1750,
82 	TYPE_PCI1751,
83 	TYPE_PCI1752,
84 	TYPE_PCI1753,
85 	TYPE_PCI1753E,
86 	TYPE_PCI1754,
87 	TYPE_PCI1756,
88 	TYPE_PCI1761,
89 	TYPE_PCI1762
90 };
91 
92 struct diosubd_data {
93 	int chans;		/*  num of chans or 8255 devices */
94 	unsigned long addr;	/*  PCI address offset */
95 };
96 
97 struct dio_irq_subd_data {
98 	unsigned short int_en;		/* interrupt enable/status bit */
99 	unsigned long addr;		/* PCI address offset */
100 };
101 
102 struct dio_boardtype {
103 	const char *name;	/*  board name */
104 	int nsubdevs;
105 	struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS];
106 	struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS];
107 	struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG];
108 	struct dio_irq_subd_data sdirq[PCI_DIO_MAX_IRQ_SUBDEVS];
109 	unsigned long id_reg;
110 	unsigned long timer_regbase;
111 	unsigned int is_16bit:1;
112 };
113 
114 static const struct dio_boardtype boardtypes[] = {
115 	[TYPE_PCI1730] = {
116 		.name		= "pci1730",
117 		/* DI, IDI, DO, IDO, ID, IRQ_DI0, IRQ_DI1, IRQ_IDI0, IRQ_IDI1 */
118 		.nsubdevs	= 9,
119 		.sdi[0]		= { 16, 0x02, },	/* DI 0-15 */
120 		.sdi[1]		= { 16, 0x00, },	/* ISO DI 0-15 */
121 		.sdo[0]		= { 16, 0x02, },	/* DO 0-15 */
122 		.sdo[1]		= { 16, 0x00, },	/* ISO DO 0-15 */
123 		.id_reg		= 0x04,
124 		.sdirq[0]	= { PCI173X_INT_DI0,  0x02, },	/* DI 0 */
125 		.sdirq[1]	= { PCI173X_INT_DI1,  0x02, },	/* DI 1 */
126 		.sdirq[2]	= { PCI173X_INT_IDI0, 0x00, },	/* ISO DI 0 */
127 		.sdirq[3]	= { PCI173X_INT_IDI1, 0x00, },	/* ISO DI 1 */
128 	},
129 	[TYPE_PCI1733] = {
130 		.name		= "pci1733",
131 		.nsubdevs	= 2,
132 		.sdi[1]		= { 32, 0x00, },	/* ISO DI 0-31 */
133 		.id_reg		= 0x04,
134 	},
135 	[TYPE_PCI1734] = {
136 		.name		= "pci1734",
137 		.nsubdevs	= 2,
138 		.sdo[1]		= { 32, 0x00, },	/* ISO DO 0-31 */
139 		.id_reg		= 0x04,
140 	},
141 	[TYPE_PCI1735] = {
142 		.name		= "pci1735",
143 		.nsubdevs	= 4,
144 		.sdi[0]		= { 32, 0x00, },	/* DI 0-31 */
145 		.sdo[0]		= { 32, 0x00, },	/* DO 0-31 */
146 		.id_reg		= 0x08,
147 		.timer_regbase	= 0x04,
148 	},
149 	[TYPE_PCI1736] = {
150 		.name		= "pci1736",
151 		.nsubdevs	= 3,
152 		.sdi[1]		= { 16, 0x00, },	/* ISO DI 0-15 */
153 		.sdo[1]		= { 16, 0x00, },	/* ISO DO 0-15 */
154 		.id_reg		= 0x04,
155 	},
156 	[TYPE_PCI1739] = {
157 		.name		= "pci1739",
158 		.nsubdevs	= 3,
159 		.sdio[0]	= { 2, 0x00, },		/* 8255 DIO */
160 		.id_reg		= 0x08,
161 	},
162 	[TYPE_PCI1750] = {
163 		.name		= "pci1750",
164 		.nsubdevs	= 2,
165 		.sdi[1]		= { 16, 0x00, },	/* ISO DI 0-15 */
166 		.sdo[1]		= { 16, 0x00, },	/* ISO DO 0-15 */
167 	},
168 	[TYPE_PCI1751] = {
169 		.name		= "pci1751",
170 		.nsubdevs	= 3,
171 		.sdio[0]	= { 2, 0x00, },		/* 8255 DIO */
172 		.timer_regbase	= 0x18,
173 	},
174 	[TYPE_PCI1752] = {
175 		.name		= "pci1752",
176 		.nsubdevs	= 3,
177 		.sdo[0]		= { 32, 0x00, },	/* DO 0-31 */
178 		.sdo[1]		= { 32, 0x04, },	/* DO 32-63 */
179 		.id_reg		= 0x10,
180 		.is_16bit	= 1,
181 	},
182 	[TYPE_PCI1753] = {
183 		.name		= "pci1753",
184 		.nsubdevs	= 4,
185 		.sdio[0]	= { 4, 0x00, },		/* 8255 DIO */
186 	},
187 	[TYPE_PCI1753E] = {
188 		.name		= "pci1753e",
189 		.nsubdevs	= 8,
190 		.sdio[0]	= { 4, 0x00, },		/* 8255 DIO */
191 		.sdio[1]	= { 4, 0x20, },		/* 8255 DIO */
192 	},
193 	[TYPE_PCI1754] = {
194 		.name		= "pci1754",
195 		.nsubdevs	= 3,
196 		.sdi[0]		= { 32, 0x00, },	/* DI 0-31 */
197 		.sdi[1]		= { 32, 0x04, },	/* DI 32-63 */
198 		.id_reg		= 0x10,
199 		.is_16bit	= 1,
200 	},
201 	[TYPE_PCI1756] = {
202 		.name		= "pci1756",
203 		.nsubdevs	= 3,
204 		.sdi[1]		= { 32, 0x00, },	/* DI 0-31 */
205 		.sdo[1]		= { 32, 0x04, },	/* DO 0-31 */
206 		.id_reg		= 0x10,
207 		.is_16bit	= 1,
208 	},
209 	[TYPE_PCI1761] = {
210 		.name		= "pci1761",
211 		.nsubdevs	= 3,
212 		.sdi[1]		= { 8, 0x01 },		/* ISO DI 0-7 */
213 		.sdo[1]		= { 8, 0x00 },		/* RELAY DO 0-7 */
214 		.id_reg		= 0x02,
215 	},
216 	[TYPE_PCI1762] = {
217 		.name		= "pci1762",
218 		.nsubdevs	= 3,
219 		.sdi[1]		= { 16, 0x02, },	/* ISO DI 0-15 */
220 		.sdo[1]		= { 16, 0x00, },	/* ISO DO 0-15 */
221 		.id_reg		= 0x04,
222 		.is_16bit	= 1,
223 	},
224 };
225 
226 struct pci_dio_dev_private_data {
227 	int boardtype;
228 	int irq_subd;
229 	unsigned short int_ctrl;
230 	unsigned short int_rf;
231 };
232 
233 struct pci_dio_sd_private_data {
234 	spinlock_t subd_slock;		/* spin-lock for cmd_running */
235 	unsigned long port_offset;
236 	short int cmd_running;
237 };
238 
process_irq(struct comedi_device * dev,unsigned int subdev,unsigned char irqflags)239 static void process_irq(struct comedi_device *dev, unsigned int subdev,
240 			unsigned char irqflags)
241 {
242 	struct comedi_subdevice *s = &dev->subdevices[subdev];
243 	struct pci_dio_sd_private_data *sd_priv = s->private;
244 	unsigned long reg = sd_priv->port_offset;
245 	struct comedi_async *async_p = s->async;
246 
247 	if (async_p) {
248 		unsigned short val = inw(dev->iobase + reg);
249 
250 		spin_lock(&sd_priv->subd_slock);
251 		if (sd_priv->cmd_running)
252 			comedi_buf_write_samples(s, &val, 1);
253 		spin_unlock(&sd_priv->subd_slock);
254 		comedi_handle_events(dev, s);
255 	}
256 }
257 
pci_dio_interrupt(int irq,void * p_device)258 static irqreturn_t pci_dio_interrupt(int irq, void *p_device)
259 {
260 	struct comedi_device *dev = p_device;
261 	struct pci_dio_dev_private_data *dev_private = dev->private;
262 	const struct dio_boardtype *board = dev->board_ptr;
263 	unsigned long cpu_flags;
264 	unsigned char irqflags;
265 	int i;
266 
267 	if (!dev->attached) {
268 		/* Ignore interrupt before device fully attached. */
269 		/* Might not even have allocated subdevices yet! */
270 		return IRQ_NONE;
271 	}
272 
273 	/* Check if we are source of interrupt */
274 	spin_lock_irqsave(&dev->spinlock, cpu_flags);
275 	irqflags = inb(dev->iobase + PCI173X_INT_FLAG_REG);
276 	if (!(irqflags & 0x0F)) {
277 		spin_unlock_irqrestore(&dev->spinlock, cpu_flags);
278 		return IRQ_NONE;
279 	}
280 
281 	/* clear all current interrupt flags */
282 	outb(irqflags, dev->iobase + PCI173X_INT_CLR_REG);
283 	spin_unlock_irqrestore(&dev->spinlock, cpu_flags);
284 
285 	/* check irq subdevice triggers */
286 	for (i = 0; i < PCI_DIO_MAX_IRQ_SUBDEVS; i++) {
287 		if (irqflags & board->sdirq[i].int_en)
288 			process_irq(dev, dev_private->irq_subd + i, irqflags);
289 	}
290 
291 	return IRQ_HANDLED;
292 }
293 
pci_dio_asy_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)294 static int pci_dio_asy_cmdtest(struct comedi_device *dev,
295 			       struct comedi_subdevice *s,
296 			       struct comedi_cmd *cmd)
297 {
298 	int err = 0;
299 
300 	/* Step 1 : check if triggers are trivially valid */
301 
302 	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
303 	err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
304 	err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
305 	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
306 	err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
307 
308 	if (err)
309 		return 1;
310 
311 	/* Step 2a : make sure trigger sources are unique */
312 	/* Step 2b : and mutually compatible */
313 
314 	/* Step 3: check if arguments are trivially valid */
315 
316 	err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
317 	/*
318 	 * For scan_begin_arg, the trigger number must be 0 and the only
319 	 * allowed flags are CR_EDGE and CR_INVERT.  CR_EDGE is ignored,
320 	 * CR_INVERT sets the trigger to falling edge.
321 	 */
322 	if (cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) {
323 		cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
324 		err |= -EINVAL;
325 	}
326 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
327 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
328 					   cmd->chanlist_len);
329 	err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
330 
331 	if (err)
332 		return 3;
333 
334 	/* Step 4: fix up any arguments */
335 
336 	/* Step 5: check channel list if it exists */
337 
338 	return 0;
339 }
340 
pci_dio_asy_cmd(struct comedi_device * dev,struct comedi_subdevice * s)341 static int pci_dio_asy_cmd(struct comedi_device *dev,
342 			   struct comedi_subdevice *s)
343 {
344 	struct pci_dio_dev_private_data *dev_private = dev->private;
345 	struct pci_dio_sd_private_data *sd_priv = s->private;
346 	const struct dio_boardtype *board = dev->board_ptr;
347 	struct comedi_cmd *cmd = &s->async->cmd;
348 	unsigned long cpu_flags;
349 	unsigned short int_en;
350 
351 	int_en = board->sdirq[s->index - dev_private->irq_subd].int_en;
352 
353 	spin_lock_irqsave(&dev->spinlock, cpu_flags);
354 	if (cmd->scan_begin_arg & CR_INVERT)
355 		dev_private->int_rf |= int_en;	/* falling edge */
356 	else
357 		dev_private->int_rf &= ~int_en;	/* rising edge */
358 	outb(dev_private->int_rf, dev->iobase + PCI173X_INT_RF_REG);
359 	dev_private->int_ctrl |= int_en;	/* enable interrupt source */
360 	outb(dev_private->int_ctrl, dev->iobase + PCI173X_INT_EN_REG);
361 	spin_unlock_irqrestore(&dev->spinlock, cpu_flags);
362 
363 	spin_lock_irqsave(&sd_priv->subd_slock, cpu_flags);
364 	sd_priv->cmd_running = 1;
365 	spin_unlock_irqrestore(&sd_priv->subd_slock, cpu_flags);
366 
367 	return 0;
368 }
369 
pci_dio_asy_cancel(struct comedi_device * dev,struct comedi_subdevice * s)370 static int pci_dio_asy_cancel(struct comedi_device *dev,
371 			      struct comedi_subdevice *s)
372 {
373 	struct pci_dio_dev_private_data *dev_private = dev->private;
374 	struct pci_dio_sd_private_data *sd_priv = s->private;
375 	const struct dio_boardtype *board = dev->board_ptr;
376 	unsigned long cpu_flags;
377 	unsigned short int_en;
378 
379 	spin_lock_irqsave(&sd_priv->subd_slock, cpu_flags);
380 	sd_priv->cmd_running = 0;
381 	spin_unlock_irqrestore(&sd_priv->subd_slock, cpu_flags);
382 
383 	int_en = board->sdirq[s->index - dev_private->irq_subd].int_en;
384 
385 	spin_lock_irqsave(&dev->spinlock, cpu_flags);
386 	dev_private->int_ctrl &= ~int_en;
387 	outb(dev_private->int_ctrl, dev->iobase + PCI173X_INT_EN_REG);
388 	spin_unlock_irqrestore(&dev->spinlock, cpu_flags);
389 
390 	return 0;
391 }
392 
393 /* same as _insn_bits_di_ because the IRQ-pins are the DI-ports  */
pci_dio_insn_bits_dirq_b(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)394 static int pci_dio_insn_bits_dirq_b(struct comedi_device *dev,
395 				    struct comedi_subdevice *s,
396 				    struct comedi_insn *insn,
397 				    unsigned int *data)
398 {
399 	struct pci_dio_sd_private_data *sd_priv = s->private;
400 	unsigned long reg = (unsigned long)sd_priv->port_offset;
401 	unsigned long iobase = dev->iobase + reg;
402 
403 	data[1] = inb(iobase);
404 
405 	return insn->n;
406 }
407 
pci_dio_insn_bits_di_b(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)408 static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
409 				  struct comedi_subdevice *s,
410 				  struct comedi_insn *insn,
411 				  unsigned int *data)
412 {
413 	unsigned long reg = (unsigned long)s->private;
414 	unsigned long iobase = dev->iobase + reg;
415 
416 	data[1] = inb(iobase);
417 	if (s->n_chan > 8)
418 		data[1] |= (inb(iobase + 1) << 8);
419 	if (s->n_chan > 16)
420 		data[1] |= (inb(iobase + 2) << 16);
421 	if (s->n_chan > 24)
422 		data[1] |= (inb(iobase + 3) << 24);
423 
424 	return insn->n;
425 }
426 
pci_dio_insn_bits_di_w(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)427 static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
428 				  struct comedi_subdevice *s,
429 				  struct comedi_insn *insn,
430 				  unsigned int *data)
431 {
432 	unsigned long reg = (unsigned long)s->private;
433 	unsigned long iobase = dev->iobase + reg;
434 
435 	data[1] = inw(iobase);
436 	if (s->n_chan > 16)
437 		data[1] |= (inw(iobase + 2) << 16);
438 
439 	return insn->n;
440 }
441 
pci_dio_insn_bits_do_b(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)442 static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
443 				  struct comedi_subdevice *s,
444 				  struct comedi_insn *insn,
445 				  unsigned int *data)
446 {
447 	unsigned long reg = (unsigned long)s->private;
448 	unsigned long iobase = dev->iobase + reg;
449 
450 	if (comedi_dio_update_state(s, data)) {
451 		outb(s->state & 0xff, iobase);
452 		if (s->n_chan > 8)
453 			outb((s->state >> 8) & 0xff, iobase + 1);
454 		if (s->n_chan > 16)
455 			outb((s->state >> 16) & 0xff, iobase + 2);
456 		if (s->n_chan > 24)
457 			outb((s->state >> 24) & 0xff, iobase + 3);
458 	}
459 
460 	data[1] = s->state;
461 
462 	return insn->n;
463 }
464 
pci_dio_insn_bits_do_w(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)465 static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
466 				  struct comedi_subdevice *s,
467 				  struct comedi_insn *insn,
468 				  unsigned int *data)
469 {
470 	unsigned long reg = (unsigned long)s->private;
471 	unsigned long iobase = dev->iobase + reg;
472 
473 	if (comedi_dio_update_state(s, data)) {
474 		outw(s->state & 0xffff, iobase);
475 		if (s->n_chan > 16)
476 			outw((s->state >> 16) & 0xffff, iobase + 2);
477 	}
478 
479 	data[1] = s->state;
480 
481 	return insn->n;
482 }
483 
pci_dio_reset(struct comedi_device * dev,unsigned long cardtype)484 static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype)
485 {
486 	struct pci_dio_dev_private_data *dev_private = dev->private;
487 	/* disable channel freeze function on the PCI-1752/1756 boards */
488 	if (cardtype == TYPE_PCI1752 || cardtype == TYPE_PCI1756)
489 		outw(0, dev->iobase + PCI1752_CFC_REG);
490 
491 	/* disable and clear interrupts */
492 	switch (cardtype) {
493 	case TYPE_PCI1730:
494 	case TYPE_PCI1733:
495 	case TYPE_PCI1736:
496 		dev_private->int_ctrl = 0x00;
497 		outb(dev_private->int_ctrl, dev->iobase + PCI173X_INT_EN_REG);
498 		/* Reset all 4 Int Flags */
499 		outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG);
500 		/* Rising Edge => IRQ . On all 4 Pins */
501 		dev_private->int_rf = 0x00;
502 		outb(dev_private->int_rf, dev->iobase + PCI173X_INT_RF_REG);
503 		break;
504 	case TYPE_PCI1739:
505 	case TYPE_PCI1750:
506 	case TYPE_PCI1751:
507 		outb(0x88, dev->iobase + PCI1750_INT_REG);
508 		break;
509 	case TYPE_PCI1753:
510 	case TYPE_PCI1753E:
511 		outb(0x88, dev->iobase + PCI1753_INT_REG(0));
512 		outb(0x80, dev->iobase + PCI1753_INT_REG(1));
513 		outb(0x80, dev->iobase + PCI1753_INT_REG(2));
514 		outb(0x80, dev->iobase + PCI1753_INT_REG(3));
515 		if (cardtype == TYPE_PCI1753E) {
516 			outb(0x88, dev->iobase + PCI1753E_INT_REG(0));
517 			outb(0x80, dev->iobase + PCI1753E_INT_REG(1));
518 			outb(0x80, dev->iobase + PCI1753E_INT_REG(2));
519 			outb(0x80, dev->iobase + PCI1753E_INT_REG(3));
520 		}
521 		break;
522 	case TYPE_PCI1754:
523 	case TYPE_PCI1756:
524 		outw(0x08, dev->iobase + PCI1754_INT_REG(0));
525 		outw(0x08, dev->iobase + PCI1754_INT_REG(1));
526 		if (cardtype == TYPE_PCI1754) {
527 			outw(0x08, dev->iobase + PCI1754_INT_REG(2));
528 			outw(0x08, dev->iobase + PCI1754_INT_REG(3));
529 		}
530 		break;
531 	case TYPE_PCI1761:
532 		/* disable interrupts */
533 		outb(0, dev->iobase + PCI1761_INT_EN_REG);
534 		/* clear interrupts */
535 		outb(0xff, dev->iobase + PCI1761_INT_CLR_REG);
536 		/* set rising edge trigger */
537 		outb(0, dev->iobase + PCI1761_INT_RF_REG);
538 		break;
539 	case TYPE_PCI1762:
540 		outw(0x0101, dev->iobase + PCI1762_INT_REG);
541 		break;
542 	default:
543 		break;
544 	}
545 
546 	return 0;
547 }
548 
pci_dio_auto_attach(struct comedi_device * dev,unsigned long context)549 static int pci_dio_auto_attach(struct comedi_device *dev,
550 			       unsigned long context)
551 {
552 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
553 	const struct dio_boardtype *board = NULL;
554 	struct comedi_subdevice *s;
555 	struct pci_dio_dev_private_data *dev_private;
556 	int ret, subdev, i, j;
557 
558 	if (context < ARRAY_SIZE(boardtypes))
559 		board = &boardtypes[context];
560 	if (!board)
561 		return -ENODEV;
562 	dev->board_ptr = board;
563 	dev->board_name = board->name;
564 
565 	dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private));
566 	if (!dev_private)
567 		return -ENOMEM;
568 
569 	ret = comedi_pci_enable(dev);
570 	if (ret)
571 		return ret;
572 	if (context == TYPE_PCI1736)
573 		dev->iobase = pci_resource_start(pcidev, 0);
574 	else
575 		dev->iobase = pci_resource_start(pcidev, 2);
576 
577 	dev_private->boardtype = context;
578 	pci_dio_reset(dev, context);
579 
580 	/* request IRQ if device has irq subdevices */
581 	if (board->sdirq[0].int_en && pcidev->irq) {
582 		ret = request_irq(pcidev->irq, pci_dio_interrupt, IRQF_SHARED,
583 				  dev->board_name, dev);
584 		if (ret == 0)
585 			dev->irq = pcidev->irq;
586 	}
587 
588 	ret = comedi_alloc_subdevices(dev, board->nsubdevs);
589 	if (ret)
590 		return ret;
591 
592 	subdev = 0;
593 	for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) {
594 		const struct diosubd_data *d = &board->sdi[i];
595 
596 		if (d->chans) {
597 			s = &dev->subdevices[subdev++];
598 			s->type		= COMEDI_SUBD_DI;
599 			s->subdev_flags	= SDF_READABLE;
600 			s->n_chan	= d->chans;
601 			s->maxdata	= 1;
602 			s->range_table	= &range_digital;
603 			s->insn_bits	= board->is_16bit
604 						? pci_dio_insn_bits_di_w
605 						: pci_dio_insn_bits_di_b;
606 			s->private	= (void *)d->addr;
607 		}
608 	}
609 
610 	for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) {
611 		const struct diosubd_data *d = &board->sdo[i];
612 
613 		if (d->chans) {
614 			s = &dev->subdevices[subdev++];
615 			s->type		= COMEDI_SUBD_DO;
616 			s->subdev_flags	= SDF_WRITABLE;
617 			s->n_chan	= d->chans;
618 			s->maxdata	= 1;
619 			s->range_table	= &range_digital;
620 			s->insn_bits	= board->is_16bit
621 						? pci_dio_insn_bits_do_w
622 						: pci_dio_insn_bits_do_b;
623 			s->private	= (void *)d->addr;
624 
625 			/* reset all outputs to 0 */
626 			if (board->is_16bit) {
627 				outw(0, dev->iobase + d->addr);
628 				if (s->n_chan > 16)
629 					outw(0, dev->iobase + d->addr + 2);
630 			} else {
631 				outb(0, dev->iobase + d->addr);
632 				if (s->n_chan > 8)
633 					outb(0, dev->iobase + d->addr + 1);
634 				if (s->n_chan > 16)
635 					outb(0, dev->iobase + d->addr + 2);
636 				if (s->n_chan > 24)
637 					outb(0, dev->iobase + d->addr + 3);
638 			}
639 		}
640 	}
641 
642 	for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) {
643 		const struct diosubd_data *d = &board->sdio[i];
644 
645 		for (j = 0; j < d->chans; j++) {
646 			s = &dev->subdevices[subdev++];
647 			ret = subdev_8255_init(dev, s, NULL,
648 					       d->addr + j * I8255_SIZE);
649 			if (ret)
650 				return ret;
651 		}
652 	}
653 
654 	if (board->id_reg) {
655 		s = &dev->subdevices[subdev++];
656 		s->type		= COMEDI_SUBD_DI;
657 		s->subdev_flags	= SDF_READABLE | SDF_INTERNAL;
658 		s->n_chan	= 4;
659 		s->maxdata	= 1;
660 		s->range_table	= &range_digital;
661 		s->insn_bits	= board->is_16bit ? pci_dio_insn_bits_di_w
662 						  : pci_dio_insn_bits_di_b;
663 		s->private	= (void *)board->id_reg;
664 	}
665 
666 	if (board->timer_regbase) {
667 		s = &dev->subdevices[subdev++];
668 
669 		dev->pacer = comedi_8254_init(dev->iobase +
670 					      board->timer_regbase,
671 					      0, I8254_IO8, 0);
672 		if (!dev->pacer)
673 			return -ENOMEM;
674 
675 		comedi_8254_subdevice_init(s, dev->pacer);
676 	}
677 
678 	dev_private->irq_subd = subdev; /* first interrupt subdevice index */
679 	for (i = 0; i < PCI_DIO_MAX_IRQ_SUBDEVS; ++i) {
680 		struct pci_dio_sd_private_data *sd_priv = NULL;
681 		const struct dio_irq_subd_data *d = &board->sdirq[i];
682 
683 		if (d->int_en) {
684 			s = &dev->subdevices[subdev++];
685 			s->type		= COMEDI_SUBD_DI;
686 			s->subdev_flags	= SDF_READABLE;
687 			s->n_chan	= 1;
688 			s->maxdata	= 1;
689 			s->range_table	= &range_digital;
690 			s->insn_bits	= pci_dio_insn_bits_dirq_b;
691 			sd_priv = comedi_alloc_spriv(s, sizeof(*sd_priv));
692 			if (!sd_priv)
693 				return -ENOMEM;
694 
695 			spin_lock_init(&sd_priv->subd_slock);
696 			sd_priv->port_offset = d->addr;
697 			sd_priv->cmd_running = 0;
698 
699 			if (dev->irq) {
700 				dev->read_subdev = s;
701 				s->type		= COMEDI_SUBD_DI;
702 				s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
703 				s->len_chanlist	= 1;
704 				s->do_cmdtest	= pci_dio_asy_cmdtest;
705 				s->do_cmd	= pci_dio_asy_cmd;
706 				s->cancel	= pci_dio_asy_cancel;
707 			}
708 		}
709 	}
710 
711 	return 0;
712 }
713 
pci_dio_detach(struct comedi_device * dev)714 static void pci_dio_detach(struct comedi_device *dev)
715 {
716 	struct pci_dio_dev_private_data *dev_private = dev->private;
717 	int boardtype = dev_private->boardtype;
718 
719 	if (dev->iobase)
720 		pci_dio_reset(dev, boardtype);
721 	comedi_pci_detach(dev);
722 }
723 
724 static struct comedi_driver adv_pci_dio_driver = {
725 	.driver_name	= "adv_pci_dio",
726 	.module		= THIS_MODULE,
727 	.auto_attach	= pci_dio_auto_attach,
728 	.detach		= pci_dio_detach,
729 };
730 
pci_dio_override_cardtype(struct pci_dev * pcidev,unsigned long cardtype)731 static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
732 					       unsigned long cardtype)
733 {
734 	/*
735 	 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
736 	 * board available.  Need to enable PCI device and request the main
737 	 * registers PCI BAR temporarily to perform the test.
738 	 */
739 	if (cardtype != TYPE_PCI1753)
740 		return cardtype;
741 	if (pci_enable_device(pcidev) < 0)
742 		return cardtype;
743 	if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) {
744 		/*
745 		 * This test is based on Advantech's "advdaq" driver source
746 		 * (which declares its module licence as "GPL" although the
747 		 * driver source does not include a "COPYING" file).
748 		 */
749 		unsigned long reg = pci_resource_start(pcidev, 2) + 53;
750 
751 		outb(0x05, reg);
752 		if ((inb(reg) & 0x07) == 0x02) {
753 			outb(0x02, reg);
754 			if ((inb(reg) & 0x07) == 0x05)
755 				cardtype = TYPE_PCI1753E;
756 		}
757 		pci_release_region(pcidev, 2);
758 	}
759 	pci_disable_device(pcidev);
760 	return cardtype;
761 }
762 
adv_pci_dio_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)763 static int adv_pci_dio_pci_probe(struct pci_dev *dev,
764 				 const struct pci_device_id *id)
765 {
766 	unsigned long cardtype;
767 
768 	cardtype = pci_dio_override_cardtype(dev, id->driver_data);
769 	return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
770 }
771 
772 static const struct pci_device_id adv_pci_dio_pci_table[] = {
773 	{ PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
774 	{ PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
775 	{ PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
776 	{ PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
777 	{ PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
778 	{ PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
779 	{ PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
780 	{ PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
781 	{ PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
782 	{ PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
783 	{ PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
784 	{ PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
785 	{ PCI_VDEVICE(ADVANTECH, 0x1761), TYPE_PCI1761 },
786 	{ PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
787 	{ 0 }
788 };
789 MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
790 
791 static struct pci_driver adv_pci_dio_pci_driver = {
792 	.name		= "adv_pci_dio",
793 	.id_table	= adv_pci_dio_pci_table,
794 	.probe		= adv_pci_dio_pci_probe,
795 	.remove		= comedi_pci_auto_unconfig,
796 };
797 module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
798 
799 MODULE_AUTHOR("Comedi https://www.comedi.org");
800 MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards");
801 MODULE_LICENSE("GPL");
802