pcmuio.c revision f95d45d114e1fd024bdee67beb80fce9b9c96126
16baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 26baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi/drivers/pcmuio.c 36baef150380d561a4d695a6be4fc509821c23611Calin Culianu Driver for Winsystems PC-104 based 48-channel and 96-channel DIO boards. 46baef150380d561a4d695a6be4fc509821c23611Calin Culianu 56baef150380d561a4d695a6be4fc509821c23611Calin Culianu COMEDI - Linux Control and Measurement Device Interface 66baef150380d561a4d695a6be4fc509821c23611Calin Culianu Copyright (C) 2006 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: pcmuio 246baef150380d561a4d695a6be4fc509821c23611Calin CulianuDescription: A driver for the PCM-UIO48A and PCM-UIO96A boards from Winsystems. 256baef150380d561a4d695a6be4fc509821c23611Calin CulianuDevices: [Winsystems] PCM-UIO48A (pcmuio48), PCM-UIO96A (pcmuio96) 266baef150380d561a4d695a6be4fc509821c23611Calin CulianuAuthor: Calin Culianu <calin@ajvar.org> 276baef150380d561a4d695a6be4fc509821c23611Calin CulianuUpdated: Fri, 13 Jan 2006 12:01:01 -0500 286baef150380d561a4d695a6be4fc509821c23611Calin CulianuStatus: works 296baef150380d561a4d695a6be4fc509821c23611Calin Culianu 306baef150380d561a4d695a6be4fc509821c23611Calin CulianuA driver for the relatively straightforward-to-program PCM-UIO48A and 316baef150380d561a4d695a6be4fc509821c23611Calin CulianuPCM-UIO96A boards from Winsystems. These boards use either one or two 326baef150380d561a4d695a6be4fc509821c23611Calin Culianu(in the 96-DIO version) WS16C48 ASIC HighDensity I/O Chips (HDIO). 336baef150380d561a4d695a6be4fc509821c23611Calin CulianuThis chip is interesting in that each I/O line is individually 346baef150380d561a4d695a6be4fc509821c23611Calin Culianuprogrammable for INPUT or OUTPUT (thus comedi_dio_config can be done 356baef150380d561a4d695a6be4fc509821c23611Calin Culianuon a per-channel basis). Also, each chip supports edge-triggered 366baef150380d561a4d695a6be4fc509821c23611Calin Culianuinterrupts for the first 24 I/O lines. Of course, since the 376baef150380d561a4d695a6be4fc509821c23611Calin Culianu96-channel version of the board has two ASICs, it can detect polarity 386baef150380d561a4d695a6be4fc509821c23611Calin Culianuchanges on up to 48 I/O lines. Since this is essentially an (non-PnP) 396baef150380d561a4d695a6be4fc509821c23611Calin CulianuISA board, I/O Address and IRQ selection are done through jumpers on 406baef150380d561a4d695a6be4fc509821c23611Calin Culianuthe board. You need to pass that information to this driver as the 416baef150380d561a4d695a6be4fc509821c23611Calin Culianufirst and second comedi_config option, respectively. Note that the 426baef150380d561a4d695a6be4fc509821c23611Calin Culianu48-channel version uses 16 bytes of IO memory and the 96-channel 436baef150380d561a4d695a6be4fc509821c23611Calin Culianuversion uses 32-bytes (in case you are worried about conflicts). The 446baef150380d561a4d695a6be4fc509821c23611Calin Culianu48-channel board is split into two 24-channel comedi subdevices. 456baef150380d561a4d695a6be4fc509821c23611Calin CulianuThe 96-channel board is split into 4 24-channel DIO subdevices. 466baef150380d561a4d695a6be4fc509821c23611Calin Culianu 476baef150380d561a4d695a6be4fc509821c23611Calin CulianuNote that IRQ support has been added, but it is untested. 486baef150380d561a4d695a6be4fc509821c23611Calin Culianu 496baef150380d561a4d695a6be4fc509821c23611Calin CulianuTo use edge-detection IRQ support, pass the IRQs of both ASICS 506baef150380d561a4d695a6be4fc509821c23611Calin Culianu(for the 96 channel version) or just 1 ASIC (for 48-channel version). 516baef150380d561a4d695a6be4fc509821c23611Calin CulianuThen, use use comedi_commands with TRIG_NOW. 526baef150380d561a4d695a6be4fc509821c23611Calin CulianuYour callback will be called each time an edge is triggered, and the data 536baef150380d561a4d695a6be4fc509821c23611Calin Culianuvalues will be two sample_t's, which should be concatenated to form one 546baef150380d561a4d695a6be4fc509821c23611Calin Culianu32-bit unsigned int. This value is the mask of channels that had 556baef150380d561a4d695a6be4fc509821c23611Calin Culianuedges detected from your channel list. Note that the bits positions 566baef150380d561a4d695a6be4fc509821c23611Calin Culianuin the mask correspond to positions in your chanlist when you specified 576baef150380d561a4d695a6be4fc509821c23611Calin Culianuthe command and *not* channel id's! 586baef150380d561a4d695a6be4fc509821c23611Calin Culianu 596baef150380d561a4d695a6be4fc509821c23611Calin CulianuTo set the polarity of the edge-detection interrupts pass a nonzero value for 606baef150380d561a4d695a6be4fc509821c23611Calin Culianueither CR_RANGE or CR_AREF for edge-up polarity, or a zero value for both 616baef150380d561a4d695a6be4fc509821c23611Calin CulianuCR_RANGE and CR_AREF if you want edge-down polarity. 626baef150380d561a4d695a6be4fc509821c23611Calin Culianu 636baef150380d561a4d695a6be4fc509821c23611Calin CulianuIn the 48-channel version: 646baef150380d561a4d695a6be4fc509821c23611Calin Culianu 656baef150380d561a4d695a6be4fc509821c23611Calin CulianuOn subdev 0, the first 24 channels channels are edge-detect channels. 666baef150380d561a4d695a6be4fc509821c23611Calin Culianu 676baef150380d561a4d695a6be4fc509821c23611Calin CulianuIn the 96-channel board you have the collowing channels that can do edge detection: 686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 696baef150380d561a4d695a6be4fc509821c23611Calin Culianusubdev 0, channels 0-24 (first 24 channels of 1st ASIC) 706baef150380d561a4d695a6be4fc509821c23611Calin Culianusubdev 2, channels 0-24 (first 24 channels of 2nd ASIC) 716baef150380d561a4d695a6be4fc509821c23611Calin Culianu 726baef150380d561a4d695a6be4fc509821c23611Calin CulianuConfiguration Options: 736baef150380d561a4d695a6be4fc509821c23611Calin Culianu [0] - I/O port base address 746baef150380d561a4d695a6be4fc509821c23611Calin Culianu [1] - IRQ (for first ASIC, or first 24 channels) 756baef150380d561a4d695a6be4fc509821c23611Calin Culianu [2] - IRQ for second ASIC (pcmuio96 only - IRQ for chans 48-72 .. can be the same as first irq!) 766baef150380d561a4d695a6be4fc509821c23611Calin Culianu*/ 776baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7825436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 795a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 80f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten#include <linux/pci.h> 816baef150380d561a4d695a6be4fc509821c23611Calin Culianu 82f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten#include "../comedidev.h" 83f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten#include "comedi_fc.h" 846baef150380d561a4d695a6be4fc509821c23611Calin Culianu 856baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CHANS_PER_PORT 8 866baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PORTS_PER_ASIC 6 876baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_PORTS_PER_ASIC 3 886baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */ 896baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT) 906baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC) 916baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_CHANS_PER_ASIC 24 926baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT) 936baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_DIO_CHANS (PORTS_PER_ASIC*2*CHANS_PER_PORT) 946baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC) 956baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define SDEV_NO ((int)(s - dev->subdevices)) 966baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define CALC_N_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/) 976baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* IO Memory sizes */ 986baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define ASIC_IOSIZE (0x10) 996baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PCMUIO48_IOSIZE ASIC_IOSIZE 1006baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PCMUIO96_IOSIZE (ASIC_IOSIZE*2) 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 1226baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page 1236baef150380d561a4d695a6be4fc509821c23611Calin Culianu and bits 0-5 are used to 'lock down' a particular 1246baef150380d561a4d695a6be4fc509821c23611Calin Culianu port above to make it readonly. */ 1256baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL0 0x8 1266baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL1 0x9 1276baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_POL2 0xA 1286baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB0 0x8 1296baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB1 0x9 1306baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_ENAB2 0xA 1316baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID0 0x8 1326baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID1 0x9 1336baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_INT_ID2 0xA 1346baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1356baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define NUM_PAGED_REGS 3 1366baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define NUM_PAGES 4 1376baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define FIRST_PAGED_REG 0x8 1386baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PAGE_BITOFFSET 6 1396baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_LOCK_BITOFFSET 0 1406baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_PAGE_MASK (~((0x1<<REG_PAGE_BITOFFSET)-1)) 1416baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define REG_LOCK_MASK ~(REG_PAGE_MASK) 1426baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_POL 1 1436baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_ENAB 2 1446baef150380d561a4d695a6be4fc509821c23611Calin Culianu#define PAGE_INT_ID 3 1456baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1466baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 1476baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Board descriptions for two imaginary boards. Describing the 1486baef150380d561a4d695a6be4fc509821c23611Calin Culianu * boards in this way is optional, and completely driver-dependent. 1496baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Some drivers use arrays such as this, other do not. 1506baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 15170a6001aeffeaa12f2a1c21470e8f3bdfb6ef8e7Bill Pembertonstruct pcmuio_board { 1526baef150380d561a4d695a6be4fc509821c23611Calin Culianu const char *name; 1536baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_asics; 1546baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_channels_per_port; 1556baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_ports; 15670a6001aeffeaa12f2a1c21470e8f3bdfb6ef8e7Bill Pemberton}; 1576baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1586baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* this structure is for data unique to this subdevice. */ 159e15849e54405152087cd343437747db8d931fcd7Bill Pembertonstruct pcmuio_subdev_private { 1606baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* mapping of halfwords (bytes) in port/chanarray to iobase */ 1616baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobases[PORTS_PER_SUBDEV]; 1626baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1636baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The below is only used for intr subdevices */ 1646baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 1656baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic; /* if non-negative, this subdev has an interrupt asic */ 1666baef150380d561a4d695a6be4fc509821c23611Calin Culianu int first_chan; /* if nonnegative, the first channel id for 1676baef150380d561a4d695a6be4fc509821c23611Calin Culianu interrupts. */ 1686baef150380d561a4d695a6be4fc509821c23611Calin Culianu int num_asic_chans; /* the number of asic channels in this subdev 1696baef150380d561a4d695a6be4fc509821c23611Calin Culianu that have interrutps */ 1706baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic_chan; /* if nonnegative, the first channel id with 1716baef150380d561a4d695a6be4fc509821c23611Calin Culianu respect to the asic that has interrupts */ 1726baef150380d561a4d695a6be4fc509821c23611Calin Culianu int enabled_mask; /* subdev-relative channel mask for channels 1736baef150380d561a4d695a6be4fc509821c23611Calin Culianu we are interested in */ 1746baef150380d561a4d695a6be4fc509821c23611Calin Culianu int active; 1756baef150380d561a4d695a6be4fc509821c23611Calin Culianu int stop_count; 1766baef150380d561a4d695a6be4fc509821c23611Calin Culianu int continuous; 1776baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 1786baef150380d561a4d695a6be4fc509821c23611Calin Culianu } intr; 179e15849e54405152087cd343437747db8d931fcd7Bill Pemberton}; 1806baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1816baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* this structure is for data unique to this hardware driver. If 1826baef150380d561a4d695a6be4fc509821c23611Calin Culianu several hardware drivers keep similar information in this structure, 18371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton feel free to suggest moving the variable to the struct comedi_device struct. */ 184055f6636d9eb27bc13236e07739e019496c21221Bill Pembertonstruct pcmuio_private { 1856baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 1866baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char pagelock; /* current page and lock */ 1876baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char pol[NUM_PAGED_REGS]; /* shadow of POLx registers */ 1886baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char enab[NUM_PAGED_REGS]; /* shadow of ENABx registers */ 1896baef150380d561a4d695a6be4fc509821c23611Calin Culianu int num; 1906baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase; 1916baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int irq; 1926baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 1936baef150380d561a4d695a6be4fc509821c23611Calin Culianu } asics[MAX_ASICS]; 194e15849e54405152087cd343437747db8d931fcd7Bill Pemberton struct pcmuio_subdev_private *sprivs; 195055f6636d9eb27bc13236e07739e019496c21221Bill Pemberton}; 1966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 197e15849e54405152087cd343437747db8d931fcd7Bill Pemberton#define subpriv ((struct pcmuio_subdev_private *)s->private) 1986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1996baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* DIO devices are slightly special. Although it is possible to 2006baef150380d561a4d695a6be4fc509821c23611Calin Culianu * implement the insn_read/insn_write interface, it is much more 2016baef150380d561a4d695a6be4fc509821c23611Calin Culianu * useful to applications if you implement the insn_bits interface. 2026baef150380d561a4d695a6be4fc509821c23611Calin Culianu * This allows packed reading/writing of the DIO channels. The 2036baef150380d561a4d695a6be4fc509821c23611Calin Culianu * comedi core can convert between insn_bits and insn_read/write */ 2040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_dio_insn_bits(struct comedi_device *dev, 2050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 2076baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 2086baef150380d561a4d695a6be4fc509821c23611Calin Culianu int byte_no; 2096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2106baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 2116baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 0 means this channel was high 2126baef150380d561a4d695a6be4fc509821c23611Calin Culianu writine a 0 sets the channel high 2136baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 1 means this channel was low 2146baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 means set this channel low 2156baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2166baef150380d561a4d695a6be4fc509821c23611Calin Culianu Therefore everything is always inverted. */ 2176baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2186baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The insn data is a mask in data[0] and the new data 2196baef150380d561a4d695a6be4fc509821c23611Calin Culianu * in data[1], each channel cooresponding to a bit. */ 2206baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2216baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 2226baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 223f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "write mask: %08x data: %08x\n", data[0], 224976fe5ab27e682d3dbfec26517a8a248638af07dRavishankar karkala Mallikarjunayya data[1]); 2256baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 2266baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2276baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state = 0; 2286baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2296baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { 2306baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* address of 8-bit port */ 2316baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr = subpriv->iobases[byte_no], 2320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* bit offset of port in 32-bit doubleword */ 2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral offset = byte_no * 8; 2346baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* this 8-bit port's data */ 2356baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte = 0, 2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The write mask for this port (if any) */ 2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral write_mask_byte = (data[0] >> offset) & 0xff, 2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The data byte for this port */ 2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data_byte = (data[1] >> offset) & 0xff; 2406baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2416baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); /* read all 8-bits for this port */ 2426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2436baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 2446baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ", 2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral byte_no, (unsigned)write_mask_byte, (unsigned)data_byte, 2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral offset, ioaddr, (unsigned)byte); 2496baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 2506baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2516baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (write_mask_byte) { 2526baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* this byte has some write_bits -- so set the output lines */ 2536baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte &= ~write_mask_byte; /* clear bits for write mask */ 2546baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */ 2556baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Write out the new digital output state */ 2566baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 2576baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 2586baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 2596baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 260f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "data_out_byte %02x\n", (unsigned)byte); 2616baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 2626baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save the digital input lines for this byte.. */ 2636baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state |= ((unsigned int)byte) << offset; 2646baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 2656baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2666baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now return the DIO lines to data[1] - note they came inverted! */ 2676baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = ~s->state; 2686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2696baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef DAMMIT_ITS_BROKEN 2706baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG */ 271f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "s->state %08x data_out %08x\n", s->state, 272976fe5ab27e682d3dbfec26517a8a248638af07dRavishankar karkala Mallikarjunayya data[1]); 2736baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif 2746baef150380d561a4d695a6be4fc509821c23611Calin Culianu 275a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten return insn->n; 2766baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 2776baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2786baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* The input or output configuration of each digital line is 2796baef150380d561a4d695a6be4fc509821c23611Calin Culianu * configured by a special insn_config instruction. chanspec 2806baef150380d561a4d695a6be4fc509821c23611Calin Culianu * contains the channel to be changed, and data[0] contains the 2816baef150380d561a4d695a6be4fc509821c23611Calin Culianu * value COMEDI_INPUT or COMEDI_OUTPUT. */ 2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_dio_insn_config(struct comedi_device *dev, 2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 2856baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 2866baef150380d561a4d695a6be4fc509821c23611Calin Culianu int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = 2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chan % 8; 2886baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr; 2896baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte; 2906baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2916baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Compute ioaddr for this channel */ 2926baef150380d561a4d695a6be4fc509821c23611Calin Culianu ioaddr = subpriv->iobases[byte_no]; 2936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2946baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 2956baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 0 an IO channel's bit sets the channel to INPUT 2966baef150380d561a4d695a6be4fc509821c23611Calin Culianu and pulls the line high as well 2976baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2986baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 to an IO channel's bit pulls the line low 2996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3006baef150380d561a4d695a6be4fc509821c23611Calin Culianu All channels are implicitly always in OUTPUT mode -- but when 3016baef150380d561a4d695a6be4fc509821c23611Calin Culianu they are high they can be considered to be in INPUT mode.. 3026baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3036baef150380d561a4d695a6be4fc509821c23611Calin Culianu Thus, we only force channels low if the config request was INPUT, 3046baef150380d561a4d695a6be4fc509821c23611Calin Culianu otherwise we do nothing to the hardware. */ 3056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3066baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (data[0]) { 3076baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_OUTPUT: 3086baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits -- don't actually do anything since 3096baef150380d561a4d695a6be4fc509821c23611Calin Culianu all input channels are also output channels... */ 3106baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits |= 1 << chan; 3116baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3126baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_INPUT: 3136baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* write a 0 to the actual register representing the channel 3146baef150380d561a4d695a6be4fc509821c23611Calin Culianu to set it to 'input'. 0 means "float high". */ 3156baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); 3166baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte &= ~(1 << bit_no); 3176baef150380d561a4d695a6be4fc509821c23611Calin Culianu /**< set input channel to '0' */ 3186baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3196baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* write out byte -- this is the only time we actually affect the 3206baef150380d561a4d695a6be4fc509821c23611Calin Culianu hardware as all channels are implicitly output -- but input 3216baef150380d561a4d695a6be4fc509821c23611Calin Culianu channels are set to float-high */ 3226baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 3236baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3246baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits */ 3256baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits &= ~(1 << chan); 3266baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3276baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3286baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_QUERY: 32925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* retrieve from shadow register */ 3306baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = 3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 3326baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 3336baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3346baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3356baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 3366baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 3376baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3386baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3396baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3406baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 3416baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 3426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3436b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic void switch_page(struct comedi_device *dev, int asic, int page) 3446b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 345a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 3469a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 347a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten 348a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (asic < 0 || asic >= board->num_asics) 3496b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* paranoia */ 3506b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (page < 0 || page >= NUM_PAGES) 3516b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* more paranoia */ 3526b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3536b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK; 3546b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET; 3556b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3566b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* now write out the shadow register */ 3576b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten outb(devpriv->asics[asic].pagelock, 3586b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); 3596b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 3606b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 361da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void init_asics(struct comedi_device *dev) 3626baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ /* sets up an 3636baef150380d561a4d695a6be4fc509821c23611Calin Culianu ASIC chip to defaults */ 364a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 3656baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic; 3666baef150380d561a4d695a6be4fc509821c23611Calin Culianu 367a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten for (asic = 0; asic < board->num_asics; ++asic) { 3686baef150380d561a4d695a6be4fc509821c23611Calin Culianu int port, page; 3696baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE; 3706baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3716baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 0); /* switch back to page 0 */ 3726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3736baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* first, clear all the DIO port bits */ 3746baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = 0; port < PORTS_PER_ASIC; ++port) 3756baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, baseaddr + REG_PORT0 + port); 3766baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3776baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Next, clear all the paged registers for each page */ 3786baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (page = 1; page < NUM_PAGES; ++page) { 3796baef150380d561a4d695a6be4fc509821c23611Calin Culianu int reg; 3806baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now clear all the paged registers */ 3816baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, page); 3826baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (reg = FIRST_PAGED_REG; 3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) 3846baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, baseaddr + reg); 3856baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3866baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3876baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* DEBUG set rising edge interrupts on port0 of both asics */ 3886baef150380d561a4d695a6be4fc509821c23611Calin Culianu /*switch_page(dev, asic, PAGE_POL); 3896baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0xff, baseaddr + REG_POL0); 3906baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_ENAB); 3916baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0xff, baseaddr + REG_ENAB0); */ 3926baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* END DEBUG */ 3936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3946baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 0); /* switch back to default page 0 */ 3956baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3966baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3976baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 3986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3996baef150380d561a4d695a6be4fc509821c23611Calin Culianu#ifdef notused 400da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void lock_port(struct comedi_device *dev, int asic, int port) 4016baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 402a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 4039a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 404a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten 405a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (asic < 0 || asic >= board->num_asics) 4066baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* paranoia */ 4076baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (port < 0 || port >= PORTS_PER_ASIC) 4086baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* more paranoia */ 4096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4106baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock |= 0x1 << port; 4116baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now write out the shadow register */ 4126baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(devpriv->asics[asic].pagelock, 4130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); 4146baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 4156baef150380d561a4d695a6be4fc509821c23611Calin Culianu 416da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void unlock_port(struct comedi_device *dev, int asic, int port) 4176baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 418a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 4199a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 420a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten 421a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (asic < 0 || asic >= board->num_asics) 4226baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* paranoia */ 4236baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (port < 0 || port >= PORTS_PER_ASIC) 4246baef150380d561a4d695a6be4fc509821c23611Calin Culianu return; /* more paranoia */ 4256baef150380d561a4d695a6be4fc509821c23611Calin Culianu devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK; 4266baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now write out the shadow register */ 4276baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(devpriv->asics[asic].pagelock, 4280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); 4296baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 4306baef150380d561a4d695a6be4fc509821c23611Calin Culianu#endif /* notused */ 4316baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4326b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic void pcmuio_stop_intr(struct comedi_device *dev, 4336b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten struct comedi_subdevice *s) 4346b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 4356b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int nports, firstport, asic, port; 4369a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 4376b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 4386b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten asic = subpriv->intr.asic; 4396b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (asic < 0) 4406b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* not an interrupt subdev */ 4416b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 4426b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.enabled_mask = 0; 4436b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 444920e2ffbe243fb0555b2c238e26fe7dbc03db98cH Hartley Sweeten s->async->inttrig = NULL; 4456b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; 4466b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; 4476b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten switch_page(dev, asic, PAGE_ENAB); 4486b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (port = firstport; port < firstport + nports; ++port) { 4496b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* disable all intrs for this subdev.. */ 4506b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port); 4516b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 4526b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 4536b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 45470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_pcmuio(int irq, void *d) 4556baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 4566baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic, got1 = 0; 4570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_device *dev = (struct comedi_device *)d; 4589a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 45968720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten int i; 4606baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4616baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (asic = 0; asic < MAX_ASICS; ++asic) { 4626baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (irq == devpriv->asics[asic].irq) { 4636baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 4646baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned triggered = 0; 4656baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase = devpriv->asics[asic].iobase; 4666baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* it is an interrupt for ASIC #asic */ 4676baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char int_pend; 4686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_lock_irqsave(&devpriv->asics[asic].spinlock, 4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 4716baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4726baef150380d561a4d695a6be4fc509821c23611Calin Culianu int_pend = inb(iobase + REG_INT_PENDING) & 0x07; 4736baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4746baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (int_pend) { 4756baef150380d561a4d695a6be4fc509821c23611Calin Culianu int port; 4766baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = 0; port < INTR_PORTS_PER_ASIC; 4770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ++port) { 4786baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (int_pend & (0x1 << port)) { 4796baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char 4800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral io_lines_with_edges = 0; 4816baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral PAGE_INT_ID); 4836baef150380d561a4d695a6be4fc509821c23611Calin Culianu io_lines_with_edges = 4840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inb(iobase + 4856baef150380d561a4d695a6be4fc509821c23611Calin Culianu REG_INT_ID0 + port); 4866baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4876baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (io_lines_with_edges) 4886baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* clear pending interrupt */ 4896baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, iobase + 4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral REG_INT_ID0 + 4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral port); 4926baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4936baef150380d561a4d695a6be4fc509821c23611Calin Culianu triggered |= 4940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral io_lines_with_edges << 4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral port * 8; 4966baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4976baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4996baef150380d561a4d695a6be4fc509821c23611Calin Culianu ++got1; 5006baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5016baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, 5030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 5046baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5056baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (triggered) { 50634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 5076baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TODO here: dispatch io lines to subdevs with commands.. */ 5080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 5090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", 5100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral irq, asic, triggered); 51168720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten for (i = 0; i < dev->n_subdevices; i++) { 51268720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten s = &dev->subdevices[i]; 5136baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ 5146baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 5156baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned oldevents; 5166baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_lock_irqsave(&subpriv-> 5180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral intr.spinlock, 5190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 5206baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5216baef150380d561a4d695a6be4fc509821c23611Calin Culianu oldevents = s->async->events; 5226baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5236baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.active) { 5246baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned mytrig = 5250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((triggered >> 5260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->intr.asic_chan) 5270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral & 5280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((0x1 << subpriv-> 5290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral intr. 5300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral num_asic_chans) - 5310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1)) << subpriv-> 5320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral intr.first_chan; 5330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (mytrig & 5340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->intr.enabled_mask) 5350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral { 5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int val 5370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = 0; 5386baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int n, 5390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ch, len; 5406baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral len = 5420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s-> 5430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral async->cmd.chanlist_len; 5446baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral n < len; 5460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral n++) { 5476baef150380d561a4d695a6be4fc509821c23611Calin Culianu ch = CR_CHAN(s->async->cmd.chanlist[n]); 5486baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (mytrig & (1U << ch)) { 5496baef150380d561a4d695a6be4fc509821c23611Calin Culianu val |= (1U << n); 5506baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5516baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5526baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Write the scan to the buffer. */ 5530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (comedi_buf_put(s->async, ((short *)&val)[0]) 5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && 5550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_buf_put 5560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->async, 5570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((short *) 5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &val)[1])) 5590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral { 5606baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); 5616baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 5626baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Overflow! Stop acquisition!! */ 5636baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 5646baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmuio_stop_intr 5650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (dev, 5660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s); 5676baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5686baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5696baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Check for end of acquisition. */ 5700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (!subpriv->intr.continuous) { 5716baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* stop_src == TRIG_COUNT */ 5726baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.stop_count > 0) { 5730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subpriv->intr.stop_count--; 5746baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.stop_count == 0) { 5756baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= COMEDI_CB_EOA; 5766baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 5776baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmuio_stop_intr 5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (dev, 5790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s); 5806baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5816baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5826baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5836baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5846baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral spin_unlock_irqrestore 5870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (&subpriv->intr.spinlock, 5880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral flags); 5896baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5906baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (oldevents != 5910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s->async->events) { 5926baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 5936baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5946baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5956baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5976baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5986baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6006baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6016baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6026baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!got1) 6036baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_NONE; /* interrupt from other source */ 6046baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_HANDLED; 6056baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6066baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_start_intr(struct comedi_device *dev, 6080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 6096baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6109a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 6119a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten 6126baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) { 6136baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* An empty acquisition! */ 6146baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= COMEDI_CB_EOA; 6156baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 0; 6166baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 6176baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 6186baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned bits = 0, pol_bits = 0, n; 6196baef150380d561a4d695a6be4fc509821c23611Calin Culianu int nports, firstport, asic, port; 620ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 6216baef150380d561a4d695a6be4fc509821c23611Calin Culianu 622c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton asic = subpriv->intr.asic; 623c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (asic < 0) 6246baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; /* not an interrupt 6256baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdev */ 6266baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.enabled_mask = 0; 6276baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 1; 6286baef150380d561a4d695a6be4fc509821c23611Calin Culianu nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; 6296baef150380d561a4d695a6be4fc509821c23611Calin Culianu firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; 6306baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (cmd->chanlist) { 6316baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < cmd->chanlist_len; n++) { 6326baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits |= (1U << CR_CHAN(cmd->chanlist[n])); 6336baef150380d561a4d695a6be4fc509821c23611Calin Culianu pol_bits |= (CR_AREF(cmd->chanlist[n]) 6340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral || CR_RANGE(cmd-> 6350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chanlist[n]) ? 1U : 0U) 6360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral << CR_CHAN(cmd->chanlist[n]); 6376baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6386baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6396baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits &= ((0x1 << subpriv->intr.num_asic_chans) - 6400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1) << subpriv->intr.first_chan; 6416baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.enabled_mask = bits; 6426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6436baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_ENAB); 6446baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = firstport; port < firstport + nports; ++port) { 6456baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned enab = 6460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bits >> (subpriv->intr.first_chan + (port - 6470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral firstport) * 6480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 8) & 0xff, pol = 6490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral pol_bits >> (subpriv->intr.first_chan + 6500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (port - firstport) * 8) & 0xff; 6516baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set enab intrs for this subdev.. */ 6526baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(enab, 6530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_ENAB0 + port); 6546baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, PAGE_POL); 6556baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(pol, 6560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->asics[asic].iobase + REG_ENAB0 + port); 6576baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6586baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6596baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 6606baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6616baef150380d561a4d695a6be4fc509821c23611Calin Culianu 662da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 6636baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6646baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 6656baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6665f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 6676baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.active) 6686baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmuio_stop_intr(dev, s); 6695f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 6706baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6716baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 6726baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6736baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6746baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 6756baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. 6766baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 6776baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int 678da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, 6790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int trignum) 6806baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6816baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 6826baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 6836baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6846baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (trignum != 0) 6856baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 6866baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6875f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 688920e2ffbe243fb0555b2c238e26fe7dbc03db98cH Hartley Sweeten s->async->inttrig = NULL; 6890389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (subpriv->intr.active) 6906baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmuio_start_intr(dev, s); 6910389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya 6925f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 6936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6940389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (event) 6956baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 6966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6976baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 6986baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7006baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 7016baef150380d561a4d695a6be4fc509821c23611Calin Culianu * 'do_cmd' function for an 'INTERRUPT' subdevice. 7026baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 703da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 7046baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 705ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 7066baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 7076baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 7086baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7095f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 7106baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 1; 7116baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7126baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up end of acquisition. */ 7136baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->stop_src) { 7146baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_COUNT: 7156baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.continuous = 0; 7166baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.stop_count = cmd->stop_arg; 7176baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7186baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 7196baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NONE */ 7206baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.continuous = 1; 7216baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.stop_count = 0; 7226baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7236baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 7246baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7256baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up start of acquisition. */ 7266baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->start_src) { 7276baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_INT: 7286baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->inttrig = pcmuio_inttrig_start_intr; 7296baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7306baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 7316baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NOW */ 7326baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmuio_start_intr(dev, s); 7336baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 7346baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 7355f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 7366baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7370389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (event) 7386baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 7396baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7406baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 7416baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 7426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 743f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweetenstatic int pcmuio_cmdtest(struct comedi_device *dev, 744f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten struct comedi_subdevice *s, 745f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten struct comedi_cmd *cmd) 7466baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 747f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten int err = 0; 748f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 749f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 1 : check if triggers are trivially valid */ 750f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 751f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); 752f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); 753f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); 754f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 755f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 756f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 757f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 758f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 1; 759f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 760f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 2a : make sure trigger sources are unique */ 761f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 762f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_is_unique(cmd->start_src); 763f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_is_unique(cmd->stop_src); 764f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 765f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 2b : and mutually compatible */ 766f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 767f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 768f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 2; 769f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 770f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 3: check if arguments are trivially valid */ 771f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 772f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 773f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 774f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 775f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 776f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 777f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten switch (cmd->stop_src) { 778f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten case TRIG_COUNT: 779f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* any count allowed */ 780f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 781f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten case TRIG_NONE: 782f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 783f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 784f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten default: 785f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 786f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten } 787f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 788f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 789f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 3; 790f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 791f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* step 4: fix up any arguments */ 792f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 793f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* if (err) return 4; */ 794f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 795f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 0; 7966baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 7976baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7986b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) 7996b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 800a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 8019a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv; 8026b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten struct comedi_subdevice *s; 8036b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; 8046b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten unsigned long iobase; 8056b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten unsigned int irq[MAX_ASICS]; 8068b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten int ret; 8076b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8086b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten iobase = it->options[0]; 8096b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[0] = it->options[1]; 8106b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[1] = it->options[2]; 8116b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 812f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "%s: io: %lx attach\n", 8132d2111ea2cf25cc60f7027130ceb34af2d03745dH Hartley Sweeten dev->driver->driver_name, iobase); 8146b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8156b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten dev->iobase = iobase; 8166b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8176b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (!iobase || !request_region(iobase, 818a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten board->num_asics * ASIC_IOSIZE, 8192d2111ea2cf25cc60f7027130ceb34af2d03745dH Hartley Sweeten dev->driver->driver_name)) { 820f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_err(dev->class_dev, "I/O port conflict\n"); 8216b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return -EIO; 8226b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8236b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 824a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten dev->board_name = board->name; 8256b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 826c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); 827c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten if (!devpriv) 828c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten return -ENOMEM; 829c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten dev->private = devpriv; 8306b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8316b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (asic = 0; asic < MAX_ASICS; ++asic) { 8326b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].num = asic; 8336b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE; 8346b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].irq = 0; /* this gets actually set at the end of 8356b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten this function when we 8366b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten request_irqs */ 8376b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten spin_lock_init(&devpriv->asics[asic].spinlock); 8386b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8396b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 840a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten chans_left = CHANS_PER_ASIC * board->num_asics; 8416b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten n_subdevs = CALC_N_SUBDEVS(chans_left); 8426b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->sprivs = 8436b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private), 8446b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten GFP_KERNEL); 8456b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (!devpriv->sprivs) { 846f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_warn(dev->class_dev, 847f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott "cannot allocate subdevice private data structures\n"); 8486b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return -ENOMEM; 8496b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 850eea6838b1206b0ac90110f1a6f58e101aa496e99H Hartley Sweeten 8518b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten ret = comedi_alloc_subdevices(dev, n_subdevs); 8528b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten if (ret) 8538b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten return ret; 8546b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8556b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 8566b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten asic = 0; 8576b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { 8586b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int byte_no; 8596b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 86068720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten s = &dev->subdevices[sdev_no]; 86168720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten s->private = &devpriv->sprivs[sdev_no]; 8626b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->maxdata = 1; 8636b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->range_table = &range_digital; 8646b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 8656b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->type = COMEDI_SUBD_DIO; 8666b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->insn_bits = pcmuio_dio_insn_bits; 8676b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->insn_config = pcmuio_dio_insn_config; 8686b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV); 8696b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic = -1; 8706b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.first_chan = -1; 8716b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic_chan = -1; 8726b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.num_asic_chans = -1; 8736b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 8746b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->len_chanlist = 1; 8756b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8766b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* save the ioport address for each 'port' of 8 channels in the 8776b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subdevice */ 8786b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) { 8796b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (port >= PORTS_PER_ASIC) { 8806b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 8816b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten ++asic; 8826b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten thisasic_chanct = 0; 8836b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8846b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->iobases[byte_no] = 8856b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].iobase + port; 8866b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8876b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (thisasic_chanct < 8886b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten CHANS_PER_PORT * INTR_PORTS_PER_ASIC 8896b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten && subpriv->intr.asic < 0) { 8906b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* this is an interrupt subdevice, so setup the struct */ 8916b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic = asic; 8926b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 8936b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.stop_count = 0; 8946b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.first_chan = byte_no * 8; 8956b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic_chan = thisasic_chanct; 8966b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.num_asic_chans = 8976b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->n_chan - subpriv->intr.first_chan; 8986b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten dev->read_subdev = s; 8996b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->subdev_flags |= SDF_CMD_READ; 9006b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->cancel = pcmuio_cancel; 9016b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->do_cmd = pcmuio_cmd; 9026b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->do_cmdtest = pcmuio_cmdtest; 9036b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->len_chanlist = subpriv->intr.num_asic_chans; 9046b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9056b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten thisasic_chanct += CHANS_PER_PORT; 9066b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9076b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten spin_lock_init(&subpriv->intr.spinlock); 9086b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9096b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten chans_left -= s->n_chan; 9106b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9116b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (!chans_left) { 9126b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten asic = 0; /* reset the asic to our first asic, to do intr subdevs */ 9136b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 9146b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9156b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9166b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9176b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9186b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten init_asics(dev); /* clear out all the registers, basically */ 9196b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9206b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { 9216b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (irq[asic] 9226b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten && request_irq(irq[asic], interrupt_pcmuio, 923a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten IRQF_SHARED, board->name, dev)) { 9246b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int i; 9256b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* unroll the allocated irqs.. */ 9266b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (i = asic - 1; i >= 0; --i) { 9276b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten free_irq(irq[i], dev); 9286b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[i].irq = irq[i] = 0; 9296b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9306b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[asic] = 0; 9316b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9326b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].irq = irq[asic]; 9336b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9346b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9356b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple 9366b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irqs.. */ 9376b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9386b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (irq[0]) { 939f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "irq: %u\n", irq[0]); 940a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (irq[1] && board->num_asics == 2) 941f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "second ASIC irq: %u\n", 942f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott irq[1]); 9436b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } else { 944f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "(IRQ mode disabled)\n"); 9456b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9466b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9476b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9486b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return 1; 9496b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 9506b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 951484ecc95d9cdfa8b2f7029e2f3409cf078aed4abH Hartley Sweetenstatic void pcmuio_detach(struct comedi_device *dev) 9526b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 953a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 9549a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 9556b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int i; 9566b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9576b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (dev->iobase) 958a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten release_region(dev->iobase, ASIC_IOSIZE * board->num_asics); 9596b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (i = 0; i < MAX_ASICS; ++i) { 9606b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (devpriv->asics[i].irq) 9616b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten free_irq(devpriv->asics[i].irq, dev); 9626b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 9636b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (devpriv && devpriv->sprivs) 9646b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten kfree(devpriv->sprivs); 9656b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 9666b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 9676b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic const struct pcmuio_board pcmuio_boards[] = { 9686b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten { 9696b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .name = "pcmuio48", 9706b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_asics = 1, 9716b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_ports = 6, 9726b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten }, { 9736b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .name = "pcmuio96", 9746b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_asics = 2, 9756b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_ports = 12, 9766b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten }, 9776b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten}; 9786b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 979294f930d98be86fb4f34302c718a49719650857fH Hartley Sweetenstatic struct comedi_driver pcmuio_driver = { 9806b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .driver_name = "pcmuio", 9816b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .module = THIS_MODULE, 9826b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .attach = pcmuio_attach, 9836b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .detach = pcmuio_detach, 9846b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .board_name = &pcmuio_boards[0].name, 9856b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .offset = sizeof(struct pcmuio_board), 9866b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_names = ARRAY_SIZE(pcmuio_boards), 9876b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten}; 988294f930d98be86fb4f34302c718a49719650857fH Hartley Sweetenmodule_comedi_driver(pcmuio_driver); 98990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 99090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 99190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 99290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 993