16baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 26baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi/drivers/pcmmio.c 36baef150380d561a4d695a6be4fc509821c23611Calin Culianu Driver for Winsystems PC-104 based multifunction IO board. 46baef150380d561a4d695a6be4fc509821c23611Calin Culianu 56baef150380d561a4d695a6be4fc509821c23611Calin Culianu COMEDI - Linux Control and Measurement Device Interface 66baef150380d561a4d695a6be4fc509821c23611Calin Culianu Copyright (C) 2007 Calin A. Culianu <calin@ajvar.org> 76baef150380d561a4d695a6be4fc509821c23611Calin Culianu 86baef150380d561a4d695a6be4fc509821c23611Calin Culianu This program is free software; you can redistribute it and/or modify 96baef150380d561a4d695a6be4fc509821c23611Calin Culianu it under the terms of the GNU General Public License as published by 106baef150380d561a4d695a6be4fc509821c23611Calin Culianu the Free Software Foundation; either version 2 of the License, or 116baef150380d561a4d695a6be4fc509821c23611Calin Culianu (at your option) any later version. 126baef150380d561a4d695a6be4fc509821c23611Calin Culianu 136baef150380d561a4d695a6be4fc509821c23611Calin Culianu This program is distributed in the hope that it will be useful, 146baef150380d561a4d695a6be4fc509821c23611Calin Culianu but WITHOUT ANY WARRANTY; without even the implied warranty of 156baef150380d561a4d695a6be4fc509821c23611Calin Culianu MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 166baef150380d561a4d695a6be4fc509821c23611Calin Culianu GNU General Public License for more details. 176baef150380d561a4d695a6be4fc509821c23611Calin Culianu 186baef150380d561a4d695a6be4fc509821c23611Calin Culianu You should have received a copy of the GNU General Public License 196baef150380d561a4d695a6be4fc509821c23611Calin Culianu along with this program; if not, write to the Free Software 206baef150380d561a4d695a6be4fc509821c23611Calin Culianu Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 216baef150380d561a4d695a6be4fc509821c23611Calin Culianu*/ 226baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 236baef150380d561a4d695a6be4fc509821c23611Calin CulianuDriver: pcmmio 246baef150380d561a4d695a6be4fc509821c23611Calin CulianuDescription: A driver for the PCM-MIO multifunction board 256baef150380d561a4d695a6be4fc509821c23611Calin CulianuDevices: [Winsystems] PCM-MIO (pcmmio) 266baef150380d561a4d695a6be4fc509821c23611Calin CulianuAuthor: Calin Culianu <calin@ajvar.org> 276baef150380d561a4d695a6be4fc509821c23611Calin CulianuUpdated: Wed, May 16 2007 16:21:10 -0500 286baef150380d561a4d695a6be4fc509821c23611Calin CulianuStatus: works 296baef150380d561a4d695a6be4fc509821c23611Calin Culianu 306baef150380d561a4d695a6be4fc509821c23611Calin CulianuA driver for the relatively new PCM-MIO multifunction board from 316baef150380d561a4d695a6be4fc509821c23611Calin CulianuWinsystems. This board is a PC-104 based I/O board. It contains 326baef150380d561a4d695a6be4fc509821c23611Calin Culianufour subdevices: 336baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdevice 0 - 16 channels of 16-bit AI 346baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdevice 1 - 8 channels of 16-bit AO 35d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson subdevice 2 - first 24 channels of the 48 channel of DIO 36d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson (with edge-triggered interrupt support) 37d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson subdevice 3 - last 24 channels of the 48 channel DIO 38d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson (no interrupt support for this bank of channels) 396baef150380d561a4d695a6be4fc509821c23611Calin Culianu 406baef150380d561a4d695a6be4fc509821c23611Calin Culianu Some notes: 416baef150380d561a4d695a6be4fc509821c23611Calin Culianu 426baef150380d561a4d695a6be4fc509821c23611Calin Culianu Synchronous reads and writes are the only things implemented for AI and AO, 436baef150380d561a4d695a6be4fc509821c23611Calin Culianu even though the hardware itself can do streaming acquisition, etc. Anyone 446baef150380d561a4d695a6be4fc509821c23611Calin Culianu want to add asynchronous I/O for AI/AO as a feature? Be my guest... 456baef150380d561a4d695a6be4fc509821c23611Calin Culianu 466baef150380d561a4d695a6be4fc509821c23611Calin Culianu Asynchronous I/O for the DIO subdevices *is* implemented, however! They are 476baef150380d561a4d695a6be4fc509821c23611Calin Culianu basically edge-triggered interrupts for any configuration of the first 486baef150380d561a4d695a6be4fc509821c23611Calin Culianu 24 DIO-lines. 496baef150380d561a4d695a6be4fc509821c23611Calin Culianu 506baef150380d561a4d695a6be4fc509821c23611Calin Culianu Also note that this interrupt support is untested. 516baef150380d561a4d695a6be4fc509821c23611Calin Culianu 526baef150380d561a4d695a6be4fc509821c23611Calin Culianu A few words about edge-detection IRQ support (commands on DIO): 536baef150380d561a4d695a6be4fc509821c23611Calin Culianu 546baef150380d561a4d695a6be4fc509821c23611Calin Culianu * To use edge-detection IRQ support for the DIO subdevice, pass the IRQ 556baef150380d561a4d695a6be4fc509821c23611Calin Culianu of the board to the comedi_config command. The board IRQ is not jumpered 566baef150380d561a4d695a6be4fc509821c23611Calin Culianu but rather configured through software, so any IRQ from 1-15 is OK. 576baef150380d561a4d695a6be4fc509821c23611Calin Culianu 586baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Due to the genericity of the comedi API, you need to create a special 596baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_command in order to use edge-triggered interrupts for DIO. 606baef150380d561a4d695a6be4fc509821c23611Calin Culianu 616baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Use comedi_commands with TRIG_NOW. Your callback will be called each 626baef150380d561a4d695a6be4fc509821c23611Calin Culianu time an edge is detected on the specified DIO line(s), and the data 636baef150380d561a4d695a6be4fc509821c23611Calin Culianu values will be two sample_t's, which should be concatenated to form 646baef150380d561a4d695a6be4fc509821c23611Calin Culianu one 32-bit unsigned int. This value is the mask of channels that had 656baef150380d561a4d695a6be4fc509821c23611Calin Culianu edges detected from your channel list. Note that the bits positions 666baef150380d561a4d695a6be4fc509821c23611Calin Culianu in the mask correspond to positions in your chanlist when you 676baef150380d561a4d695a6be4fc509821c23611Calin Culianu specified the command and *not* channel id's! 686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 696baef150380d561a4d695a6be4fc509821c23611Calin Culianu * To set the polarity of the edge-detection interrupts pass a nonzero value 706baef150380d561a4d695a6be4fc509821c23611Calin Culianu for either CR_RANGE or CR_AREF for edge-up polarity, or a zero 716baef150380d561a4d695a6be4fc509821c23611Calin Culianu value for both CR_RANGE and CR_AREF if you want edge-down polarity. 726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 736baef150380d561a4d695a6be4fc509821c23611Calin CulianuConfiguration Options: 746baef150380d561a4d695a6be4fc509821c23611Calin Culianu [0] - I/O port base address 75d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson [1] - IRQ (optional -- for edge-detect interrupt support only, 76d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson leave out if you don't need this feature) 776baef150380d561a4d695a6be4fc509821c23611Calin Culianu*/ 786baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7925436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 805a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 816baef150380d561a4d695a6be4fc509821c23611Calin Culianu#include "../comedidev.h" 820b8f754a6220158f2348bc6eae2772bc64bc98a2Bill Pemberton#include "pcm_common.h" 836baef150380d561a4d695a6be4fc509821c23611Calin Culianu#include <linux/pci.h> /* for PCI devices */ 846baef150380d561a4d695a6be4fc509821c23611Calin Culianu 856baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */ 866baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CHANS_PER_PORT 8 876baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PORTS_PER_ASIC 6 886baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_PORTS_PER_ASIC 3 896baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */ 906baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT) 916baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC) 926baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_CHANS_PER_ASIC 24 936baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT) 946baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_DIO_CHANS (PORTS_PER_ASIC*1*CHANS_PER_PORT) 956baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC) 966baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define SDEV_NO ((int)(s - dev->subdevices)) 976baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CALC_N_DIO_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/) 986baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* IO Memory sizes */ 996baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define ASIC_IOSIZE (0x0B) 1006baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PCMMIO48_IOSIZE ASIC_IOSIZE 1016baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1026baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* Some offsets - these are all in the 16byte IO memory offset from 1036baef150380d561a4d695a6be4fc509821c23611Calin Culianu the base address. Note that there is a paging scheme to swap out 1046baef150380d561a4d695a6be4fc509821c23611Calin Culianu offsets 0x8-0xA using the PAGELOCK register. See the table below. 1056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1066baef150380d561a4d695a6be4fc509821c23611Calin Culianu Register(s) Pages R/W? Description 1076baef150380d561a4d695a6be4fc509821c23611Calin Culianu -------------------------------------------------------------- 1086baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_PORTx All R/W Read/Write/Configure IO 1096baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_INT_PENDING All ReadOnly Quickly see which INT_IDx has int. 1106baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_PAGELOCK All WriteOnly Select a page 1116baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_POLx Pg. 1 only WriteOnly Select edge-detection polarity 1126baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_ENABx Pg. 2 only WriteOnly Enable/Disable edge-detect. int. 1136baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_INT_IDx Pg. 3 only R/W See which ports/bits have ints. 1146baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 1156baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT0 0x0 1166baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT1 0x1 1176baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT2 0x2 1186baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT3 0x3 1196baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT4 0x4 1206baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PORT5 0x5 1216baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_PENDING 0x6 122d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson#define REG_PAGELOCK 0x7 /* 123d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * page selector register, upper 2 bits select 124d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * a page and bits 0-5 are used to 'lock down' 125d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * a particular port above to make it readonly. 126d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 1276baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL0 0x8 1286baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL1 0x9 1296baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL2 0xA 1306baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB0 0x8 1316baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB1 0x9 1326baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB2 0xA 1336baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID0 0x8 1346baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID1 0x9 1356baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID2 0xA 1366baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1376baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define NUM_PAGED_REGS 3 1386baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define NUM_PAGES 4 1396baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define FIRST_PAGED_REG 0x8 1406baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PAGE_BITOFFSET 6 1416baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_LOCK_BITOFFSET 0 1426baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PAGE_MASK (~((0x1<<REG_PAGE_BITOFFSET)-1)) 143d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson#define REG_LOCK_MASK (~(REG_PAGE_MASK)) 1446baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_POL 1 1456baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_ENAB 2 1466baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_INT_ID 3 1476baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, 1490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *, unsigned int *); 1500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, 1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *, unsigned int *); 1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ao_winsn(struct comedi_device *, struct comedi_subdevice *, 1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *, unsigned int *); 1546baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1556baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 1566baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Board descriptions for two imaginary boards. Describing the 1576baef150380d561a4d695a6be4fc509821c23611Calin Culianu * boards in this way is optional, and completely driver-dependent. 1586baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Some drivers use arrays such as this, other do not. 1596baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 160657f81ec27758ddb859ea9c74929996bea607194Bill Pembertonstruct pcmmio_board { 1616baef150380d561a4d695a6be4fc509821c23611Calin Culianu const char *name; 1626baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int dio_num_asics; 1636baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int dio_num_ports; 1646baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int total_iosize; 1656baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int ai_bits; 1666baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int ao_bits; 1676baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int n_ai_chans; 1686baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int n_ao_chans; 1699ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton const struct comedi_lrange *ai_range_table, *ao_range_table; 17056b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas int (*ai_rinsn) (struct comedi_device *dev, 17156b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_subdevice *s, 17256b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_insn *insn, 17356b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas unsigned int *data); 17456b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas int (*ao_rinsn) (struct comedi_device *dev, 17556b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_subdevice *s, 17656b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_insn *insn, 17756b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas unsigned int *data); 17856b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas int (*ao_winsn) (struct comedi_device *dev, 17956b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_subdevice *s, 18056b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas struct comedi_insn *insn, 18156b8421ceef7f2dae95b882034ebf6958bad58f6Arun Thomas unsigned int *data); 182657f81ec27758ddb859ea9c74929996bea607194Bill Pemberton}; 1836baef150380d561a4d695a6be4fc509821c23611Calin Culianu 184d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnsonstatic const struct comedi_lrange ranges_ai = { 185d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., 10.)} 1866baef150380d561a4d695a6be4fc509821c23611Calin Culianu}; 1876baef150380d561a4d695a6be4fc509821c23611Calin Culianu 188d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnsonstatic const struct comedi_lrange ranges_ao = { 189d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson 6, {RANGE(0., 5.), RANGE(0., 10.), RANGE(-5., 5.), RANGE(-10., 10.), 1900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)} 1916baef150380d561a4d695a6be4fc509821c23611Calin Culianu}; 1926baef150380d561a4d695a6be4fc509821c23611Calin Culianu 193657f81ec27758ddb859ea9c74929996bea607194Bill Pembertonstatic const struct pcmmio_board pcmmio_boards[] = { 1946baef150380d561a4d695a6be4fc509821c23611Calin Culianu { 1950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "pcmmio", 1960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_num_asics = 1, 1970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_num_ports = 6, 1980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .total_iosize = 32, 1990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_bits = 16, 2000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_bits = 16, 2010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .n_ai_chans = 16, 2020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .n_ao_chans = 8, 2030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_table = &ranges_ai, 2040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_range_table = &ranges_ao, 2050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_rinsn = ai_rinsn, 2060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_rinsn = ao_rinsn, 2070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_winsn = ao_winsn}, 2086baef150380d561a4d695a6be4fc509821c23611Calin Culianu}; 2096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2106baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 2116baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Useful for shorthand access to the particular board structure 2126baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 213657f81ec27758ddb859ea9c74929996bea607194Bill Pemberton#define thisboard ((const struct pcmmio_board *)dev->board_ptr) 2146baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2156baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* this structure is for data unique to this subdevice. */ 2164467df9406bc40fdbc9cf64cfb2e95cba8f77e1eBill Pembertonstruct pcmmio_subdev_private { 2176baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2186baef150380d561a4d695a6be4fc509821c23611Calin Culianu union { 219d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* for DIO: mapping of halfwords (bytes) 220d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson in port/chanarray to iobase */ 2216baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobases[PORTS_PER_SUBDEV]; 2226baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2236baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* for AI/AO */ 2246baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase; 2256baef150380d561a4d695a6be4fc509821c23611Calin Culianu }; 2266baef150380d561a4d695a6be4fc509821c23611Calin Culianu union { 2276baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 2286baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2296baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The below is only used for intr subdevices */ 2306baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 231d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 232d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * if non-negative, this subdev has an 233d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * interrupt asic 234d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 235d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson int asic; 236d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 237d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * if nonnegative, the first channel id for 238d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * interrupts. 239d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 240d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson int first_chan; 241d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 242d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * the number of asic channels in this subdev 243d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * that have interrutps 244d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 245d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson int num_asic_chans; 246d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 247d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * if nonnegative, the first channel id with 248d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * respect to the asic that has interrupts 249d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 250d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson int asic_chan; 251d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 252d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * subdev-relative channel mask for channels 253d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * we are interested in 254d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 255d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson int enabled_mask; 2566baef150380d561a4d695a6be4fc509821c23611Calin Culianu int active; 2576baef150380d561a4d695a6be4fc509821c23611Calin Culianu int stop_count; 2586baef150380d561a4d695a6be4fc509821c23611Calin Culianu int continuous; 2596baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 2606baef150380d561a4d695a6be4fc509821c23611Calin Culianu } intr; 2616baef150380d561a4d695a6be4fc509821c23611Calin Culianu } dio; 2626baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 263d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* the last unsigned int data written */ 264d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson unsigned int shadow_samples[8]; 2656baef150380d561a4d695a6be4fc509821c23611Calin Culianu } ao; 2666baef150380d561a4d695a6be4fc509821c23611Calin Culianu }; 2674467df9406bc40fdbc9cf64cfb2e95cba8f77e1eBill Pemberton}; 2686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 269d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson/* 270d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * this structure is for data unique to this hardware driver. If 271d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * several hardware drivers keep similar information in this structure, 272d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * feel free to suggest moving the variable to the struct comedi_device struct. 273d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 274e56ab7156f5f4918eb89a19b3061de1a7fe69354Bill Pembertonstruct pcmmio_private { 2756baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* stuff for DIO */ 2766baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 2776baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char pagelock; /* current page and lock */ 278d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* shadow of POLx registers */ 279d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson unsigned char pol[NUM_PAGED_REGS]; 280d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* shadow of ENABx registers */ 281d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson unsigned char enab[NUM_PAGED_REGS]; 2826baef150380d561a4d695a6be4fc509821c23611Calin Culianu int num; 2836baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase; 2846baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int irq; 2856baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 2866baef150380d561a4d695a6be4fc509821c23611Calin Culianu } asics[MAX_ASICS]; 2874467df9406bc40fdbc9cf64cfb2e95cba8f77e1eBill Pemberton struct pcmmio_subdev_private *sprivs; 288e56ab7156f5f4918eb89a19b3061de1a7fe69354Bill Pemberton}; 2896baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2906baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 2916baef150380d561a4d695a6be4fc509821c23611Calin Culianu * most drivers define the following macro to make it easy to 2926baef150380d561a4d695a6be4fc509821c23611Calin Culianu * access the private structure. 2936baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 294e56ab7156f5f4918eb89a19b3061de1a7fe69354Bill Pemberton#define devpriv ((struct pcmmio_private *)dev->private) 2954467df9406bc40fdbc9cf64cfb2e95cba8f77e1eBill Pemberton#define subpriv ((struct pcmmio_subdev_private *)s->private) 2966baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 297139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module 2986baef150380d561a4d695a6be4fc509821c23611Calin Culianu * which functions to call to configure/deconfigure (attach/detach) 2996baef150380d561a4d695a6be4fc509821c23611Calin Culianu * the board, and also about the kernel module that contains 3006baef150380d561a4d695a6be4fc509821c23611Calin Culianu * the device code. 3016baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 3020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_attach(struct comedi_device *dev, 3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 304da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmmio_detach(struct comedi_device *dev); 3056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 306139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver = { 30768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "pcmmio", 30868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 30968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = pcmmio_attach, 31068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = pcmmio_detach, 3116baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* It is not necessary to implement the following members if you are 3126baef150380d561a4d695a6be4fc509821c23611Calin Culianu * writing a driver for a ISA PnP or PCI card */ 3136baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Most drivers will support multiple types of boards by 3146baef150380d561a4d695a6be4fc509821c23611Calin Culianu * having an array of board structures. These were defined 3156baef150380d561a4d695a6be4fc509821c23611Calin Culianu * in pcmmio_boards[] above. Note that the element 'name' 3166baef150380d561a4d695a6be4fc509821c23611Calin Culianu * was first in the structure -- Comedi uses this fact to 3176baef150380d561a4d695a6be4fc509821c23611Calin Culianu * extract the name of the board without knowing any details 3186baef150380d561a4d695a6be4fc509821c23611Calin Culianu * about the structure except for its length. 3196baef150380d561a4d695a6be4fc509821c23611Calin Culianu * When a device is attached (by comedi_config), the name 3206baef150380d561a4d695a6be4fc509821c23611Calin Culianu * of the device is given to Comedi, and Comedi tries to 3216baef150380d561a4d695a6be4fc509821c23611Calin Culianu * match it by going through the list of board names. If 3226baef150380d561a4d695a6be4fc509821c23611Calin Culianu * there is a match, the address of the pointer is put 3236baef150380d561a4d695a6be4fc509821c23611Calin Culianu * into dev->board_ptr and driver->attach() is called. 3246baef150380d561a4d695a6be4fc509821c23611Calin Culianu * 3256baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Note that these are not necessary if you can determine 3266baef150380d561a4d695a6be4fc509821c23611Calin Culianu * the type of board in software. ISA PnP, PCI, and PCMCIA 3276baef150380d561a4d695a6be4fc509821c23611Calin Culianu * devices are such boards. 3286baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 32968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &pcmmio_boards[0].name, 33068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct pcmmio_board), 3318629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton .num_names = ARRAY_SIZE(pcmmio_boards), 3326baef150380d561a4d695a6be4fc509821c23611Calin Culianu}; 3336baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_dio_insn_bits(struct comedi_device *dev, 3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_dio_insn_config(struct comedi_device *dev, 3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 3406baef150380d561a4d695a6be4fc509821c23611Calin Culianu 34170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_pcmmio(int irq, void *d); 34234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *); 343814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s); 344814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s); 345814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_cmd *cmd); 3476baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3486baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* some helper functions to deal with specifics of this device's registers */ 349d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson/* sets up/clears ASIC chips to defaults */ 350d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnsonstatic void init_asics(struct comedi_device *dev); 351814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void switch_page(struct comedi_device *dev, int asic, int page); 3526baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef notused 353814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void lock_port(struct comedi_device *dev, int asic, int port); 354814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void unlock_port(struct comedi_device *dev, int asic, int port); 3556baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 3566baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3576baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 3586baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Attach is called by the Comedi core to configure the driver 3596baef150380d561a4d695a6be4fc509821c23611Calin Culianu * for a particular board. If you specified a board_name array 3606baef150380d561a4d695a6be4fc509821c23611Calin Culianu * in the driver structure, dev->board_ptr contains that 3616baef150380d561a4d695a6be4fc509821c23611Calin Culianu * address. 3626baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 363da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) 3646baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 36534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 3666baef150380d561a4d695a6be4fc509821c23611Calin Culianu int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic, 3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisasic_chanct = 0; 3686baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase; 3696baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int irq[MAX_ASICS]; 3706baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3716baef150380d561a4d695a6be4fc509821c23611Calin Culianu iobase = it->options[0]; 3726baef150380d561a4d695a6be4fc509821c23611Calin Culianu irq[0] = it->options[1]; 3736baef150380d561a4d695a6be4fc509821c23611Calin Culianu 374cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor, 375cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn driver.driver_name, iobase); 3766baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3776baef150380d561a4d695a6be4fc509821c23611Calin Culianu dev->iobase = iobase; 3786baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3796baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!iobase || !request_region(iobase, 3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisboard->total_iosize, 3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral driver.driver_name)) { 382cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); 3836baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EIO; 3846baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3866baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 3876baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Initialize dev->board_name. Note that we can use the "thisboard" 3886baef150380d561a4d695a6be4fc509821c23611Calin Culianu * macro now, since we just initialized it in the last line. 3896baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 3906baef150380d561a4d695a6be4fc509821c23611Calin Culianu dev->board_name = thisboard->name; 3916baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3926baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 3936baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Allocate the private structure area. alloc_private() is a 3946baef150380d561a4d695a6be4fc509821c23611Calin Culianu * convenient macro defined in comedidev.h. 3956baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 396e56ab7156f5f4918eb89a19b3061de1a7fe69354Bill Pemberton if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) { 397cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_ERR "comedi%d: cannot allocate private data structure\n", 398cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn dev->minor); 3996baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -ENOMEM; 4006baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4016baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4026baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (asic = 0; asic < MAX_ASICS; ++asic) { 4036baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].num = asic; 4046baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].iobase = 4050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + 16 + asic * ASIC_IOSIZE; 406d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 407d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * this gets actually set at the end of this function when we 408d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * request_irqs 409d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 410d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson devpriv->asics[asic].irq = 0; 4116baef150380d561a4d695a6be4fc509821c23611Calin Culianu spin_lock_init(&devpriv->asics[asic].spinlock); 4126baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4136baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4146baef150380d561a4d695a6be4fc509821c23611Calin Culianu chans_left = CHANS_PER_ASIC * thisboard->dio_num_asics; 4156baef150380d561a4d695a6be4fc509821c23611Calin Culianu n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left); 4166baef150380d561a4d695a6be4fc509821c23611Calin Culianu n_subdevs = n_dio_subdevs + 2; 4176baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->sprivs = 4180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), 4190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral GFP_KERNEL); 4206baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!devpriv->sprivs) { 421cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n", 422cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn dev->minor); 4236baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -ENOMEM; 4246baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4256baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* 4266baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Allocate the subdevice structures. alloc_subdevice() is a 4276baef150380d561a4d695a6be4fc509821c23611Calin Culianu * convenient macro defined in comedidev.h. 4286baef150380d561a4d695a6be4fc509821c23611Calin Culianu * 4296baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO) 4306baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 4316baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (alloc_subdevices(dev, n_subdevs) < 0) { 432cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n", 433cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn dev->minor); 4346baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -ENOMEM; 4356baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4366baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4376baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* First, AI */ 4386baef150380d561a4d695a6be4fc509821c23611Calin Culianu sdev_no = 0; 4396baef150380d561a4d695a6be4fc509821c23611Calin Culianu s = dev->subdevices + sdev_no; 4406baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->private = devpriv->sprivs + sdev_no; 4416baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->maxdata = (1 << thisboard->ai_bits) - 1; 4426baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->range_table = thisboard->ai_range_table; 4436baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; 4446baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->type = COMEDI_SUBD_AI; 4456baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->n_chan = thisboard->n_ai_chans; 4466baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->len_chanlist = s->n_chan; 4476baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->insn_read = thisboard->ai_rinsn; 4486baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->iobase = dev->iobase + 0; 4496baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* initialize the resource enable register by clearing it */ 4506baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, subpriv->iobase + 3); 4516baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, subpriv->iobase + 4 + 3); 4526baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4536baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Next, AO */ 4546baef150380d561a4d695a6be4fc509821c23611Calin Culianu ++sdev_no; 4556baef150380d561a4d695a6be4fc509821c23611Calin Culianu s = dev->subdevices + sdev_no; 4566baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->private = devpriv->sprivs + sdev_no; 4576baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->maxdata = (1 << thisboard->ao_bits) - 1; 4586baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->range_table = thisboard->ao_range_table; 4596baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->subdev_flags = SDF_READABLE; 4606baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->type = COMEDI_SUBD_AO; 4616baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->n_chan = thisboard->n_ao_chans; 4626baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->len_chanlist = s->n_chan; 4636baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->insn_read = thisboard->ao_rinsn; 4646baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->insn_write = thisboard->ao_winsn; 4656baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->iobase = dev->iobase + 8; 4666baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* initialize the resource enable register by clearing it */ 4676baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, subpriv->iobase + 3); 4686baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, subpriv->iobase + 4 + 3); 4696baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4706baef150380d561a4d695a6be4fc509821c23611Calin Culianu ++sdev_no; 4716baef150380d561a4d695a6be4fc509821c23611Calin Culianu port = 0; 4726baef150380d561a4d695a6be4fc509821c23611Calin Culianu asic = 0; 4736baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) { 4746baef150380d561a4d695a6be4fc509821c23611Calin Culianu int byte_no; 4756baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4766baef150380d561a4d695a6be4fc509821c23611Calin Culianu s = dev->subdevices + sdev_no; 4776baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->private = devpriv->sprivs + sdev_no; 4786baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->maxdata = 1; 4796baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->range_table = &range_digital; 4806baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 4816baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->type = COMEDI_SUBD_DIO; 4826baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->insn_bits = pcmmio_dio_insn_bits; 4836baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->insn_config = pcmmio_dio_insn_config; 484214e7b5c8281bf41238f575128e4fec5652ed797Bill Pemberton s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV); 4856baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.asic = -1; 4866baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.first_chan = -1; 4876baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.asic_chan = -1; 4886baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.num_asic_chans = -1; 4896baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 0; 4906baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->len_chanlist = 1; 4916baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4926baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save the ioport address for each 'port' of 8 channels in the 4936baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdevice */ 4946baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) { 4956baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (port >= PORTS_PER_ASIC) { 4966baef150380d561a4d695a6be4fc509821c23611Calin Culianu port = 0; 4976baef150380d561a4d695a6be4fc509821c23611Calin Culianu ++asic; 4986baef150380d561a4d695a6be4fc509821c23611Calin Culianu thisasic_chanct = 0; 4996baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5006baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->iobases[byte_no] = 5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + port; 5026baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5036baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (thisasic_chanct < 5040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral CHANS_PER_PORT * INTR_PORTS_PER_ASIC 5050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && subpriv->dio.intr.asic < 0) { 506d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 507d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * this is an interrupt subdevice, 508d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * so setup the struct 509d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 5106baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.asic = asic; 5116baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 0; 5126baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.stop_count = 0; 5136baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.first_chan = byte_no * 8; 5146baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.asic_chan = thisasic_chanct; 5156baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.num_asic_chans = 5160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s->n_chan - subpriv->dio.intr.first_chan; 5176baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->cancel = pcmmio_cancel; 5186baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->do_cmd = pcmmio_cmd; 5196baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->do_cmdtest = pcmmio_cmdtest; 5206baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->len_chanlist = 5210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->dio.intr.num_asic_chans; 5226baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5236baef150380d561a4d695a6be4fc509821c23611Calin Culianu thisasic_chanct += CHANS_PER_PORT; 5246baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5256baef150380d561a4d695a6be4fc509821c23611Calin Culianu spin_lock_init(&subpriv->dio.intr.spinlock); 5266baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5276baef150380d561a4d695a6be4fc509821c23611Calin Culianu chans_left -= s->n_chan; 5286baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5296baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!chans_left) { 530d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 531d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * reset the asic to our first asic, 532d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * to do intr subdevs 533d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 534d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson asic = 0; 5356baef150380d561a4d695a6be4fc509821c23611Calin Culianu port = 0; 5366baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5376baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5386baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5396baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5406baef150380d561a4d695a6be4fc509821c23611Calin Culianu init_asics(dev); /* clear out all the registers, basically */ 5416baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5426baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { 5436baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (irq[asic] 5440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && request_irq(irq[asic], interrupt_pcmmio, 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral IRQF_SHARED, thisboard->name, dev)) { 5466baef150380d561a4d695a6be4fc509821c23611Calin Culianu int i; 5476baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* unroll the allocated irqs.. */ 5486baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (i = asic - 1; i >= 0; --i) { 5495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(irq[i], dev); 5506baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[i].irq = irq[i] = 0; 5516baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5526baef150380d561a4d695a6be4fc509821c23611Calin Culianu irq[asic] = 0; 5536baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5546baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].irq = irq[asic]; 5556baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5566baef150380d561a4d695a6be4fc509821c23611Calin Culianu 557d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson dev->irq = irq[0]; /* 558d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * grr.. wish comedi dev struct supported 559d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * multiple irqs.. 560d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 5616baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5626baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (irq[0]) { 563cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]); 5644b2ba24399cfcd7c80a20cd3bbedc5df0ebd4345Dan Carpenter if (thisboard->dio_num_asics == 2 && irq[1]) 565cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n", 566cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn dev->minor, irq[1]); 5676baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 568cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor); 5696baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5706baef150380d561a4d695a6be4fc509821c23611Calin Culianu 571cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk(KERN_INFO "comedi%d: attached\n", dev->minor); 5726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5736baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 5746baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 5756baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5766baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 5776baef150380d561a4d695a6be4fc509821c23611Calin Culianu * _detach is called to deconfigure a device. It should deallocate 5786baef150380d561a4d695a6be4fc509821c23611Calin Culianu * resources. 5796baef150380d561a4d695a6be4fc509821c23611Calin Culianu * This function is also called when _attach() fails, so it should be 5806baef150380d561a4d695a6be4fc509821c23611Calin Culianu * careful not to release resources that were not necessarily 5816baef150380d561a4d695a6be4fc509821c23611Calin Culianu * allocated by _attach(). dev->private and dev->subdevices are 5826baef150380d561a4d695a6be4fc509821c23611Calin Culianu * deallocated automatically by the core. 5836baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 584da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmmio_detach(struct comedi_device *dev) 5856baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 5866baef150380d561a4d695a6be4fc509821c23611Calin Culianu int i; 5876baef150380d561a4d695a6be4fc509821c23611Calin Culianu 588bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn printk(KERN_INFO "comedi%d: %s: remove\n", dev->minor, driver.driver_name); 5896baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (dev->iobase) 5906baef150380d561a4d695a6be4fc509821c23611Calin Culianu release_region(dev->iobase, thisboard->total_iosize); 5916baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5926baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (i = 0; i < MAX_ASICS; ++i) { 5936baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (devpriv && devpriv->asics[i].irq) 5945f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(devpriv->asics[i].irq, dev); 5956baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5976baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (devpriv && devpriv->sprivs) 5986baef150380d561a4d695a6be4fc509821c23611Calin Culianu kfree(devpriv->sprivs); 5996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6006baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 6016baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6026baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6036baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* DIO devices are slightly special. Although it is possible to 6046baef150380d561a4d695a6be4fc509821c23611Calin Culianu * implement the insn_read/insn_write interface, it is much more 6056baef150380d561a4d695a6be4fc509821c23611Calin Culianu * useful to applications if you implement the insn_bits interface. 6066baef150380d561a4d695a6be4fc509821c23611Calin Culianu * This allows packed reading/writing of the DIO channels. The 6076baef150380d561a4d695a6be4fc509821c23611Calin Culianu * comedi core can convert between insn_bits and insn_read/write */ 6080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_dio_insn_bits(struct comedi_device *dev, 6090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 6100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 6116baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6126baef150380d561a4d695a6be4fc509821c23611Calin Culianu int byte_no; 6136baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (insn->n != 2) 6146baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 6156baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6166baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 6176baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 0 means this channel was high 6186baef150380d561a4d695a6be4fc509821c23611Calin Culianu writine a 0 sets the channel high 6196baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 1 means this channel was low 6206baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 means set this channel low 6216baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6226baef150380d561a4d695a6be4fc509821c23611Calin Culianu Therefore everything is always inverted. */ 6236baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6246baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The insn data is a mask in data[0] and the new data 6256baef150380d561a4d695a6be4fc509821c23611Calin Culianu * in data[1], each channel cooresponding to a bit. */ 6266baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6276baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 6286baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 629bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn printk(KERN_DEBUG "write mask: %08x data: %08x\n", data[0], data[1]); 6306baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 6316baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6326baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state = 0; 6336baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6346baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { 6356baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* address of 8-bit port */ 6366baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr = subpriv->iobases[byte_no], 6370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* bit offset of port in 32-bit doubleword */ 6380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral offset = byte_no * 8; 6396baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* this 8-bit port's data */ 6406baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte = 0, 6410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The write mask for this port (if any) */ 6420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral write_mask_byte = (data[0] >> offset) & 0xff, 6430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The data byte for this port */ 6440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data_byte = (data[1] >> offset) & 0xff; 6456baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6466baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); /* read all 8-bits for this port */ 6476baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6486baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 6496baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 6500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 651bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn (KERN_DEBUG "byte %d wmb %02x db %02x offset %02d io %04x," 652bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn " data_in %02x ", byte_no, (unsigned)write_mask_byte, 653bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn (unsigned)data_byte, offset, ioaddr, (unsigned)byte); 6546baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 6556baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6566baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (write_mask_byte) { 657d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* 658d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * this byte has some write_bits 659d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson * -- so set the output lines 660d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson */ 661d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* clear bits for write mask */ 662d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson byte &= ~write_mask_byte; 663d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson /* set to inverted data_byte */ 664d2d08955e77a84a0a022dfa9e6f4b4b6c6773281Daniel Patrick Johnson byte |= ~data_byte & write_mask_byte; 6656baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Write out the new digital output state */ 6666baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 6676baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6686baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 6696baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 670cf5682788f2cc35643f0bc1898646e2cff4af7f3Johannes Thumshirn printk("data_out_byte %02x\n", (unsigned)byte); 6716baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 6726baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save the digital input lines for this byte.. */ 6736baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state |= ((unsigned int)byte) << offset; 6746baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6756baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6766baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now return the DIO lines to data[1] - note they came inverted! */ 6776baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = ~s->state; 6786baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6796baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 6806baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 681bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn printk(KERN_DEBUG "s->state %08x data_out %08x\n", s->state, data[1]); 6826baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 6836baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6846baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 2; 6856baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6866baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6876baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* The input or output configuration of each digital line is 6886baef150380d561a4d695a6be4fc509821c23611Calin Culianu * configured by a special insn_config instruction. chanspec 6896baef150380d561a4d695a6be4fc509821c23611Calin Culianu * contains the channel to be changed, and data[0] contains the 6906baef150380d561a4d695a6be4fc509821c23611Calin Culianu * value COMEDI_INPUT or COMEDI_OUTPUT. */ 6910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_dio_insn_config(struct comedi_device *dev, 6920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 6930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 6946baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6956baef150380d561a4d695a6be4fc509821c23611Calin Culianu int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = 6960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chan % 8; 6976baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr; 6986baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte; 6996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7006baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Compute ioaddr for this channel */ 7016baef150380d561a4d695a6be4fc509821c23611Calin Culianu ioaddr = subpriv->iobases[byte_no]; 7026baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7036baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 7046baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 0 an IO channel's bit sets the channel to INPUT 7056baef150380d561a4d695a6be4fc509821c23611Calin Culianu and pulls the line high as well 7066baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7076baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 to an IO channel's bit pulls the line low 7086baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7096baef150380d561a4d695a6be4fc509821c23611Calin Culianu All channels are implicitly always in OUTPUT mode -- but when 7106baef150380d561a4d695a6be4fc509821c23611Calin Culianu they are high they can be considered to be in INPUT mode.. 7116baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7126baef150380d561a4d695a6be4fc509821c23611Calin Culianu Thus, we only force channels low if the config request was INPUT, 7136baef150380d561a4d695a6be4fc509821c23611Calin Culianu otherwise we do nothing to the hardware. */ 7146baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7156baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (data[0]) { 7166baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_OUTPUT: 7176baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits -- don't actually do anything since 7186baef150380d561a4d695a6be4fc509821c23611Calin Culianu all input channels are also output channels... */ 7196baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits |= 1 << chan; 7206baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7216baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_INPUT: 7226baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* write a 0 to the actual register representing the channel 7236baef150380d561a4d695a6be4fc509821c23611Calin Culianu to set it to 'input'. 0 means "float high". */ 7246baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); 7256baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte &= ~(1 << bit_no); 7266baef150380d561a4d695a6be4fc509821c23611Calin Culianu /**< set input channel to '0' */ 7276baef150380d561a4d695a6be4fc509821c23611Calin Culianu 728013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 729013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * write out byte -- this is the only time we actually affect 730013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * the hardware as all channels are implicitly output 731013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * -- but input channels are set to float-high 732013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 7336baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 7346baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7356baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits */ 7366baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits &= ~(1 << chan); 7376baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7386baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7396baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_QUERY: 74025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* retrieve from shadow register */ 7416baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = 7420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 7436baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 7446baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7456baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7466baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 7476baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 7486baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7496baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 7506baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7516baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 7526baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 7536baef150380d561a4d695a6be4fc509821c23611Calin Culianu 754da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void init_asics(struct comedi_device *dev) 7556baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ /* sets up an 7566baef150380d561a4d695a6be4fc509821c23611Calin Culianu ASIC chip to defaults */ 7576baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic; 7586baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7596baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (asic = 0; asic < thisboard->dio_num_asics; ++asic) { 7606baef150380d561a4d695a6be4fc509821c23611Calin Culianu int port, page; 7616baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long baseaddr = devpriv->asics[asic].iobase; 7626baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7636baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 0); /* switch back to page 0 */ 7646baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7656baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* first, clear all the DIO port bits */ 7666baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = 0; port < PORTS_PER_ASIC; ++port) 7676baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, baseaddr + REG_PORT0 + port); 7686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7696baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Next, clear all the paged registers for each page */ 7706baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (page = 1; page < NUM_PAGES; ++page) { 7716baef150380d561a4d695a6be4fc509821c23611Calin Culianu int reg; 7726baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now clear all the paged registers */ 7736baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, page); 7746baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (reg = FIRST_PAGED_REG; 7750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) 7766baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, baseaddr + reg); 7776baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 7786baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7796baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG set rising edge interrupts on port0 of both asics */ 7806baef150380d561a4d695a6be4fc509821c23611Calin Culianu /*switch_page(dev, asic, PAGE_POL); 7816baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0xff, baseaddr + REG_POL0); 7826baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_ENAB); 7836baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0xff, baseaddr + REG_ENAB0); */ 7846baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* END DEBUG */ 7856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 786013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* switch back to default page 0 */ 787013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson switch_page(dev, asic, 0); 7886baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 7896baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 7906baef150380d561a4d695a6be4fc509821c23611Calin Culianu 791da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void switch_page(struct comedi_device *dev, int asic, int page) 7926baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 7936baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (asic < 0 || asic >= thisboard->dio_num_asics) 7946baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* paranoia */ 7956baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (page < 0 || page >= NUM_PAGES) 7966baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* more paranoia */ 7976baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7986baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK; 7996baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET; 8006baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8016baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now write out the shadow register */ 8026baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(devpriv->asics[asic].pagelock, 8030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_PAGELOCK); 8046baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 8056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8066baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef notused 807da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void lock_port(struct comedi_device *dev, int asic, int port) 8086baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 8096baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (asic < 0 || asic >= thisboard->dio_num_asics) 8106baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* paranoia */ 8116baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (port < 0 || port >= PORTS_PER_ASIC) 8126baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* more paranoia */ 8136baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8146baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock |= 0x1 << port; 8156baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now write out the shadow register */ 8166baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(devpriv->asics[asic].pagelock, 8170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_PAGELOCK); 8186baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; 8196baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 8206baef150380d561a4d695a6be4fc509821c23611Calin Culianu 821da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void unlock_port(struct comedi_device *dev, int asic, int port) 8226baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 8236baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (asic < 0 || asic >= thisboard->dio_num_asics) 8246baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* paranoia */ 8256baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (port < 0 || port >= PORTS_PER_ASIC) 8266baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* more paranoia */ 8276baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK; 8286baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now write out the shadow register */ 8296baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(devpriv->asics[asic].pagelock, 8300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_PAGELOCK); 8316baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 8326baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif /* notused */ 8336baef150380d561a4d695a6be4fc509821c23611Calin Culianu 83470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_pcmmio(int irq, void *d) 8356baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 8366baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic, got1 = 0; 8370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_device *dev = (struct comedi_device *)d; 8386baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8396baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (asic = 0; asic < MAX_ASICS; ++asic) { 8406baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (irq == devpriv->asics[asic].irq) { 8416baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 8426baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned triggered = 0; 8436baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase = devpriv->asics[asic].iobase; 8446baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* it is an interrupt for ASIC #asic */ 8456baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char int_pend; 8466baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_lock_irqsave(&devpriv->asics[asic].spinlock, 8480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 8496baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8506baef150380d561a4d695a6be4fc509821c23611Calin Culianu int_pend = inb(iobase + REG_INT_PENDING) & 0x07; 8516baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8526baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (int_pend) { 8536baef150380d561a4d695a6be4fc509821c23611Calin Culianu int port; 8546baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = 0; port < INTR_PORTS_PER_ASIC; 8550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ++port) { 8566baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (int_pend & (0x1 << port)) { 8576baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char 8580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral io_lines_with_edges = 0; 8596baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 8600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral PAGE_INT_ID); 8616baef150380d561a4d695a6be4fc509821c23611Calin Culianu io_lines_with_edges = 8620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inb(iobase + 8636baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_INT_ID0 + port); 8646baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8656baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (io_lines_with_edges) 866013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 867013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * clear pending 868013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * interrupt 869013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 8706baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, iobase + 8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral REG_INT_ID0 + 8720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral port); 8736baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8746baef150380d561a4d695a6be4fc509821c23611Calin Culianu triggered |= 8750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral io_lines_with_edges << 8760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral port * 8; 8776baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 8786baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 8796baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8806baef150380d561a4d695a6be4fc509821c23611Calin Culianu ++got1; 8816baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 8826baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, 8840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 8856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 8866baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (triggered) { 88734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 888013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 889013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * TODO here: dispatch io lines to subdevs 890013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * with commands.. 891013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 8920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 893bcd9a1e91fbc293bbbbddd98df687ad2e8027c89Johannes Thumshirn (KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n", 8940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral irq, asic, triggered); 8956baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (s = dev->subdevices + 2; 8960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s < dev->subdevices + dev->n_subdevices; 8970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ++s) { 898013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 899013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * this is an interrupt subdev, 900013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * and it matches this asic! 901013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 902013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson if (subpriv->dio.intr.asic == asic) { 9036baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 9046baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned oldevents; 9056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_lock_irqsave(&subpriv->dio. 9070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral intr.spinlock, 9080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 9096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9106baef150380d561a4d695a6be4fc509821c23611Calin Culianu oldevents = s->async->events; 9116baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9126baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->dio.intr.active) { 9136baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned mytrig = 9140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((triggered >> 9150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->dio.intr.asic_chan) 9160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral & 9170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((0x1 << subpriv-> 9180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dio.intr. 9190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral num_asic_chans) - 9200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1)) << subpriv-> 9210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dio.intr.first_chan; 9220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (mytrig & 9230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->dio. 9240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral intr.enabled_mask) { 9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int val 9260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = 0; 9276baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int n, 9280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ch, len; 9296baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral len = 9310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s-> 9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral async->cmd.chanlist_len; 9336baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; 9340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral n < len; 9350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral n++) { 9366baef150380d561a4d695a6be4fc509821c23611Calin Culianu ch = CR_CHAN(s->async->cmd.chanlist[n]); 937013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson if (mytrig & (1U << ch)) 9386baef150380d561a4d695a6be4fc509821c23611Calin Culianu val |= (1U << n); 9396baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9406baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Write the scan to the buffer. */ 9410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (comedi_buf_put(s->async, ((short *)&val)[0]) 9420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && 9430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_buf_put 9440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->async, 9450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((short *) 946013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson &val)[1])) { 9476baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); 9486baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 9496baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Overflow! Stop acquisition!! */ 9506baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 9516baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmmio_stop_intr 9520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (dev, 9530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s); 9546baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9556baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9566baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Check for end of acquisition. */ 9570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (!subpriv->dio.intr.continuous) { 9586baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* stop_src == TRIG_COUNT */ 9596baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->dio.intr.stop_count > 0) { 9600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->dio.intr.stop_count--; 9616baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->dio.intr.stop_count == 0) { 9626baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= COMEDI_CB_EOA; 9636baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 9646baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmmio_stop_intr 9650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (dev, 9660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s); 9676baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9686baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9696baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9706baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9716baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_unlock_irqrestore 9740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (&subpriv->dio.intr. 9750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spinlock, flags); 9766baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9776baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (oldevents != 9780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s->async->events) { 9796baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 9806baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9816baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9826baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9836baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9846baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9856baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9866baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9876baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9886baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 9896baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!got1) 9906baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_NONE; /* interrupt from other source */ 9916baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_HANDLED; 9926baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 9936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pcmmio_stop_intr(struct comedi_device *dev, 9950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 9966baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 9976baef150380d561a4d695a6be4fc509821c23611Calin Culianu int nports, firstport, asic, port; 9986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 999c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton asic = subpriv->dio.intr.asic; 1000c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (asic < 0) 10016baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* not an interrupt subdev */ 10026baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10036baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.enabled_mask = 0; 10046baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 0; 10056baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->inttrig = 0; 10066baef150380d561a4d695a6be4fc509821c23611Calin Culianu nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT; 10076baef150380d561a4d695a6be4fc509821c23611Calin Culianu firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT; 10086baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_ENAB); 10096baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = firstport; port < firstport + nports; ++port) { 10106baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* disable all intrs for this subdev.. */ 10116baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port); 10126baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10136baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 10146baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmmio_start_intr(struct comedi_device *dev, 10160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 10176baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 10186baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) { 10196baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* An empty acquisition! */ 10206baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= COMEDI_CB_EOA; 10216baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 0; 10226baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 10236baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 10246baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned bits = 0, pol_bits = 0, n; 10256baef150380d561a4d695a6be4fc509821c23611Calin Culianu int nports, firstport, asic, port; 1026ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 10276baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1028c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton asic = subpriv->dio.intr.asic; 10290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (asic < 0) 10306baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; /* not an interrupt 10316baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdev */ 10326baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.enabled_mask = 0; 10336baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 1; 10346baef150380d561a4d695a6be4fc509821c23611Calin Culianu nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT; 10356baef150380d561a4d695a6be4fc509821c23611Calin Culianu firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT; 10366baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (cmd->chanlist) { 10376baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < cmd->chanlist_len; n++) { 10386baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits |= (1U << CR_CHAN(cmd->chanlist[n])); 10396baef150380d561a4d695a6be4fc509821c23611Calin Culianu pol_bits |= (CR_AREF(cmd->chanlist[n]) 10400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral || CR_RANGE(cmd-> 10410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chanlist[n]) ? 1U : 0U) 10420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral << CR_CHAN(cmd->chanlist[n]); 10436baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10446baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10456baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits &= ((0x1 << subpriv->dio.intr.num_asic_chans) - 10460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1) << subpriv->dio.intr.first_chan; 10476baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.enabled_mask = bits; 10486baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1049013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson { 1050013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 1051013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * the below code configures the board 1052013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * to use a specific IRQ from 0-15. 1053013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 10546baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char b; 1055013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 1056013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * set resource enable register 1057013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * to enable IRQ operation 1058013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 10596baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(1 << 4, dev->iobase + 3); 10606baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set bits 0-3 of b to the irq number from 0-15 */ 10616baef150380d561a4d695a6be4fc509821c23611Calin Culianu b = dev->irq & ((1 << 4) - 1); 10626baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(b, dev->iobase + 2); 10636baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* done, we told the board what irq to use */ 10646baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10656baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10666baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_ENAB); 10676baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = firstport; port < firstport + nports; ++port) { 10686baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned enab = 10690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bits >> (subpriv->dio.intr.first_chan + (port - 10700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral firstport) 10710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 8) & 0xff, pol = 10720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral pol_bits >> (subpriv->dio.intr.first_chan + 10730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (port - firstport) * 8) & 0xff; 10746baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set enab intrs for this subdev.. */ 10756baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(enab, 10760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_ENAB0 + port); 10776baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_POL); 10786baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(pol, 10790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_ENAB0 + port); 10806baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10816baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 10826baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 10836baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 10846baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1085da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 10866baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 10876baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 10886baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10895f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); 10906baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->dio.intr.active) 10916baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmmio_stop_intr(dev, s); 10925f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); 10936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10946baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 10956baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 10966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 10976baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 10986baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. 10996baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 11006baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int 1101da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, 11020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int trignum) 11036baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 11046baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 11056baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 11066baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11076baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (trignum != 0) 11086baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 11096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11105f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); 11116baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->inttrig = 0; 1112013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson if (subpriv->dio.intr.active) 11136baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmmio_start_intr(dev, s); 11145f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); 11156baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1116013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson if (event) 11176baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 11186baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11196baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 11206baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 11216baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11226baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 11236baef150380d561a4d695a6be4fc509821c23611Calin Culianu * 'do_cmd' function for an 'INTERRUPT' subdevice. 11246baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 1125da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 11266baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 1127ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 11286baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 11296baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 11306baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11315f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); 11326baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.active = 1; 11336baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11346baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up end of acquisition. */ 11356baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->stop_src) { 11366baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_COUNT: 11376baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.continuous = 0; 11386baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.stop_count = cmd->stop_arg; 11396baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 11406baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 11416baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NONE */ 11426baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.continuous = 1; 11436baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->dio.intr.stop_count = 0; 11446baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 11456baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 11466baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11476baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up start of acquisition. */ 11486baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->start_src) { 11496baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_INT: 11506baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->inttrig = pcmmio_inttrig_start_intr; 11516baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 11526baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 11536baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NOW */ 11546baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmmio_start_intr(dev, s); 11556baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 11566baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 11575f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); 11586baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1159013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson if (event) 11606baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 11616baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11626baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 11636baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 11646baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11656baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int 11660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralpcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 11670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_cmd *cmd) 11686baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 11690b8f754a6220158f2348bc6eae2772bc64bc98a2Bill Pemberton return comedi_pcm_cmdtest(dev, s, cmd); 11706baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 11716baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11726baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int adc_wait_ready(unsigned long iobase) 11736baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 11746baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long retry = 100000; 11756baef150380d561a4d695a6be4fc509821c23611Calin Culianu while (retry--) 11766baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (inb(iobase + 3) & 0x80) 11776baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 11786baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 11796baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 11806baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11816baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* All this is for AI and AO */ 1182da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 11830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 11846baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 11856baef150380d561a4d695a6be4fc509821c23611Calin Culianu int n; 11866baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase = subpriv->iobase; 11876baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11886baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* 11896baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1. write the CMD byte (to BASE+2) 11906baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2. read junk lo byte (BASE+0) 11916baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3. read junk hi byte (BASE+1) 11926baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4. (mux settled so) write CMD byte again (BASE+2) 11936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5. read valid lo byte(BASE+0) 11946baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6. read valid hi byte(BASE+1) 11956baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11966baef150380d561a4d695a6be4fc509821c23611Calin Culianu Additionally note that the BASE += 4 if the channel >= 8 11976baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 11986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 11996baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* convert n samples */ 12006baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < insn->n; n++) { 12016baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned chan = CR_CHAN(insn->chanspec), range = 12020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec); 12036baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char command_byte = 0; 12046baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned iooffset = 0; 1205790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short sample, adc_adjust = 0; 12066baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12076baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (chan > 7) 1208013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson chan -= 8, iooffset = 4; /* 1209013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * use the second dword 1210013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * for channels > 7 1211013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 12126baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12136baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (aref != AREF_DIFF) { 12146baef150380d561a4d695a6be4fc509821c23611Calin Culianu aref = AREF_GROUND; 1215013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson command_byte |= 1 << 7; /* 1216013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * set bit 7 to indicate 1217013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * single-ended 1218013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 12196baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 12206baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (range < 2) 1221013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson adc_adjust = 0x8000; /* 1222013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * bipolar ranges 1223013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * (-5,5 .. -10,10 need to be 1224013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * adjusted -- that is.. they 1225013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * need to wrap around by 1226013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * adding 0x8000 1227013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 12286baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12296baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (chan % 2) { 1230013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson command_byte |= 1 << 6; /* 1231013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * odd-numbered channels 1232013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * have bit 6 set 1233013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 12346baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 12356baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12366baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* select the channel, bits 4-5 == chan/2 */ 12376baef150380d561a4d695a6be4fc509821c23611Calin Culianu command_byte |= ((chan / 2) & 0x3) << 4; 12386baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12396baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set the range, bits 2-3 */ 12406baef150380d561a4d695a6be4fc509821c23611Calin Culianu command_byte |= (range & 0x3) << 2; 12416baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12426baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* need to do this twice to make sure mux settled */ 1243013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* chan/range/aref select */ 1244013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson outb(command_byte, iobase + iooffset + 2); 12456baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1246013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* wait for the adc to say it finised the conversion */ 1247013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson adc_wait_ready(iobase + iooffset); 12486baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1249013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* select the chan/range/aref AGAIN */ 1250013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson outb(command_byte, iobase + iooffset + 2); 12516baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12526baef150380d561a4d695a6be4fc509821c23611Calin Culianu adc_wait_ready(iobase + iooffset); 12536baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1254013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* read data lo byte */ 1255013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson sample = inb(iobase + iooffset + 0); 1256013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson 1257013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* read data hi byte */ 1258013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson sample |= inb(iobase + iooffset + 1) << 8; 12596baef150380d561a4d695a6be4fc509821c23611Calin Culianu sample += adc_adjust; /* adjustment .. munge data */ 12606baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[n] = sample; 12616baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 12626baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* return the number of samples read/written */ 12636baef150380d561a4d695a6be4fc509821c23611Calin Culianu return n; 12646baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 12656baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1266da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 12670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 12686baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 12696baef150380d561a4d695a6be4fc509821c23611Calin Culianu int n; 12706baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < insn->n; n++) { 12716baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned chan = CR_CHAN(insn->chanspec); 12726baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (chan < s->n_chan) 12736baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[n] = subpriv->ao.shadow_samples[chan]; 12746baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 12756baef150380d561a4d695a6be4fc509821c23611Calin Culianu return n; 12766baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 12776baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12786baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int wait_dac_ready(unsigned long iobase) 12796baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 12806baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long retry = 100000L; 12816baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12826baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* This may seem like an absurd way to handle waiting and violates the 12836baef150380d561a4d695a6be4fc509821c23611Calin Culianu "no busy waiting" policy. The fact is that the hardware is 12846baef150380d561a4d695a6be4fc509821c23611Calin Culianu normally so fast that we usually only need one time through the loop 12856baef150380d561a4d695a6be4fc509821c23611Calin Culianu anyway. The longer timeout is for rare occasions and for detecting 128625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi non-existent hardware. */ 12876baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12886baef150380d561a4d695a6be4fc509821c23611Calin Culianu while (retry--) { 12896baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (inb(iobase + 3) & 0x80) 12906baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 12916baef150380d561a4d695a6be4fc509821c23611Calin Culianu 12926baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 12936baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 12946baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 12956baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1296da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 12970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 12986baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 12996baef150380d561a4d695a6be4fc509821c23611Calin Culianu int n; 13006baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned iobase = subpriv->iobase, iooffset = 0; 13016baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13026baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < insn->n; n++) { 13036baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned chan = CR_CHAN(insn->chanspec), range = 13040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral CR_RANGE(insn->chanspec); 13056baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (chan < s->n_chan) { 13066baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char command_byte = 0, range_byte = 13070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral range & ((1 << 4) - 1); 13086baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (chan >= 4) 13096baef150380d561a4d695a6be4fc509821c23611Calin Culianu chan -= 4, iooffset += 4; 13106baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set the range.. */ 13116baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(range_byte, iobase + iooffset + 0); 13126baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, iobase + iooffset + 1); 13136baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13146baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* tell it to begin */ 13156baef150380d561a4d695a6be4fc509821c23611Calin Culianu command_byte = (chan << 1) | 0x60; 13166baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(command_byte, iobase + iooffset + 2); 13176baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13186baef150380d561a4d695a6be4fc509821c23611Calin Culianu wait_dac_ready(iobase + iooffset); 13196baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1320013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* low order byte */ 1321013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson outb(data[n] & 0xff, iobase + iooffset + 0); 1322013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson 1323013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* high order byte */ 1324013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); 1325013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson 1326013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* 1327013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * set bit 4 of command byte to indicate 1328013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson * data is loaded and trigger conversion 1329013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson */ 1330013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson command_byte = 0x70 | (chan << 1); 13316baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* trigger converion */ 13326baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(command_byte, iobase + iooffset + 2); 13336baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13346baef150380d561a4d695a6be4fc509821c23611Calin Culianu wait_dac_ready(iobase + iooffset); 13356baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1336013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson /* save to shadow register for ao_rinsn */ 1337013f230c4f2622cbbc736c50223b49bced024655Daniel Patrick Johnson subpriv->ao.shadow_samples[chan] = data[n]; 13386baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 13396baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 13406baef150380d561a4d695a6be4fc509821c23611Calin Culianu return n; 13416baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 13426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13436baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 13446baef150380d561a4d695a6be4fc509821c23611Calin Culianu * A convenient macro that defines init_module() and cleanup_module(), 13456baef150380d561a4d695a6be4fc509821c23611Calin Culianu * as necessary. 13466baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 13477114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_init_module(void) 13487114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 13497114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver); 13507114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 13517114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 13527114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_cleanup_module(void) 13537114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 13547114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver); 13557114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 13567114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 13577114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_init_module); 13587114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_cleanup_module); 135990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 136090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 136190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 136290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 1363