16a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
26a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    comedi/drivers/amplc_pc236.c
36a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    Driver for Amplicon PC36AT and PCI236 DIO boards.
46a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
56a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    Copyright (C) 2002 MEV Ltd. <http://www.mev.co.uk/>
66a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
76a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    COMEDI - Linux Control and Measurement Device Interface
86a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
96a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
106a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    This program is free software; you can redistribute it and/or modify
116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    it under the terms of the GNU General Public License as published by
126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    the Free Software Foundation; either version 2 of the License, or
136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    (at your option) any later version.
146a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
156a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    This program is distributed in the hope that it will be useful,
166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    but WITHOUT ANY WARRANTY; without even the implied warranty of
176a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
186a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    GNU General Public License for more details.
196a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
206a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    You should have received a copy of the GNU General Public License
216a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    along with this program; if not, write to the Free Software
226a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
246a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott*/
256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
266a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottDriver: amplc_pc236
276a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottDescription: Amplicon PC36AT, PCI236
286a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottAuthor: Ian Abbott <abbotti@mev.co.uk>
296a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottDevices: [Amplicon] PC36AT (pc36at), PCI236 (pci236 or amplc_pc236)
300d6e5dad12c5a2860e3d13b4d7a4702f90386003Ian AbbottUpdated: Wed, 01 Apr 2009 15:41:25 +0100
316a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottStatus: works
326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottConfiguration options - PC36AT:
346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  [0] - I/O port base address
356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  [1] - IRQ (optional)
366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottConfiguration options - PCI236:
386a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  [0] - PCI bus of device (optional)
396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  [1] - PCI slot of device (optional)
406a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  If bus/slot is not specified, the first available PCI device will be
416a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott  used.
426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
436a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottThe PC36AT ISA board and PCI236 PCI board have a single 8255 appearing
446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottas subdevice 0.
456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
466a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottSubdevice 1 pretends to be a digital input device, but it always returns
476a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott0 when read. However, if you run a command with scan_begin_src=TRIG_EXT,
480d6e5dad12c5a2860e3d13b4d7a4702f90386003Ian Abbotta rising edge on port C bit 3 acts as an external trigger, which can be
496a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottused to wake up tasks.  This is like the comedi_parport device, but the
506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottonly way to physically disable the interrupt on the PC36AT is to remove
516a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottthe IRQ jumper.  If no interrupt is connected, then subdevice 1 is
526a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottunused.
536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott*/
546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
5670265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby
576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#include "../comedidev.h"
586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#include "comedi_pci.h"
606a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
616a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#include "8255.h"
626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#include "plx9052.h"
636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PC236_DRIVER_NAME	"amplc_pc236"
656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/* PCI236 PCI configuration register information */
676a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PCI_VENDOR_ID_AMPLICON 0x14dc
686a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PCI_DEVICE_ID_INVALID 0xffff
706a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
716a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/* PC36AT / PCI236 registers */
726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
736a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PC236_IO_SIZE		4
746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#define PC236_LCR_IO_SIZE	128
756a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
766a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * INTCSR values for PCI236.
786a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/* Disable interrupt, also clear any interrupt there */
8053106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1ENAB_DISABLED \
819f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1POL_HIGH \
829f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI2POL_HIGH \
839f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_PCIENAB_DISABLED \
849f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1SEL_EDGE \
859f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1CLRINT_ASSERTED)
866a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/* Enable interrupt, also clear any interrupt there. */
8753106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB_ENABLED \
889f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1POL_HIGH \
899f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI2POL_HIGH \
909f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_PCIENAB_ENABLED \
919f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1SEL_EDGE \
929f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	| PLX9052_INTCSR_LI1CLRINT_ASSERTED)
936a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Board descriptions for Amplicon PC36AT and PCI236.
966a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottenum pc236_bustype { isa_bustype, pci_bustype };
996a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottenum pc236_model { pc36at_model, pci236_model, anypci_model };
1006a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
10157ad869651d1d2f163a1c5ccb577ee794847fd77Bill Pembertonstruct pc236_board {
1026a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	const char *name;
1036a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	const char *fancy_name;
1046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned short devid;
1056a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	enum pc236_bustype bustype;
1066a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	enum pc236_model model;
10757ad869651d1d2f163a1c5ccb577ee794847fd77Bill Pemberton};
10857ad869651d1d2f163a1c5ccb577ee794847fd77Bill Pembertonstatic const struct pc236_board pc236_boards[] = {
1096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	{
1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pc36at",
1110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fancy_name = "PC36AT",
1120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .bustype = isa_bustype,
1130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .model = pc36at_model,
1140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
1156a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
1166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	{
1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci236",
1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fancy_name = "PCI236",
1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .devid = PCI_DEVICE_ID_AMPLICON_PCI236,
1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .bustype = pci_bustype,
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .model = pci236_model,
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
1236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
1246a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
1256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	{
1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = PC236_DRIVER_NAME,
1270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fancy_name = PC236_DRIVER_NAME,
1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .devid = PCI_DEVICE_ID_INVALID,
1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .bustype = pci_bustype,
1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .model = anypci_model,	/* wildcard */
1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
1326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
1336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott};
1346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
1366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottstatic DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
1377b0be12b26d86ea2bd5079f0d723289e2f5a43a9Peter Huewe	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
1387b0be12b26d86ea2bd5079f0d723289e2f5a43a9Peter Huewe	{0}
1396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott};
1406a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1416a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan AbbottMODULE_DEVICE_TABLE(pci, pc236_pci_table);
1426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif /* CONFIG_COMEDI_PCI */
1436a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
1456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Useful for shorthand access to the particular board structure
1466a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
14757ad869651d1d2f163a1c5ccb577ee794847fd77Bill Pemberton#define thisboard ((const struct pc236_board *)dev->board_ptr)
1486a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1496a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/* this structure is for data unique to this hardware driver.  If
1506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott   several hardware drivers keep similar information in this structure,
1519f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi   feel free to suggest moving the variable to the struct comedi_device struct.
1529f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi */
153f1ee810a1383b623ec523edd521467a7b620a09aBill Pembertonstruct pc236_private {
1546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
1556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* PCI device */
1566a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	struct pci_dev *pci_dev;
1579f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
1586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
1596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int enable_irq;
160f1ee810a1383b623ec523edd521467a7b620a09aBill Pemberton};
1616a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
162f1ee810a1383b623ec523edd521467a7b620a09aBill Pemberton#define devpriv ((struct pc236_private *)dev->private)
1636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
165139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
1666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * which functions to call to configure/deconfigure (attach/detach)
1676a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * the board, and also about the kernel module that contains
1686a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * the device code.
1696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
170da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it);
171da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_detach(struct comedi_device *dev);
172139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_amplc_pc236 = {
17368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PC236_DRIVER_NAME,
17468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
17568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pc236_attach,
17668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pc236_detach,
17768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &pc236_boards[0].name,
17868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct pc236_board),
1798629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton	.num_names = ARRAY_SIZE(pc236_boards),
1806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott};
1816a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
1826a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
183727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev,
184727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas						  const struct pci_device_id
185727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas						  *ent)
186727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
187727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name);
188727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
189727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
190727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev)
191727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
192727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
193727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
194727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
195727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_amplc_pc236_pci_driver = {
196727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = pc236_pci_table,
197727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_amplc_pc236_pci_probe,
198727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_amplc_pc236_pci_remove)
199727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
200727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
201727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_amplc_pc236_init_module(void)
202727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
203727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
204727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
205727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_amplc_pc236);
206727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
207727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
208727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
209727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_amplc_pc236_pci_driver.name =
210727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	    (char *)driver_amplc_pc236.driver_name;
211727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_amplc_pc236_pci_driver);
212727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
213727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
214727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_amplc_pc236_cleanup_module(void)
215727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
216727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_amplc_pc236_pci_driver);
217727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_amplc_pc236);
218727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
219727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
220727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_amplc_pc236_init_module);
221727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_amplc_pc236_cleanup_module);
2226a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#else
2237114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_amplc_pc236_init_module(void)
2247114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
2257114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_amplc_pc236);
2267114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
2277114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
2287114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_amplc_pc236_cleanup_module(void)
2297114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
2307114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_amplc_pc236);
2317114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
2327114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
2337114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_amplc_pc236_init_module);
2347114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_amplc_pc236_cleanup_module);
2356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
2366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottstatic int pc236_request_region(unsigned minor, unsigned long from,
2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				unsigned long extent);
239814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void pc236_intr_disable(struct comedi_device *dev);
240814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void pc236_intr_enable(struct comedi_device *dev);
241814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int pc236_intr_check(struct comedi_device *dev);
2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_insn(struct comedi_device *dev,
2430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
2440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_cmdtest(struct comedi_device *dev,
2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd);
2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_cmd(struct comedi_device *dev,
2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
2500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_cancel(struct comedi_device *dev,
2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s);
25270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pc236_interrupt(int irq, void *d);
2536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
2556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function looks for a PCI device matching the requested board name,
2566a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * bus and slot.
2576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
2586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
2596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottstatic int
260da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpc236_find_pci(struct comedi_device *dev, int bus, int slot,
2610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       struct pci_dev **pci_dev_p)
2626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
2636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	struct pci_dev *pci_dev = NULL;
2646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	*pci_dev_p = NULL;
2666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2676a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* Look for matching PCI device. */
2686a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
2690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_dev != NULL;
2700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
2710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      PCI_ANY_ID, pci_dev)) {
2726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		/* If bus/slot specified, check them. */
2736a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		if (bus || slot) {
2746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			if (bus != pci_dev->bus->number
2750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || slot != PCI_SLOT(pci_dev->devfn))
2766a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				continue;
2776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
2786a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		if (thisboard->model == anypci_model) {
2796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			/* Match any supported model. */
2806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			int i;
2816a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2826a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) {
2836a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				if (pc236_boards[i].bustype != pci_bustype)
2846a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott					continue;
2856a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				if (pci_dev->device == pc236_boards[i].devid) {
2866a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott					/* Change board_ptr to matched board. */
2876a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott					dev->board_ptr = &pc236_boards[i];
2886a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott					break;
2896a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				}
2906a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			}
2916a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			if (i == ARRAY_SIZE(pc236_boards))
2926a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				continue;
2936a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		} else {
2946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			/* Match specific model name. */
2956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			if (pci_dev->device != thisboard->devid)
2966a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				continue;
2976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
2986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
2996a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		/* Found a match. */
3006a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		*pci_dev_p = pci_dev;
3016a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return 0;
3026a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
3036a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* No match found. */
3046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (bus || slot) {
3056a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR
3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       "comedi%d: error! no %s found at pci %02x:%02x!\n",
3070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor, thisboard->name, bus, slot);
3086a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	} else {
3096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR "comedi%d: error! no %s found!\n",
3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor, thisboard->name);
3116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
3126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return -EIO;
3136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
3146a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
3156a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
3166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
3176a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Attach is called by the Comedi core to configure the driver
3186a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * for a particular board.  If you specified a board_name array
3196a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * in the driver structure, dev->board_ptr contains that
3206a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * address.
3216a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
322da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
3236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
32434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
3256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned long iobase = 0;
3266a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned int irq = 0;
3276a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
3286a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	struct pci_dev *pci_dev = NULL;
3296a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int bus = 0, slot = 0;
3306a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
3316a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int share_irq = 0;
3326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int ret;
3336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
3346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PC236_DRIVER_NAME);
3366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
3376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Allocate the private structure area.  alloc_private() is a
3386a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * convenient macro defined in comedidev.h.
3396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
340c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	ret = alloc_private(dev, sizeof(struct pc236_private));
341c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (ret < 0) {
3426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR "comedi%d: error! out of memory!\n",
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor);
3446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return ret;
3456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
3466a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* Process options. */
3476a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	switch (thisboard->bustype) {
3486a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	case isa_bustype:
3496a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		iobase = it->options[0];
3506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		irq = it->options[1];
3516a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		share_irq = 0;
3526a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		break;
3536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
3546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	case pci_bustype:
3556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		bus = it->options[0];
3566a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		slot = it->options[1];
3576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		share_irq = 1;
3586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
359c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		ret = pc236_find_pci(dev, bus, slot, &pci_dev);
360c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		if (ret < 0)
3616a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			return ret;
3626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		devpriv->pci_dev = pci_dev;
3636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		break;
3646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif /* CONFIG_COMEDI_PCI */
3656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	default:
3666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR
3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       "comedi%d: %s: BUG! cannot determine board type!\n",
3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor, PC236_DRIVER_NAME);
3696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return -EINVAL;
3706a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		break;
3716a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
3726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
3736a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
3746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Initialize dev->board_name.
3756a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
3766a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	dev->board_name = thisboard->name;
3776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
3786a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* Enable device and reserve I/O spaces. */
3796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
3806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (pci_dev) {
381c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton
382c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME);
383c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton		if (ret < 0) {
3846a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			printk(KERN_ERR
3850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       "comedi%d: error! cannot enable PCI device and request regions!\n",
3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       dev->minor);
3876a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			return ret;
3886a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
3896a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		devpriv->lcr_iobase = pci_resource_start(pci_dev, 1);
3906a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		iobase = pci_resource_start(pci_dev, 2);
3916a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		irq = pci_dev->irq;
3926a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	} else
3936a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
3946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	{
3956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE);
3969f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi		if (ret < 0)
3976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			return ret;
3986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
3996a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	dev->iobase = iobase;
4006a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4016a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
4026a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Allocate the subdevice structures.  alloc_subdevice() is a
4036a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * convenient macro defined in comedidev.h.
4046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
405c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	ret = alloc_subdevices(dev, 2);
406c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (ret < 0) {
4076a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR "comedi%d: error! out of memory!\n",
4080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor);
4096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return ret;
4106a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	s = dev->subdevices + 0;
4136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* digital i/o subdevice (8255) */
414c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	ret = subdev_8255_init(dev, s, NULL, iobase);
415c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (ret < 0) {
4166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR "comedi%d: error! out of memory!\n",
4170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor);
4186a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return ret;
4196a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4206a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	s = dev->subdevices + 1;
4216a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	dev->read_subdev = s;
4226a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	s->type = COMEDI_SUBD_UNUSED;
4236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	pc236_intr_disable(dev);
4246a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (irq) {
4256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		unsigned long flags = share_irq ? IRQF_SHARED : 0;
4266a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4275f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(irq, pc236_interrupt, flags,
4286a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				PC236_DRIVER_NAME, dev) >= 0) {
4296a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			dev->irq = irq;
4306a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->type = COMEDI_SUBD_DI;
4316a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
4326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->n_chan = 1;
4336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->maxdata = 1;
4346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->range_table = &range_digital;
4356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->insn_bits = pc236_intr_insn;
4366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->do_cmdtest = pc236_intr_cmdtest;
4376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->do_cmd = pc236_intr_cmd;
4386a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			s->cancel = pc236_intr_cancel;
4396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
4406a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4416a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
4426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (thisboard->bustype == isa_bustype) {
4436a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk("(base %#lx) ", iobase);
4446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	} else {
4456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
4466a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk("(pci %s) ", pci_name(pci_dev));
4476a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
4486a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4499f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	if (irq)
4506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
4519f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	else
4526a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk("(no irq) ");
4536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	printk("attached\n");
4556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4566a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 1;
4576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
4586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
4606a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * _detach is called to deconfigure a device.  It should deallocate
4616a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * resources.
4626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function is also called when _attach() fails, so it should be
4636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * careful not to release resources that were not necessarily
4646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * allocated by _attach().  dev->private and dev->subdevices are
4656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * deallocated automatically by the core.
4666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
467da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_detach(struct comedi_device *dev)
4686a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
4696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PC236_DRIVER_NAME);
4719f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	if (devpriv)
4726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		pc236_intr_disable(dev);
4739f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi
4746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (dev->irq)
4755f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
4769f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi	if (dev->subdevices)
4776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		subdev_8255_cleanup(dev, dev->subdevices + 0);
4786a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (devpriv) {
4796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
4806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		if (devpriv->pci_dev) {
4819f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi			if (dev->iobase)
4826a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				comedi_pci_disable(devpriv->pci_dev);
4836a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			pci_dev_put(devpriv->pci_dev);
4846a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		} else
4856a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
4866a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		{
4879f7a344b69485dc1052534a4e1b2e5a8f7de086eBenjamin Adolphi			if (dev->iobase)
4886a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				release_region(dev->iobase, PC236_IO_SIZE);
4896a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
4906a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4916a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (dev->board_name) {
4926a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_INFO "comedi%d: %s removed\n",
4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev->minor, dev->board_name);
4946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
4956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 0;
4966a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
4976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
4986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
4996a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function checks and requests an I/O region, reporting an error
5006a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * if there is a conflict.
5016a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
5026a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbottstatic int pc236_request_region(unsigned minor, unsigned long from,
5030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				unsigned long extent)
5046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
5056a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!from || !request_region(from, extent, PC236_DRIVER_NAME)) {
5066a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
5070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       minor, from, extent);
5086a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return -EIO;
5096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
5106a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 0;
5116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
5126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
5146a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function is called to mark the interrupt as disabled (no command
5156a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * configured on subdevice 1) and to physically disable the interrupt
5166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * (not possible on the PC36AT, except by removing the IRQ jumper!).
5176a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
518da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pc236_intr_disable(struct comedi_device *dev)
5196a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
5206a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned long flags;
5216a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5225f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
5236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	devpriv->enable_irq = 0;
5246a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
5256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (devpriv->lcr_iobase)
5266a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
5276a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
5285f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
5296a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
5306a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5316a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
5326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function is called to mark the interrupt as enabled (a command
5336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * configured on subdevice 1) and to physically enable the interrupt
5346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!).
5356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
536da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pc236_intr_enable(struct comedi_device *dev)
5376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
5386a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned long flags;
5396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5405f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
5416a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	devpriv->enable_irq = 1;
5426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
5436a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (devpriv->lcr_iobase)
5446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
5456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
5465f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
5476a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
5486a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5496a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
5506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * This function is called when an interrupt occurs to check whether
5516a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * the interrupt has been marked as enabled and was generated by the
5526a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * board.  If so, the function prepares the hardware for the next
5536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * interrupt.
5546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Returns 0 if the interrupt should be ignored.
5556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
556da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_intr_check(struct comedi_device *dev)
5576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
5586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int retval = 0;
5596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	unsigned long flags;
5606a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5615f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
5626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (devpriv->enable_irq) {
5636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		retval = 1;
5646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#ifdef CONFIG_COMEDI_PCI
5656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		if (devpriv->lcr_iobase) {
5666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR)
5670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     & PLX9052_INTCSR_LI1STAT_MASK)
5680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    == PLX9052_INTCSR_LI1STAT_INACTIVE) {
5696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				retval = 0;
5706a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			} else {
5716a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				/* Clear interrupt and keep it enabled. */
5726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott				outl(PCI236_INTR_ENABLE,
5730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     devpriv->lcr_iobase + PLX9052_INTCSR);
5746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott			}
5756a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		}
5766a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott#endif
5776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
5785f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
5796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return retval;
5816a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
5826a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5836a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
5846a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Input from subdevice 1.
5856a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Copied from the comedi_parport driver.
5866a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
5870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_insn(struct comedi_device *dev,
5880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
5890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
5906a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
5916a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	data[1] = 0;
5926a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 2;
5936a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
5946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
5956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
5966a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Subdevice 1 command test.
5976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Copied from the comedi_parport driver.
5986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
5990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_cmdtest(struct comedi_device *dev,
6000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
6010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
6026a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
6036a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int err = 0;
6046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int tmp;
6056a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6066a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* step 1 */
6076a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6086a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	tmp = cmd->start_src;
6096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	cmd->start_src &= TRIG_NOW;
6106a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!cmd->start_src || tmp != cmd->start_src)
6116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	tmp = cmd->scan_begin_src;
6146a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	cmd->scan_begin_src &= TRIG_EXT;
6156a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
6166a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6176a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6186a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	tmp = cmd->convert_src;
6196a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	cmd->convert_src &= TRIG_FOLLOW;
6206a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!cmd->convert_src || tmp != cmd->convert_src)
6216a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6226a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6236a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	tmp = cmd->scan_end_src;
6246a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	cmd->scan_end_src &= TRIG_COUNT;
6256a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
6266a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6276a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6286a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	tmp = cmd->stop_src;
6296a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	cmd->stop_src &= TRIG_NONE;
6306a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (!cmd->stop_src || tmp != cmd->stop_src)
6316a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6326a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6336a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (err)
6346a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return 1;
6356a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6366a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* step 2: ignored */
6376a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6386a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (err)
6396a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return 2;
6406a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6416a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* step 3: */
6426a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6436a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (cmd->start_arg != 0) {
6446a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		cmd->start_arg = 0;
6456a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6466a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
6476a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (cmd->scan_begin_arg != 0) {
6486a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		cmd->scan_begin_arg = 0;
6496a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6506a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
6516a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (cmd->convert_arg != 0) {
6526a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		cmd->convert_arg = 0;
6536a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6546a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
6556a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (cmd->scan_end_arg != 1) {
6566a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		cmd->scan_end_arg = 1;
6576a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6586a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
6596a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (cmd->stop_arg != 0) {
6606a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		cmd->stop_arg = 0;
6616a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		err++;
6626a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
6636a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6646a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (err)
6656a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return 3;
6666a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6676a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	/* step 4: ignored */
6686a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6696a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (err)
6706a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		return 4;
6716a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6726a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 0;
6736a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
6746a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6756a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
6766a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Subdevice 1 command.
6776a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
678da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
6796a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
6806a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	pc236_intr_enable(dev);
6816a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6826a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 0;
6836a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
6846a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6856a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
6866a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Subdevice 1 cancel command.
6876a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
6880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pc236_intr_cancel(struct comedi_device *dev,
6890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
6906a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
6916a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	pc236_intr_disable(dev);
6926a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6936a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return 0;
6946a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
6956a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
6966a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott/*
6976a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Interrupt service routine.
6986a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott * Based on the comedi_parport driver.
6996a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott */
70070265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pc236_interrupt(int irq, void *d)
7016a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott{
70271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
70334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 1;
7046a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	int handled;
7056a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott
7066a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	handled = pc236_intr_check(dev);
7076a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	if (dev->attached && handled) {
7086a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		comedi_buf_put(s->async, 0);
7096a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
7106a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott		comedi_event(dev, s);
7116a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	}
7126a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott	return IRQ_RETVAL(handled);
7136a5c8664766b82b36ec50bd2de9e72d3eae0dfbbIan Abbott}
71490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
71590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
71690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
71790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
718