[go: nahoru, domu]

171f81efb22bc68533fe7a25e98361413d446850aChase Southwood/*
271f81efb22bc68533fe7a25e98361413d446850aChase Southwood * addi_apci_1564.c
371f81efb22bc68533fe7a25e98361413d446850aChase Southwood * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
471f81efb22bc68533fe7a25e98361413d446850aChase Southwood *
571f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	ADDI-DATA GmbH
671f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	Dieselstrasse 3
771f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	D-77833 Ottersweier
871f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	Tel: +19(0)7223/9493-0
971f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	Fax: +49(0)7223/9493-92
1071f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	http://www.addi-data.com
1171f81efb22bc68533fe7a25e98361413d446850aChase Southwood *	info@addi-data.com
1271f81efb22bc68533fe7a25e98361413d446850aChase Southwood *
1371f81efb22bc68533fe7a25e98361413d446850aChase Southwood * This program is free software; you can redistribute it and/or modify it under
1471f81efb22bc68533fe7a25e98361413d446850aChase Southwood * the terms of the GNU General Public License as published by the Free Software
1571f81efb22bc68533fe7a25e98361413d446850aChase Southwood * Foundation; either version 2 of the License, or (at your option) any later
1671f81efb22bc68533fe7a25e98361413d446850aChase Southwood * version.
1771f81efb22bc68533fe7a25e98361413d446850aChase Southwood *
1871f81efb22bc68533fe7a25e98361413d446850aChase Southwood * This program is distributed in the hope that it will be useful, but WITHOUT
1971f81efb22bc68533fe7a25e98361413d446850aChase Southwood * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2071f81efb22bc68533fe7a25e98361413d446850aChase Southwood * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2171f81efb22bc68533fe7a25e98361413d446850aChase Southwood * details.
2271f81efb22bc68533fe7a25e98361413d446850aChase Southwood */
2371f81efb22bc68533fe7a25e98361413d446850aChase Southwood
24ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h>
2533782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/pci.h>
2699acc5ae9b9e544adb0921c16640293010360566Chase Southwood#include <linux/interrupt.h>
2799acc5ae9b9e544adb0921c16640293010360566Chase Southwood#include <linux/sched.h>
2833782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten
293d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "../comedidev.h"
303d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "comedi_fc.h"
31860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood#include "amcc_s5933.h"
32f94f771cc667bdf9ab6a4869bcd19de41c180602Chase Southwood#include "addi_watchdog.h"
333d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten
344c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwoodstruct apci1564_private {
354c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	unsigned int amcc_iobase;	/* base of AMCC I/O registers */
361e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	unsigned int mode1;		/* riding-edge/high level channels */
371e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	unsigned int mode2;		/* falling-edge/low level channels */
381e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	unsigned int ctrl;		/* interrupt mode OR (edge) . AND (level) */
394c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	unsigned char timer_select_mode;
404c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	unsigned char mode_select_register;
414c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	struct task_struct *tsk_current;
424c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood};
434c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood
44bf6a1578c10a4f3ef94a3c744267f18f9c3642bdH Hartley Sweeten#include "addi-data/hwdrv_apci1564.c"
45317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten
461e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_reset(struct comedi_device *dev)
471e15687ea472614d48416c53bebcf213c07a5532Chase Southwood{
481e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	struct apci1564_private *devpriv = dev->private;
491e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
501e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Disable the input interrupts and reset status register */
511e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
521e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
531e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
541e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
551e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
561e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Reset the output channels and disable interrupts */
571e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DO_REG);
581e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
591e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
601e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Reset the watchdog registers */
611e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	addi_watchdog_reset(devpriv->amcc_iobase + APCI1564_WDOG_REG);
621e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
631e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Reset the timer registers */
641e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
651e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
661e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
671e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Reset the counter registers */
6885d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood	outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER1));
6985d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood	outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER2));
7085d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood	outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER3));
7185d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood	outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER4));
721e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
731e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	return 0;
741e15687ea472614d48416c53bebcf213c07a5532Chase Southwood}
751e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
76860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwoodstatic irqreturn_t apci1564_interrupt(int irq, void *d)
77b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood{
78860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	struct comedi_device *dev = d;
79860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	struct apci1564_private *devpriv = dev->private;
80860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	struct comedi_subdevice *s = dev->read_subdev;
81b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	unsigned int status;
82b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	unsigned int ctrl;
83b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	unsigned int chan;
84860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
85860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	/* check interrupt is from this device */
86860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
87860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	     INTCSR_INTR_ASSERTED) == 0)
88860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		return IRQ_NONE;
89860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
90b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	status = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
91b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	if (status & APCI1564_DI_INT_ENABLE) {
92860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		/* disable the interrupt */
93b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		outl(status & APCI1564_DI_INT_DISABLE,
94b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		     devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
95860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
96b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG)
97b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood			       & 0xffff;
98860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		comedi_buf_put(s, s->state);
99860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
100860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		comedi_event(dev, s);
101860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
102860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		/* enable the interrupt */
103b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		outl(status, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
104860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	}
105860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
106b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	status = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG);
107b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	if (status & 0x01) {
108b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		/*  Disable Timer Interrupt */
109b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		ctrl = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
110b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
111860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
112b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		/* Send a signal to from kernel to user space */
113b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		send_sig(SIGIO, devpriv->tsk_current, 0);
114860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
115b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		/*  Enable Timer Interrupt */
116b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		outl(ctrl, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
117860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	}
118860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
119b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood	for (chan = 0; chan < 4; chan++) {
12085d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood		status = inl(dev->iobase + APCI1564_COUNTER_IRQ_REG(chan));
121b11771aa4c22074df2b804c02433c5357514f5c5Chase Southwood		if (status & 0x01) {
122860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood			/*  Disable Counter Interrupt */
12385d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood			ctrl = inl(dev->iobase +
12485d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood				  APCI1564_COUNTER_CTRL_REG(chan));
12585d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood			outl(0x0, dev->iobase +
12685d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood			    APCI1564_COUNTER_CTRL_REG(chan));
127860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
128860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood			/* Send a signal to from kernel to user space */
129860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood			send_sig(SIGIO, devpriv->tsk_current, 0);
130860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
131860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood			/*  Enable Counter Interrupt */
13285d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood			outl(ctrl, dev->iobase +
13385d7c9ab5129e96d25b455d7bf45066c376e8e2dChase Southwood			    APCI1564_COUNTER_CTRL_REG(chan));
134860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		}
135860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	}
136860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood
137860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood	return IRQ_HANDLED;
138b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood}
139b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
14036682e575c7db04549ae504dd13896dd31c5a014Chase Southwoodstatic int apci1564_di_insn_bits(struct comedi_device *dev,
14136682e575c7db04549ae504dd13896dd31c5a014Chase Southwood				 struct comedi_subdevice *s,
14236682e575c7db04549ae504dd13896dd31c5a014Chase Southwood				 struct comedi_insn *insn,
14336682e575c7db04549ae504dd13896dd31c5a014Chase Southwood				 unsigned int *data)
14436682e575c7db04549ae504dd13896dd31c5a014Chase Southwood{
1454c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	struct apci1564_private *devpriv = dev->private;
14636682e575c7db04549ae504dd13896dd31c5a014Chase Southwood
1474c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	data[1] = inl(devpriv->amcc_iobase + APCI1564_DI_REG);
14836682e575c7db04549ae504dd13896dd31c5a014Chase Southwood
14936682e575c7db04549ae504dd13896dd31c5a014Chase Southwood	return insn->n;
15036682e575c7db04549ae504dd13896dd31c5a014Chase Southwood}
15136682e575c7db04549ae504dd13896dd31c5a014Chase Southwood
15296211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwoodstatic int apci1564_do_insn_bits(struct comedi_device *dev,
15396211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood				 struct comedi_subdevice *s,
15496211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood				 struct comedi_insn *insn,
15596211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood				 unsigned int *data)
15696211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood{
1574c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	struct apci1564_private *devpriv = dev->private;
15896211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood
1594c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	s->state = inl(devpriv->amcc_iobase + APCI1564_DO_REG);
16096211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood
16196211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood	if (comedi_dio_update_state(s, data))
1624c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood		outl(s->state, devpriv->amcc_iobase + APCI1564_DO_REG);
16396211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood
16496211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood	data[1] = s->state;
16596211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood
16696211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood	return insn->n;
16796211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood}
16896211ca58a5d43e6cb527b2a110fbc5df4d15949Chase Southwood
1696347fc88ec4453934a5428e21051ff95cad01180Chase Southwoodstatic int apci1564_diag_insn_bits(struct comedi_device *dev,
1706347fc88ec4453934a5428e21051ff95cad01180Chase Southwood				   struct comedi_subdevice *s,
1716347fc88ec4453934a5428e21051ff95cad01180Chase Southwood				   struct comedi_insn *insn,
1726347fc88ec4453934a5428e21051ff95cad01180Chase Southwood				   unsigned int *data)
1736347fc88ec4453934a5428e21051ff95cad01180Chase Southwood{
1746347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	struct apci1564_private *devpriv = dev->private;
1756347fc88ec4453934a5428e21051ff95cad01180Chase Southwood
1766347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	data[1] = inl(devpriv->amcc_iobase + APCI1564_DO_INT_STATUS_REG) & 3;
1776347fc88ec4453934a5428e21051ff95cad01180Chase Southwood
1786347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	return insn->n;
1796347fc88ec4453934a5428e21051ff95cad01180Chase Southwood}
1806347fc88ec4453934a5428e21051ff95cad01180Chase Southwood
1811e15687ea472614d48416c53bebcf213c07a5532Chase Southwood/*
1821e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * Change-Of-State (COS) interrupt configuration
1831e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
1841e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * Channels 0 to 15 are interruptible. These channels can be configured
1851e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * to generate interrupts based on AND/OR logic for the desired channels.
1861e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
1871e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	OR logic
1881e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		- reacts to rising or falling edges
1891e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		- interrupt is generated when any enabled channel
1901e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		  meet the desired interrupt condition
1911e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
1921e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	AND logic
1931e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		- reacts to changes in level of the selected inputs
1941e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		- interrupt is generated when all enabled channels
1951e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		  meet the desired interrupt condition
1961e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		- after an interrupt, a change in level must occur on
1971e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *		  the selected inputs to release the IRQ logic
1981e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
1991e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * The COS interrupt must be configured before it can be enabled.
2001e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
2011e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[0] : INSN_CONFIG_DIGITAL_TRIG
2021e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[1] : trigger number (= 0)
2031e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[2] : configuration operation:
2041e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	          COMEDI_DIGITAL_TRIG_DISABLE = no interrupts
2051e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	          COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts
2061e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	          COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts
2071e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[3] : left-shift for data[4] and data[5]
2081e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[4] : rising-edge/high level channels
2091e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *	data[5] : falling-edge/low level channels
2101e15687ea472614d48416c53bebcf213c07a5532Chase Southwood */
2111e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_cos_insn_config(struct comedi_device *dev,
2121e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				    struct comedi_subdevice *s,
2131e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				    struct comedi_insn *insn,
2141e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				    unsigned int *data)
215b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood{
2164c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	struct apci1564_private *devpriv = dev->private;
2171e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	unsigned int shift, oldmask;
2181e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
2191e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	switch (data[0]) {
2201e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	case INSN_CONFIG_DIGITAL_TRIG:
2211e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		if (data[1] != 0)
2221e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			return -EINVAL;
2231e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		shift = data[3];
2241e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		oldmask = (1U << shift) - 1;
2251e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		switch (data[2]) {
2261e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		case COMEDI_DIGITAL_TRIG_DISABLE:
2271e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->ctrl = 0;
2281e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode1 = 0;
2291e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode2 = 0;
230f89ced89d8c0d155e8d802612e3860a440d04afeChase Southwood			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
231f89ced89d8c0d155e8d802612e3860a440d04afeChase Southwood			inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
232f89ced89d8c0d155e8d802612e3860a440d04afeChase Southwood			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
233f89ced89d8c0d155e8d802612e3860a440d04afeChase Southwood			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
2341e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			break;
2351e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
2361e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
2371e15687ea472614d48416c53bebcf213c07a5532Chase Southwood					      APCI1564_DI_INT_OR)) {
2381e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* switching to 'OR' mode */
2391e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->ctrl = APCI1564_DI_INT_ENABLE |
2401e15687ea472614d48416c53bebcf213c07a5532Chase Southwood						APCI1564_DI_INT_OR;
2411e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* wipe old channels */
2421e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode1 = 0;
2431e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode2 = 0;
2441e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			} else {
2451e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* preserve unspecified channels */
2461e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode1 &= oldmask;
2471e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode2 &= oldmask;
2481e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			}
2491e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			/* configure specified channels */
2501e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode1 |= data[4] << shift;
2511e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode2 |= data[5] << shift;
2521e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			break;
2531e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
2541e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
2551e15687ea472614d48416c53bebcf213c07a5532Chase Southwood					      APCI1564_DI_INT_AND)) {
2561e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* switching to 'AND' mode */
2571e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->ctrl = APCI1564_DI_INT_ENABLE |
2581e15687ea472614d48416c53bebcf213c07a5532Chase Southwood						APCI1564_DI_INT_AND;
2591e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* wipe old channels */
2601e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode1 = 0;
2611e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode2 = 0;
2621e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			} else {
2631e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				/* preserve unspecified channels */
2641e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode1 &= oldmask;
2651e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				devpriv->mode2 &= oldmask;
2661e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			}
2671e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			/* configure specified channels */
2681e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode1 |= data[4] << shift;
2691e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			devpriv->mode2 |= data[5] << shift;
2701e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			break;
2711e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		default:
2721e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			return -EINVAL;
2731e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		}
2741e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		break;
2751e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	default:
2761e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		return -EINVAL;
2771e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	}
2781e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	return insn->n;
2791e15687ea472614d48416c53bebcf213c07a5532Chase Southwood}
280aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
2811e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_cos_insn_bits(struct comedi_device *dev,
2821e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				  struct comedi_subdevice *s,
2831e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				  struct comedi_insn *insn,
2841e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				  unsigned int *data)
2851e15687ea472614d48416c53bebcf213c07a5532Chase Southwood{
2861e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	data[1] = s->state;
287aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
2881e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	return 0;
2891e15687ea472614d48416c53bebcf213c07a5532Chase Southwood}
290aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
2911e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_cos_cmdtest(struct comedi_device *dev,
2921e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				struct comedi_subdevice *s,
2931e15687ea472614d48416c53bebcf213c07a5532Chase Southwood				struct comedi_cmd *cmd)
2941e15687ea472614d48416c53bebcf213c07a5532Chase Southwood{
2951e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	int err = 0;
296aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
2971e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Step 1 : check if triggers are trivially valid */
298aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
2991e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
3001e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
3011e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
3021e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
3031e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
304aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
3051e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	if (err)
3061e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		return 1;
3071e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3081e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Step 2a : make sure trigger sources are unique */
3091e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Step 2b : and mutually compatible */
3101e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3111e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Step 3: check if arguments are trivially valid */
3121e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3131e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
3141e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
3151e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
3161e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
3171e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
3181e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3191e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	if (err)
3201e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		return 3;
3211e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
322cc67b0167a366f4b13935fe05abd58d396c30375H Hartley Sweeten	/* Step 4: fix up any arguments */
3231e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
324cc67b0167a366f4b13935fe05abd58d396c30375H Hartley Sweeten	/* Step 5: check channel list if it exists */
3251e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3261e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	return 0;
3271e15687ea472614d48416c53bebcf213c07a5532Chase Southwood}
3281e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3291e15687ea472614d48416c53bebcf213c07a5532Chase Southwood/*
3301e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * Change-Of-State (COS) 'do_cmd' operation
3311e15687ea472614d48416c53bebcf213c07a5532Chase Southwood *
3321e15687ea472614d48416c53bebcf213c07a5532Chase Southwood * Enable the COS interrupt as configured by apci1564_cos_insn_config().
3331e15687ea472614d48416c53bebcf213c07a5532Chase Southwood */
3341e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_cos_cmd(struct comedi_device *dev,
3351e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			    struct comedi_subdevice *s)
3361e15687ea472614d48416c53bebcf213c07a5532Chase Southwood{
3371e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	struct apci1564_private *devpriv = dev->private;
3381e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3391e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	if (!devpriv->ctrl) {
3401e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		dev_warn(dev->class_dev,
3411e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			"Interrupts disabled due to mode configuration!\n");
3421e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		return -EINVAL;
3431e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	}
3441e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3451e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(devpriv->mode1, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
3461e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(devpriv->mode2, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
3471e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(devpriv->ctrl, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
3481e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3491e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	return 0;
3501e15687ea472614d48416c53bebcf213c07a5532Chase Southwood}
3511e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3521e15687ea472614d48416c53bebcf213c07a5532Chase Southwoodstatic int apci1564_cos_cancel(struct comedi_device *dev,
3531e15687ea472614d48416c53bebcf213c07a5532Chase Southwood			       struct comedi_subdevice *s)
3541e15687ea472614d48416c53bebcf213c07a5532Chase Southwood{
3551e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	struct apci1564_private *devpriv = dev->private;
3561e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
3571e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
3581e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
3591e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
3601e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
361b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
362b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	return 0;
363b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood}
364b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
36543ba213156dba3afb4c8367da16c3d90aa87d2f8H Hartley Sweetenstatic int apci1564_auto_attach(struct comedi_device *dev,
366b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood				      unsigned long context_unused)
367b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood{
368b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
3694c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	struct apci1564_private *devpriv;
370b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	struct comedi_subdevice *s;
3719f2dbefb0ddb548b9a062f6ca729534efc15b0d6Chase Southwood	int ret;
372b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
373b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
374b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	if (!devpriv)
375b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood		return -ENOMEM;
376b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
377b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	ret = comedi_pci_enable(dev);
378b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	if (ret)
379b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood		return ret;
380b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
381128f798918c398b5ae84e5734c3b5df8c35d5d94Chase Southwood	dev->iobase = pci_resource_start(pcidev, 1);
3824c95a2b6b531e2caae211803d0ef88600c5d5f06Chase Southwood	devpriv->amcc_iobase = pci_resource_start(pcidev, 0);
383b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
384aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood	apci1564_reset(dev);
385aed3f9d498babd9cf4f0656e4a415cd25c725aa3Chase Southwood
386b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	if (pcidev->irq > 0) {
387860ba36cbeadee9064e2925be11dfb8368b9b25dChase Southwood		ret = request_irq(pcidev->irq, apci1564_interrupt, IRQF_SHARED,
388b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood				  dev->board_name, dev);
389b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood		if (ret == 0)
390b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood			dev->irq = pcidev->irq;
391b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	}
392b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
3936347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	ret = comedi_alloc_subdevices(dev, 6);
394b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	if (ret)
395b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood		return ret;
396b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
397b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	/*  Allocate and Initialise DI Subdevice Structures */
3989f2dbefb0ddb548b9a062f6ca729534efc15b0d6Chase Southwood	s = &dev->subdevices[0];
3996caf60158821699e772a9545b030c7254519078eChase Southwood	s->type		= COMEDI_SUBD_DI;
4006caf60158821699e772a9545b030c7254519078eChase Southwood	s->subdev_flags	= SDF_READABLE;
4016caf60158821699e772a9545b030c7254519078eChase Southwood	s->n_chan	= 32;
4026caf60158821699e772a9545b030c7254519078eChase Southwood	s->maxdata	= 1;
4036caf60158821699e772a9545b030c7254519078eChase Southwood	s->range_table	= &range_digital;
4046caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_bits	= apci1564_di_insn_bits;
405cffd83b6d1e6e403a77c5babf1443cdfd1a080efChase Southwood
406b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	/*  Allocate and Initialise DO Subdevice Structures */
4079f2dbefb0ddb548b9a062f6ca729534efc15b0d6Chase Southwood	s = &dev->subdevices[1];
4086caf60158821699e772a9545b030c7254519078eChase Southwood	s->type		= COMEDI_SUBD_DO;
4096caf60158821699e772a9545b030c7254519078eChase Southwood	s->subdev_flags	= SDF_WRITEABLE;
4106caf60158821699e772a9545b030c7254519078eChase Southwood	s->n_chan	= 32;
4116caf60158821699e772a9545b030c7254519078eChase Southwood	s->maxdata	= 1;
4126caf60158821699e772a9545b030c7254519078eChase Southwood	s->range_table	= &range_digital;
4136caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_bits	= apci1564_do_insn_bits;
414b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
4151e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	/* Change-Of-State (COS) interrupt subdevice */
4161496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	s = &dev->subdevices[2];
4171e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	if (dev->irq) {
4181e15687ea472614d48416c53bebcf213c07a5532Chase Southwood		dev->read_subdev = s;
4196caf60158821699e772a9545b030c7254519078eChase Southwood		s->type		= COMEDI_SUBD_DI;
4206caf60158821699e772a9545b030c7254519078eChase Southwood		s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
4216caf60158821699e772a9545b030c7254519078eChase Southwood		s->n_chan	= 1;
4226caf60158821699e772a9545b030c7254519078eChase Southwood		s->maxdata	= 1;
4236caf60158821699e772a9545b030c7254519078eChase Southwood		s->range_table	= &range_digital;
4246caf60158821699e772a9545b030c7254519078eChase Southwood		s->len_chanlist	= 1;
4256caf60158821699e772a9545b030c7254519078eChase Southwood		s->insn_config	= apci1564_cos_insn_config;
4266caf60158821699e772a9545b030c7254519078eChase Southwood		s->insn_bits	= apci1564_cos_insn_bits;
4276caf60158821699e772a9545b030c7254519078eChase Southwood		s->do_cmdtest	= apci1564_cos_cmdtest;
4286caf60158821699e772a9545b030c7254519078eChase Southwood		s->do_cmd	= apci1564_cos_cmd;
4296caf60158821699e772a9545b030c7254519078eChase Southwood		s->cancel	= apci1564_cos_cancel;
4301e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	} else {
4316caf60158821699e772a9545b030c7254519078eChase Southwood		s->type		= COMEDI_SUBD_UNUSED;
4321e15687ea472614d48416c53bebcf213c07a5532Chase Southwood	}
4331e15687ea472614d48416c53bebcf213c07a5532Chase Southwood
4341496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	/*  Allocate and Initialise Timer Subdevice Structures */
4351496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	s = &dev->subdevices[3];
4366caf60158821699e772a9545b030c7254519078eChase Southwood	s->type		= COMEDI_SUBD_TIMER;
4376caf60158821699e772a9545b030c7254519078eChase Southwood	s->subdev_flags	= SDF_WRITEABLE;
4386caf60158821699e772a9545b030c7254519078eChase Southwood	s->n_chan	= 1;
4396caf60158821699e772a9545b030c7254519078eChase Southwood	s->maxdata	= 0;
4406caf60158821699e772a9545b030c7254519078eChase Southwood	s->len_chanlist	= 1;
4416caf60158821699e772a9545b030c7254519078eChase Southwood	s->range_table	= &range_digital;
4426caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_write	= apci1564_timer_write;
4436caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_read	= apci1564_timer_read;
4446caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_config	= apci1564_timer_config;
4451496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood
4461496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	/* Initialize the watchdog subdevice */
4471496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	s = &dev->subdevices[4];
4481496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	ret = addi_watchdog_init(s, devpriv->amcc_iobase + APCI1564_WDOG_REG);
4491496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood	if (ret)
4501496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood		return ret;
4511496e5961113860e97e8fc39c4fdc0e83c1fbcabChase Southwood
4526347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	/* Initialize the diagnostic status subdevice */
4536347fc88ec4453934a5428e21051ff95cad01180Chase Southwood	s = &dev->subdevices[5];
4546caf60158821699e772a9545b030c7254519078eChase Southwood	s->type		= COMEDI_SUBD_DI;
4556caf60158821699e772a9545b030c7254519078eChase Southwood	s->subdev_flags	= SDF_READABLE;
4566caf60158821699e772a9545b030c7254519078eChase Southwood	s->n_chan	= 2;
4576caf60158821699e772a9545b030c7254519078eChase Southwood	s->maxdata	= 1;
4586caf60158821699e772a9545b030c7254519078eChase Southwood	s->range_table	= &range_digital;
4596caf60158821699e772a9545b030c7254519078eChase Southwood	s->insn_bits	= apci1564_diag_insn_bits;
4606347fc88ec4453934a5428e21051ff95cad01180Chase Southwood
461b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	return 0;
462b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood}
463b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood
464b30c3e824ebaa142bf7361c567612727d24af717Chase Southwoodstatic void apci1564_detach(struct comedi_device *dev)
46543ba213156dba3afb4c8367da16c3d90aa87d2f8H Hartley Sweeten{
46671893bb077a61c7b590bf7780422407a01a409c0Chase Southwood	if (dev->iobase)
46771893bb077a61c7b590bf7780422407a01a409c0Chase Southwood		apci1564_reset(dev);
468aac307f9dd5ce1fe651140a036ab4b0a0571b54aH Hartley Sweeten	comedi_pci_detach(dev);
46943ba213156dba3afb4c8367da16c3d90aa87d2f8H Hartley Sweeten}
47043ba213156dba3afb4c8367da16c3d90aa87d2f8H Hartley Sweeten
47120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct comedi_driver apci1564_driver = {
47220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.driver_name	= "addi_apci_1564",
47320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.module		= THIS_MODULE,
47443ba213156dba3afb4c8367da16c3d90aa87d2f8H Hartley Sweeten	.auto_attach	= apci1564_auto_attach,
475b30c3e824ebaa142bf7361c567612727d24af717Chase Southwood	.detach		= apci1564_detach,
47620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
47720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
478a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int apci1564_pci_probe(struct pci_dev *dev,
479b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten			      const struct pci_device_id *id)
48020a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{
481b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten	return comedi_pci_auto_config(dev, &apci1564_driver, id->driver_data);
48220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}
48320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
48441e043fcfa2236bb2c4a8335eb09f4c8cee224b3Jingoo Hanstatic const struct pci_device_id apci1564_pci_table[] = {
485317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1006) },
486317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten	{ 0 }
487317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten};
48820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley SweetenMODULE_DEVICE_TABLE(pci, apci1564_pci_table);
489317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten
49020a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct pci_driver apci1564_pci_driver = {
49120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.name		= "addi_apci_1564",
49220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.id_table	= apci1564_pci_table,
49320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.probe		= apci1564_pci_probe,
4949901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe	.remove		= comedi_pci_auto_unconfig,
49520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
49620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenmodule_comedi_pci_driver(apci1564_driver, apci1564_pci_driver);
49790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
49890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
499b5ebcaa8d3405e14ca431257fd6c6cdc30df13c5Georg GastMODULE_DESCRIPTION("ADDI-DATA APCI-1564, 32 channel DI / 32 channel DO boards");
50090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
501