pcmuio.c revision f45a1f26eae4cadbfeb65b4b36bfa3583f694066
16baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 29e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * pcmuio.c 39e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Comedi driver for Winsystems PC-104 based 48/96-channel DIO boards. 49e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 59e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * COMEDI - Linux Control and Measurement Device Interface 69e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.org> 79e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 89e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * This program is free software; you can redistribute it and/or modify 99e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * it under the terms of the GNU General Public License as published by 109e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * the Free Software Foundation; either version 2 of the License, or 119e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * (at your option) any later version. 129e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 139e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * This program is distributed in the hope that it will be useful, 149e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * but WITHOUT ANY WARRANTY; without even the implied warranty of 159e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 169e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * GNU General Public License for more details. 179e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten */ 186baef150380d561a4d695a6be4fc509821c23611Calin Culianu 196baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 209e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Driver: pcmuio 219e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Description: Winsystems PC-104 based 48/96-channel DIO boards. 229e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Devices: (Winsystems) PCM-UIO48A [pcmuio48] 239e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * (Winsystems) PCM-UIO96A [pcmuio96] 249e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Author: Calin Culianu <calin@ajvar.org> 259e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Updated: Fri, 13 Jan 2006 12:01:01 -0500 269e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Status: works 279e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 289e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * A driver for the relatively straightforward-to-program PCM-UIO48A and 299e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * PCM-UIO96A boards from Winsystems. These boards use either one or two 309e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * (in the 96-DIO version) WS16C48 ASIC HighDensity I/O Chips (HDIO). This 319e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * chip is interesting in that each I/O line is individually programmable 329e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * for INPUT or OUTPUT (thus comedi_dio_config can be done on a per-channel 339e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * basis). Also, each chip supports edge-triggered interrupts for the first 349e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 24 I/O lines. Of course, since the 96-channel version of the board has 359e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * two ASICs, it can detect polarity changes on up to 48 I/O lines. Since 369e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * this is essentially an (non-PnP) ISA board, I/O Address and IRQ selection 379e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * are done through jumpers on the board. You need to pass that information 389e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * to this driver as the first and second comedi_config option, respectively. 399e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Note that the 48-channel version uses 16 bytes of IO memory and the 96- 409e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * channel version uses 32-bytes (in case you are worried about conflicts). 419e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * The 48-channel board is split into two 24-channel comedi subdevices. The 429e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 96-channel board is split into 4 24-channel DIO subdevices. 439e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 449e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Note that IRQ support has been added, but it is untested. 459e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 469e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * To use edge-detection IRQ support, pass the IRQs of both ASICS (for the 479e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 96 channel version) or just 1 ASIC (for 48-channel version). Then, use 489e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * comedi_commands with TRIG_NOW. Your callback will be called each time an 499e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * edge is triggered, and the data values will be two sample_t's, which 509e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * should be concatenated to form one 32-bit unsigned int. This value is 519e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * the mask of channels that had edges detected from your channel list. Note 529e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * that the bits positions in the mask correspond to positions in your 539e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * chanlist when you specified the command and *not* channel id's! 549e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 559e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * To set the polarity of the edge-detection interrupts pass a nonzero value 569e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * for either CR_RANGE or CR_AREF for edge-up polarity, or a zero value for 579e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * both CR_RANGE and CR_AREF if you want edge-down polarity. 589e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 599e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * In the 48-channel version: 609e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 619e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * On subdev 0, the first 24 channels channels are edge-detect channels. 629e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 639e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * In the 96-channel board you have the following channels that can do edge 649e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * detection: 659e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 669e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * subdev 0, channels 0-24 (first 24 channels of 1st ASIC) 679e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * subdev 2, channels 0-24 (first 24 channels of 2nd ASIC) 689e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * 699e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * Configuration Options: 709e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * [0] - I/O port base address 719e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * [1] - IRQ (for first ASIC, or first 24 channels) 729e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * [2] - IRQ (for second ASIC, pcmuio96 only - IRQ for chans 48-72 739e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten * can be the same as first irq!) 749e1087b5ae4c31c812e3f8a35256d7922a1cdbd6H Hartley Sweeten */ 756baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7625436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 775a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 786baef150380d561a4d695a6be4fc509821c23611Calin Culianu 79f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten#include "../comedidev.h" 8033782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten 81f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten#include "comedi_fc.h" 826baef150380d561a4d695a6be4fc509821c23611Calin Culianu 83f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten/* 84f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * Register I/O map 85f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 86f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * Offset Page 0 Page 1 Page 2 Page 3 87f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * ------ ----------- ----------- ----------- ----------- 88f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x00 Port 0 I/O Port 0 I/O Port 0 I/O Port 0 I/O 89f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x01 Port 1 I/O Port 1 I/O Port 1 I/O Port 1 I/O 90f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x02 Port 2 I/O Port 2 I/O Port 2 I/O Port 2 I/O 91f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x03 Port 3 I/O Port 3 I/O Port 3 I/O Port 3 I/O 92f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x04 Port 4 I/O Port 4 I/O Port 4 I/O Port 4 I/O 93f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x05 Port 5 I/O Port 5 I/O Port 5 I/O Port 5 I/O 94f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x06 INT_PENDING INT_PENDING INT_PENDING INT_PENDING 95f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x07 Page/Lock Page/Lock Page/Lock Page/Lock 96f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x08 N/A POL_0 ENAB_0 INT_ID0 97f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x09 N/A POL_1 ENAB_1 INT_ID1 98f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten * 0x0a N/A POL_2 ENAB_2 INT_ID2 99f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten */ 100f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PORT_REG(x) (0x00 + (x)) 101f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_INT_PENDING_REG 0x06 102f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_LOCK_REG 0x07 103f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_LOCK_PORT(x) ((1 << (x)) & 0x3f) 104f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE(x) (((x) & 0x3) << 6) 105f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_MASK PCMUIO_PAGE(3) 106f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_POL 1 107f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_ENAB 2 108f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_INT_ID 3 109f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten#define PCMUIO_PAGE_REG(x) (0x08 + (x)) 110f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten 111288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define CHANS_PER_PORT 8 112288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define PORTS_PER_ASIC 6 113288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define INTR_PORTS_PER_ASIC 3 114288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten/* number of channels per comedi subdevice */ 115288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define MAX_CHANS_PER_SUBDEV 24 116288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV / CHANS_PER_PORT) 117288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define CHANS_PER_ASIC (CHANS_PER_PORT * PORTS_PER_ASIC) 118288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define INTR_CHANS_PER_ASIC 24 119288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC / CHANS_PER_PORT) 120288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define MAX_DIO_CHANS (PORTS_PER_ASIC * 2 * CHANS_PER_PORT) 121288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define MAX_ASICS (MAX_DIO_CHANS / CHANS_PER_ASIC) 1226baef150380d561a4d695a6be4fc509821c23611Calin Culianu 123288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten/* IO Memory sizes */ 124288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define ASIC_IOSIZE 0x10 125288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define PCMUIO48_IOSIZE ASIC_IOSIZE 126288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define PCMUIO96_IOSIZE (ASIC_IOSIZE * 2) 1276baef150380d561a4d695a6be4fc509821c23611Calin Culianu 128288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define NUM_PAGED_REGS 3 129288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define NUM_PAGES 4 130288201328ba804a5630c7a460534e668703f114fH Hartley Sweeten#define FIRST_PAGED_REG 0x8 1316baef150380d561a4d695a6be4fc509821c23611Calin Culianu 13270a6001aeffeaa12f2a1c21470e8f3bdfb6ef8e7Bill Pembertonstruct pcmuio_board { 1336baef150380d561a4d695a6be4fc509821c23611Calin Culianu const char *name; 1346baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_asics; 1356baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_channels_per_port; 1366baef150380d561a4d695a6be4fc509821c23611Calin Culianu const int num_ports; 13770a6001aeffeaa12f2a1c21470e8f3bdfb6ef8e7Bill Pemberton}; 1386baef150380d561a4d695a6be4fc509821c23611Calin Culianu 139fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweetenstatic const struct pcmuio_board pcmuio_boards[] = { 140fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten { 141fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .name = "pcmuio48", 142fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .num_asics = 1, 143fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .num_ports = 6, 144fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten }, { 145fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .name = "pcmuio96", 146fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .num_asics = 2, 147fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten .num_ports = 12, 148fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten }, 149fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten}; 150fbe3bb17b9f9e18b771c30449916807c4c25e308H Hartley Sweeten 151e15849e54405152087cd343437747db8d931fcd7Bill Pembertonstruct pcmuio_subdev_private { 1526baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* mapping of halfwords (bytes) in port/chanarray to iobase */ 1536baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobases[PORTS_PER_SUBDEV]; 1546baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1556baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The below is only used for intr subdevices */ 1566baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 157365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* if non-negative, this subdev has an interrupt asic */ 158365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten int asic; 159365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* if nonnegative, the first channel id for interrupts */ 160365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten int first_chan; 161365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* 162365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * the number of asic channels in this 163365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * subdev that have interrutps 164365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten */ 165365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten int num_asic_chans; 166365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* 167365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * if nonnegative, the first channel id with 168365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * respect to the asic that has interrupts 169365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten */ 170365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten int asic_chan; 171365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* 172365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * subdev-relative channel mask for channels 173365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * we are interested in 174365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten */ 175365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten int enabled_mask; 1766baef150380d561a4d695a6be4fc509821c23611Calin Culianu int active; 1776baef150380d561a4d695a6be4fc509821c23611Calin Culianu int stop_count; 1786baef150380d561a4d695a6be4fc509821c23611Calin Culianu int continuous; 1796baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 1806baef150380d561a4d695a6be4fc509821c23611Calin Culianu } intr; 181e15849e54405152087cd343437747db8d931fcd7Bill Pemberton}; 1826baef150380d561a4d695a6be4fc509821c23611Calin Culianu 183055f6636d9eb27bc13236e07739e019496c21221Bill Pembertonstruct pcmuio_private { 1846baef150380d561a4d695a6be4fc509821c23611Calin Culianu struct { 185365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* current page and lock */ 186365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten unsigned char pagelock; 187365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* shadow of POLx registers */ 188365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten unsigned char pol[NUM_PAGED_REGS]; 189365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* shadow of ENABx registers */ 190365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten unsigned char enab[NUM_PAGED_REGS]; 1916baef150380d561a4d695a6be4fc509821c23611Calin Culianu int num; 1926baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long iobase; 1936baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned int irq; 1946baef150380d561a4d695a6be4fc509821c23611Calin Culianu spinlock_t spinlock; 1956baef150380d561a4d695a6be4fc509821c23611Calin Culianu } asics[MAX_ASICS]; 196e15849e54405152087cd343437747db8d931fcd7Bill Pemberton struct pcmuio_subdev_private *sprivs; 197055f6636d9eb27bc13236e07739e019496c21221Bill Pemberton}; 1986baef150380d561a4d695a6be4fc509821c23611Calin Culianu 1990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_dio_insn_bits(struct comedi_device *dev, 2000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 2026baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 2038099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 2046baef150380d561a4d695a6be4fc509821c23611Calin Culianu int byte_no; 2056baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2066baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 2076baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 0 means this channel was high 2086baef150380d561a4d695a6be4fc509821c23611Calin Culianu writine a 0 sets the channel high 2096baef150380d561a4d695a6be4fc509821c23611Calin Culianu reading a 1 means this channel was low 2106baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 means set this channel low 2116baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2126baef150380d561a4d695a6be4fc509821c23611Calin Culianu Therefore everything is always inverted. */ 2136baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2146baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* The insn data is a mask in data[0] and the new data 2156baef150380d561a4d695a6be4fc509821c23611Calin Culianu * in data[1], each channel cooresponding to a bit. */ 2166baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2176baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state = 0; 2186baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2196baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { 2206baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* address of 8-bit port */ 2216baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr = subpriv->iobases[byte_no], 2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* bit offset of port in 32-bit doubleword */ 2230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral offset = byte_no * 8; 2246baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* this 8-bit port's data */ 2256baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte = 0, 2260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The write mask for this port (if any) */ 2270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral write_mask_byte = (data[0] >> offset) & 0xff, 2280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* The data byte for this port */ 2290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data_byte = (data[1] >> offset) & 0xff; 2306baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2316baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); /* read all 8-bits for this port */ 2326baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2336baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (write_mask_byte) { 234365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten byte &= ~write_mask_byte; 235365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten byte |= ~data_byte & write_mask_byte; 2366baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 2376baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 2386baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save the digital input lines for this byte.. */ 2396baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->state |= ((unsigned int)byte) << offset; 2406baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 2416baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2426baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now return the DIO lines to data[1] - note they came inverted! */ 2436baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = ~s->state; 2446baef150380d561a4d695a6be4fc509821c23611Calin Culianu 245a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten return insn->n; 2466baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 2476baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_dio_insn_config(struct comedi_device *dev, 2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 2516baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 2528099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 2536baef150380d561a4d695a6be4fc509821c23611Calin Culianu int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = 2540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chan % 8; 2556baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long ioaddr; 2566baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned char byte; 2576baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2586baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Compute ioaddr for this channel */ 2596baef150380d561a4d695a6be4fc509821c23611Calin Culianu ioaddr = subpriv->iobases[byte_no]; 2606baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2616baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* NOTE: 2626baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 0 an IO channel's bit sets the channel to INPUT 2636baef150380d561a4d695a6be4fc509821c23611Calin Culianu and pulls the line high as well 2646baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2656baef150380d561a4d695a6be4fc509821c23611Calin Culianu writing a 1 to an IO channel's bit pulls the line low 2666baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2676baef150380d561a4d695a6be4fc509821c23611Calin Culianu All channels are implicitly always in OUTPUT mode -- but when 2686baef150380d561a4d695a6be4fc509821c23611Calin Culianu they are high they can be considered to be in INPUT mode.. 2696baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2706baef150380d561a4d695a6be4fc509821c23611Calin Culianu Thus, we only force channels low if the config request was INPUT, 2716baef150380d561a4d695a6be4fc509821c23611Calin Culianu otherwise we do nothing to the hardware. */ 2726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2736baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (data[0]) { 2746baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_OUTPUT: 2756baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits -- don't actually do anything since 2766baef150380d561a4d695a6be4fc509821c23611Calin Culianu all input channels are also output channels... */ 2776baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits |= 1 << chan; 2786baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 2796baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_INPUT: 2806baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* write a 0 to the actual register representing the channel 2816baef150380d561a4d695a6be4fc509821c23611Calin Culianu to set it to 'input'. 0 means "float high". */ 2826baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte = inb(ioaddr); 2836baef150380d561a4d695a6be4fc509821c23611Calin Culianu byte &= ~(1 << bit_no); 2846baef150380d561a4d695a6be4fc509821c23611Calin Culianu /**< set input channel to '0' */ 2856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 286365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* 287365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * write out byte 288365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * This is the only time we actually affect the hardware 289365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * as all channels are implicitly output -- but input 290365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten * channels are set to float-high. 291365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten */ 2926baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(byte, ioaddr); 2936baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2946baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* save to io_bits */ 2956baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->io_bits &= ~(1 << chan); 2966baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 2976baef150380d561a4d695a6be4fc509821c23611Calin Culianu 2986baef150380d561a4d695a6be4fc509821c23611Calin Culianu case INSN_CONFIG_DIO_QUERY: 29925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* retrieve from shadow register */ 3006baef150380d561a4d695a6be4fc509821c23611Calin Culianu data[1] = 3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 3026baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 3036baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3046baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3056baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 3066baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 3076baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 3086baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3106baef150380d561a4d695a6be4fc509821c23611Calin Culianu return insn->n; 3116baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 3126baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3136b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic void switch_page(struct comedi_device *dev, int asic, int page) 3146b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 315a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 3169a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 317a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten 318a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (asic < 0 || asic >= board->num_asics) 3196b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* paranoia */ 3206b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (page < 0 || page >= NUM_PAGES) 3216b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* more paranoia */ 3226b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 323f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten devpriv->asics[asic].pagelock &= ~PCMUIO_PAGE_MASK; 324f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten devpriv->asics[asic].pagelock |= PCMUIO_PAGE(page); 3256b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3266b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* now write out the shadow register */ 3276b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten outb(devpriv->asics[asic].pagelock, 328f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten dev->iobase + ASIC_IOSIZE * asic + PCMUIO_PAGE_LOCK_REG); 3296b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 3306b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 331da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void init_asics(struct comedi_device *dev) 3326baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ /* sets up an 3336baef150380d561a4d695a6be4fc509821c23611Calin Culianu ASIC chip to defaults */ 334a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 3356baef150380d561a4d695a6be4fc509821c23611Calin Culianu int asic; 3366baef150380d561a4d695a6be4fc509821c23611Calin Culianu 337a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten for (asic = 0; asic < board->num_asics; ++asic) { 3386baef150380d561a4d695a6be4fc509821c23611Calin Culianu int port, page; 3396baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE; 3406baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3416baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, 0); /* switch back to page 0 */ 3426baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3436baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* first, clear all the DIO port bits */ 3446baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = 0; port < PORTS_PER_ASIC; ++port) 345f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten outb(0, baseaddr + PCMUIO_PORT_REG(port)); 3466baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3476baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Next, clear all the paged registers for each page */ 3486baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (page = 1; page < NUM_PAGES; ++page) { 3496baef150380d561a4d695a6be4fc509821c23611Calin Culianu int reg; 3506baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* now clear all the paged registers */ 3516baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch_page(dev, asic, page); 3526baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (reg = FIRST_PAGED_REG; 3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) 3546baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(0, baseaddr + reg); 3556baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3566baef150380d561a4d695a6be4fc509821c23611Calin Culianu 357365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* switch back to default page 0 */ 358365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten switch_page(dev, asic, 0); 3596baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 3606baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 3616baef150380d561a4d695a6be4fc509821c23611Calin Culianu 3626b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic void pcmuio_stop_intr(struct comedi_device *dev, 3636b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten struct comedi_subdevice *s) 3646b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 3659a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 3668099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 3678099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten int nports, firstport, asic, port; 3686b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3696b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten asic = subpriv->intr.asic; 3706b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (asic < 0) 3716b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return; /* not an interrupt subdev */ 3726b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3736b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.enabled_mask = 0; 3746b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 375920e2ffbe243fb0555b2c238e26fe7dbc03db98cH Hartley Sweeten s->async->inttrig = NULL; 3766b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; 3776b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; 378f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten switch_page(dev, asic, PCMUIO_PAGE_ENAB); 3796b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (port = firstport; port < firstport + nports; ++port) { 3806b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* disable all intrs for this subdev.. */ 381f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten outb(0, devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port)); 3826b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 3836b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 3846b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 3853b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweetenstatic void pcmuio_handle_intr_subdev(struct comedi_device *dev, 3863b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten struct comedi_subdevice *s, 3873b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned triggered) 3883b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten{ 3893b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 3903b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned int len = s->async->cmd.chanlist_len; 3913b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned oldevents = s->async->events; 3923b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned int val = 0; 3933b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned long flags; 3943b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned mytrig; 3953b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned int i; 3963b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 3973b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten spin_lock_irqsave(&subpriv->intr.spinlock, flags); 3983b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 3993b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (!subpriv->intr.active) 4003b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten goto done; 4013b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4023b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten mytrig = triggered >> subpriv->intr.asic_chan; 4033b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten mytrig &= ((0x1 << subpriv->intr.num_asic_chans) - 1); 4043b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten mytrig <<= subpriv->intr.first_chan; 4053b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4063b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (!(mytrig & subpriv->intr.enabled_mask)) 4073b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten goto done; 4083b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4093b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten for (i = 0; i < len; i++) { 4103b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]); 4113b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (mytrig & (1U << chan)) 4123b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten val |= (1U << i); 4133b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4143b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4153b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* Write the scan to the buffer. */ 4163b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (comedi_buf_put(s->async, ((short *)&val)[0]) && 4173b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten comedi_buf_put(s->async, ((short *)&val)[1])) { 4183b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); 4193b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } else { 4203b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* Overflow! Stop acquisition!! */ 4213b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 4223b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten pcmuio_stop_intr(dev, s); 4233b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4243b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4253b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* Check for end of acquisition. */ 4263b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (!subpriv->intr.continuous) { 4273b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* stop_src == TRIG_COUNT */ 4283b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (subpriv->intr.stop_count > 0) { 4293b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten subpriv->intr.stop_count--; 4303b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (subpriv->intr.stop_count == 0) { 4313b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten s->async->events |= COMEDI_CB_EOA; 4323b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* TODO: STOP_ACQUISITION_CALL_HERE!! */ 4333b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten pcmuio_stop_intr(dev, s); 4343b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4353b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4363b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4373b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4383b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweetendone: 4393b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 4403b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4413b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (oldevents != s->async->events) 4423b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten comedi_event(dev, s); 4433b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten} 4443b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4453b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweetenstatic int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic) 4466baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 4479a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 4488099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv; 4493b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned long iobase = devpriv->asics[asic].iobase; 4503b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned triggered = 0; 4513b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten int got1 = 0; 4523b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned long flags; 4533b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned char int_pend; 45468720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten int i; 4556baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4563b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags); 4573b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 458f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten int_pend = inb(iobase + PCMUIO_INT_PENDING_REG) & 0x07; 4593b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (int_pend) { 4603b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten for (i = 0; i < INTR_PORTS_PER_ASIC; ++i) { 4613b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (int_pend & (0x1 << i)) { 4623b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten unsigned char val; 4633b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 464f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten switch_page(dev, asic, PCMUIO_PAGE_INT_ID); 465f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten val = inb(iobase + PCMUIO_PAGE_REG(i)); 4663b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (val) 4673b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* clear pending interrupt */ 468f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten outb(0, iobase + PCMUIO_PAGE_REG(i)); 4693b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4703b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten triggered |= (val << (i * 8)); 4716baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4723b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4736baef150380d561a4d695a6be4fc509821c23611Calin Culianu 4743b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten ++got1; 4753b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4763b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4773b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, flags); 4783b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4793b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (triggered) { 4803b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten struct comedi_subdevice *s; 4813b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* TODO here: dispatch io lines to subdevs with commands.. */ 4823b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten for (i = 0; i < dev->n_subdevices; i++) { 4833b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten s = &dev->subdevices[i]; 4843b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten subpriv = s->private; 4853b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (subpriv->intr.asic == asic) { 4863b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* 4873b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten * This is an interrupt subdev, and it 4883b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten * matches this asic! 4893b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten */ 4903b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten pcmuio_handle_intr_subdev(dev, s, 4913b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten triggered); 4926baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 4933b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4943b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten } 4953b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten return got1; 4963b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten} 4973b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten 4983b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweetenstatic irqreturn_t interrupt_pcmuio(int irq, void *d) 4993b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten{ 5003b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten struct comedi_device *dev = d; 5013b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 5023b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten int got1 = 0; 5033b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten int asic; 5046baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5053b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten for (asic = 0; asic < MAX_ASICS; ++asic) { 5063b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (irq == devpriv->asics[asic].irq) { 5073b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten /* it is an interrupt for ASIC #asic */ 5083b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten if (pcmuio_handle_asic_interrupt(dev, asic)) 5093b48c535802eb515069b4f2ff26f0601eabf51b8H Hartley Sweeten got1++; 5106baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5116baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5126baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!got1) 5136baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_NONE; /* interrupt from other source */ 5146baef150380d561a4d695a6be4fc509821c23611Calin Culianu return IRQ_HANDLED; 5156baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 5166baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcmuio_start_intr(struct comedi_device *dev, 5180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 5196baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 5209a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 5218099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 5229a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten 5236baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) { 5246baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* An empty acquisition! */ 5256baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->events |= COMEDI_CB_EOA; 5266baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 0; 5276baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 5286baef150380d561a4d695a6be4fc509821c23611Calin Culianu } else { 5296baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned bits = 0, pol_bits = 0, n; 5306baef150380d561a4d695a6be4fc509821c23611Calin Culianu int nports, firstport, asic, port; 531ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 5326baef150380d561a4d695a6be4fc509821c23611Calin Culianu 533c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton asic = subpriv->intr.asic; 534c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (asic < 0) 5356baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; /* not an interrupt 5366baef150380d561a4d695a6be4fc509821c23611Calin Culianu subdev */ 5376baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.enabled_mask = 0; 5386baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 1; 5396baef150380d561a4d695a6be4fc509821c23611Calin Culianu nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; 5406baef150380d561a4d695a6be4fc509821c23611Calin Culianu firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; 5416baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (cmd->chanlist) { 5426baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (n = 0; n < cmd->chanlist_len; n++) { 5436baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits |= (1U << CR_CHAN(cmd->chanlist[n])); 5446baef150380d561a4d695a6be4fc509821c23611Calin Culianu pol_bits |= (CR_AREF(cmd->chanlist[n]) 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral || CR_RANGE(cmd-> 5460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral chanlist[n]) ? 1U : 0U) 5470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral << CR_CHAN(cmd->chanlist[n]); 5486baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5496baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5506baef150380d561a4d695a6be4fc509821c23611Calin Culianu bits &= ((0x1 << subpriv->intr.num_asic_chans) - 5510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1) << subpriv->intr.first_chan; 5526baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.enabled_mask = bits; 5536baef150380d561a4d695a6be4fc509821c23611Calin Culianu 554f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten switch_page(dev, asic, PCMUIO_PAGE_ENAB); 5556baef150380d561a4d695a6be4fc509821c23611Calin Culianu for (port = firstport; port < firstport + nports; ++port) { 5566baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned enab = 5570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bits >> (subpriv->intr.first_chan + (port - 5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral firstport) * 5590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 8) & 0xff, pol = 5600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral pol_bits >> (subpriv->intr.first_chan + 5610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (port - firstport) * 8) & 0xff; 5626baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* set enab intrs for this subdev.. */ 5636baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(enab, 564f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port)); 565f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten switch_page(dev, asic, PCMUIO_PAGE_POL); 5666baef150380d561a4d695a6be4fc509821c23611Calin Culianu outb(pol, 567f45a1f26eae4cadbfeb65b4b36bfa3583f694066H Hartley Sweeten devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port)); 5686baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5696baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 5706baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 5716baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 5726baef150380d561a4d695a6be4fc509821c23611Calin Culianu 573da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 5746baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 5758099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 5766baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 5776baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5785f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 5796baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (subpriv->intr.active) 5806baef150380d561a4d695a6be4fc509821c23611Calin Culianu pcmuio_stop_intr(dev, s); 5815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 5826baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5836baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 5846baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 5856baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5866baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 5876baef150380d561a4d695a6be4fc509821c23611Calin Culianu * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. 5886baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 5896baef150380d561a4d695a6be4fc509821c23611Calin Culianustatic int 590da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, 5910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int trignum) 5926baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 5938099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 5946baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 5956baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 5966baef150380d561a4d695a6be4fc509821c23611Calin Culianu 5976baef150380d561a4d695a6be4fc509821c23611Calin Culianu if (trignum != 0) 5986baef150380d561a4d695a6be4fc509821c23611Calin Culianu return -EINVAL; 5996baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6005f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 601920e2ffbe243fb0555b2c238e26fe7dbc03db98cH Hartley Sweeten s->async->inttrig = NULL; 6020389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (subpriv->intr.active) 6036baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmuio_start_intr(dev, s); 6040389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya 6055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 6066baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6070389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (event) 6086baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 6096baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6106baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 1; 6116baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6126baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6136baef150380d561a4d695a6be4fc509821c23611Calin Culianu/* 6146baef150380d561a4d695a6be4fc509821c23611Calin Culianu * 'do_cmd' function for an 'INTERRUPT' subdevice. 6156baef150380d561a4d695a6be4fc509821c23611Calin Culianu */ 616da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 6176baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 6188099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv = s->private; 619ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 6206baef150380d561a4d695a6be4fc509821c23611Calin Culianu unsigned long flags; 6216baef150380d561a4d695a6be4fc509821c23611Calin Culianu int event = 0; 6226baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&subpriv->intr.spinlock, flags); 6246baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.active = 1; 6256baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6266baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up end of acquisition. */ 6276baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->stop_src) { 6286baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_COUNT: 6296baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.continuous = 0; 6306baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.stop_count = cmd->stop_arg; 6316baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 6326baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 6336baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NONE */ 6346baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.continuous = 1; 6356baef150380d561a4d695a6be4fc509821c23611Calin Culianu subpriv->intr.stop_count = 0; 6366baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 6376baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6386baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6396baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* Set up start of acquisition. */ 6406baef150380d561a4d695a6be4fc509821c23611Calin Culianu switch (cmd->start_src) { 6416baef150380d561a4d695a6be4fc509821c23611Calin Culianu case TRIG_INT: 6426baef150380d561a4d695a6be4fc509821c23611Calin Culianu s->async->inttrig = pcmuio_inttrig_start_intr; 6436baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 6446baef150380d561a4d695a6be4fc509821c23611Calin Culianu default: 6456baef150380d561a4d695a6be4fc509821c23611Calin Culianu /* TRIG_NOW */ 6466baef150380d561a4d695a6be4fc509821c23611Calin Culianu event = pcmuio_start_intr(dev, s); 6476baef150380d561a4d695a6be4fc509821c23611Calin Culianu break; 6486baef150380d561a4d695a6be4fc509821c23611Calin Culianu } 6495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); 6506baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6510389245f0c5692111c0dc8d997fc4af72d789472Ravishankar karkala Mallikarjunayya if (event) 6526baef150380d561a4d695a6be4fc509821c23611Calin Culianu comedi_event(dev, s); 6536baef150380d561a4d695a6be4fc509821c23611Calin Culianu 6546baef150380d561a4d695a6be4fc509821c23611Calin Culianu return 0; 6556baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 6566baef150380d561a4d695a6be4fc509821c23611Calin Culianu 657f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweetenstatic int pcmuio_cmdtest(struct comedi_device *dev, 658f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten struct comedi_subdevice *s, 659f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten struct comedi_cmd *cmd) 6606baef150380d561a4d695a6be4fc509821c23611Calin Culianu{ 661f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten int err = 0; 662f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 663f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 1 : check if triggers are trivially valid */ 664f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 665f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); 666f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); 667f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); 668f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 669f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 670f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 671f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 672f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 1; 673f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 674f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 2a : make sure trigger sources are unique */ 675f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 676f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_is_unique(cmd->start_src); 677f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_is_unique(cmd->stop_src); 678f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 679f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 2b : and mutually compatible */ 680f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 681f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 682f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 2; 683f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 684f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* Step 3: check if arguments are trivially valid */ 685f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 686f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 687f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 688f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 689f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 690f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 691f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten switch (cmd->stop_src) { 692f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten case TRIG_COUNT: 693f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* any count allowed */ 694f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 695f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten case TRIG_NONE: 696f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 697f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 698f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten default: 699f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten break; 700f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten } 701f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 702f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten if (err) 703f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 3; 704f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 705f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* step 4: fix up any arguments */ 706f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 707f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten /* if (err) return 4; */ 708f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten 709f95d45d114e1fd024bdee67beb80fce9b9c96126H Hartley Sweeten return 0; 7106baef150380d561a4d695a6be4fc509821c23611Calin Culianu} 7116baef150380d561a4d695a6be4fc509821c23611Calin Culianu 7126b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweetenstatic int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) 7136b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 714a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten const struct pcmuio_board *board = comedi_board(dev); 7156b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten struct comedi_subdevice *s; 7168099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_private *devpriv; 7178099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten struct pcmuio_subdev_private *subpriv; 7186b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; 7196b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten unsigned int irq[MAX_ASICS]; 7208b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten int ret; 7216b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 7226b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[0] = it->options[1]; 7236b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[1] = it->options[2]; 7246b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 72535626c2efecd6dad6ef67124ae2604385b717ed7H Hartley Sweeten ret = comedi_request_region(dev, it->options[0], 72635626c2efecd6dad6ef67124ae2604385b717ed7H Hartley Sweeten board->num_asics * ASIC_IOSIZE); 72735626c2efecd6dad6ef67124ae2604385b717ed7H Hartley Sweeten if (ret) 72835626c2efecd6dad6ef67124ae2604385b717ed7H Hartley Sweeten return ret; 7296b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 730c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); 731c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten if (!devpriv) 732c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten return -ENOMEM; 733c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten dev->private = devpriv; 7346b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 7356b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (asic = 0; asic < MAX_ASICS; ++asic) { 7366b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].num = asic; 7376b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE; 7386b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten spin_lock_init(&devpriv->asics[asic].spinlock); 7396b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 7406b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 741a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten chans_left = CHANS_PER_ASIC * board->num_asics; 74200b863964d3d24e7ae1dfb571e45707136c6cf42H Hartley Sweeten n_subdevs = (chans_left / MAX_CHANS_PER_SUBDEV) + 74300b863964d3d24e7ae1dfb571e45707136c6cf42H Hartley Sweeten (!!(chans_left % MAX_CHANS_PER_SUBDEV)); 74478110bb8dc4a7ff331bfa3cfe7d4e287cfb3f22bJoe Perches devpriv->sprivs = kcalloc(n_subdevs, 74578110bb8dc4a7ff331bfa3cfe7d4e287cfb3f22bJoe Perches sizeof(struct pcmuio_subdev_private), 74678110bb8dc4a7ff331bfa3cfe7d4e287cfb3f22bJoe Perches GFP_KERNEL); 74778110bb8dc4a7ff331bfa3cfe7d4e287cfb3f22bJoe Perches if (!devpriv->sprivs) 7486b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return -ENOMEM; 749eea6838b1206b0ac90110f1a6f58e101aa496e99H Hartley Sweeten 7508b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten ret = comedi_alloc_subdevices(dev, n_subdevs); 7518b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten if (ret) 7528b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten return ret; 7536b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 7546b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 7556b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten asic = 0; 7566b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { 7576b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int byte_no; 7586b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 75968720ae68a94444387d56bc5a166396e33e420a5H Hartley Sweeten s = &dev->subdevices[sdev_no]; 7608099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten subpriv = &devpriv->sprivs[sdev_no]; 7618099a9841f1d9ff15de8f12cf1ba36b574d804c8H Hartley Sweeten s->private = subpriv; 7626b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->maxdata = 1; 7636b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->range_table = &range_digital; 7646b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 7656b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->type = COMEDI_SUBD_DIO; 7666b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->insn_bits = pcmuio_dio_insn_bits; 7676b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->insn_config = pcmuio_dio_insn_config; 7686b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV); 7696b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic = -1; 7706b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.first_chan = -1; 7716b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic_chan = -1; 7726b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.num_asic_chans = -1; 7736b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 7746b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->len_chanlist = 1; 7756b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 7766b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* save the ioport address for each 'port' of 8 channels in the 7776b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subdevice */ 7786d28bea92c27c383dd224ca6327d84d0dde2e770H Hartley Sweeten for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; 7796d28bea92c27c383dd224ca6327d84d0dde2e770H Hartley Sweeten ++byte_no, ++port) { 7806b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (port >= PORTS_PER_ASIC) { 7816b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 7826b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten ++asic; 7836b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten thisasic_chanct = 0; 7846b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 7856b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->iobases[byte_no] = 7866b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].iobase + port; 7876b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 7886b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (thisasic_chanct < 7896b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten CHANS_PER_PORT * INTR_PORTS_PER_ASIC 7906b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten && subpriv->intr.asic < 0) { 791365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* setup the interrupt subdevice */ 7926b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic = asic; 7936b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.active = 0; 7946b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.stop_count = 0; 7956b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.first_chan = byte_no * 8; 7966b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.asic_chan = thisasic_chanct; 7976b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten subpriv->intr.num_asic_chans = 7986b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->n_chan - subpriv->intr.first_chan; 7996b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten dev->read_subdev = s; 8006b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->subdev_flags |= SDF_CMD_READ; 8016b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->cancel = pcmuio_cancel; 8026b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->do_cmd = pcmuio_cmd; 8036b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->do_cmdtest = pcmuio_cmdtest; 8046b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten s->len_chanlist = subpriv->intr.num_asic_chans; 8056b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8066b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten thisasic_chanct += CHANS_PER_PORT; 8076b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8086b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten spin_lock_init(&subpriv->intr.spinlock); 8096b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8106b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten chans_left -= s->n_chan; 8116b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8126b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (!chans_left) { 813365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten /* reset to our first asic, to do intr subdevs */ 814365c473e1da54e209aa8c01da2084c896f18fb20H Hartley Sweeten asic = 0; 8156b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten port = 0; 8166b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8176b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8186b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8196b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8206b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten init_asics(dev); /* clear out all the registers, basically */ 8216b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8226b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { 8236b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (irq[asic] 8246b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten && request_irq(irq[asic], interrupt_pcmuio, 825a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten IRQF_SHARED, board->name, dev)) { 8266b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int i; 8276b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten /* unroll the allocated irqs.. */ 8286b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (i = asic - 1; i >= 0; --i) { 8296b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten free_irq(irq[i], dev); 8306b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[i].irq = irq[i] = 0; 8316b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8326b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten irq[asic] = 0; 8336b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8346b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten devpriv->asics[asic].irq = irq[asic]; 8356b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8366b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8376b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (irq[0]) { 838f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "irq: %u\n", irq[0]); 839a28b59957d3ad01481c2ea87aca50cfdb85417f2H Hartley Sweeten if (irq[1] && board->num_asics == 2) 840f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "second ASIC irq: %u\n", 841f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott irq[1]); 8426b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } else { 843f41ad6675f2d5705a0fc1e210af8eb4a27dbacb4Ian Abbott dev_dbg(dev->class_dev, "(IRQ mode disabled)\n"); 8446b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8456b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8466b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8476b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten return 1; 8486b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 8496b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 850484ecc95d9cdfa8b2f7029e2f3409cf078aed4abH Hartley Sweetenstatic void pcmuio_detach(struct comedi_device *dev) 8516b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten{ 8529a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten struct pcmuio_private *devpriv = dev->private; 8536b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten int i; 8546b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 8556b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten for (i = 0; i < MAX_ASICS; ++i) { 8566b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (devpriv->asics[i].irq) 8576b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten free_irq(devpriv->asics[i].irq, dev); 8586b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten } 8596b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten if (devpriv && devpriv->sprivs) 8606b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten kfree(devpriv->sprivs); 861a32c6d0084992d3e58a93120c9ce9527e80c651eH Hartley Sweeten comedi_legacy_detach(dev); 8626b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten} 8636b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten 864294f930d98be86fb4f34302c718a49719650857fH Hartley Sweetenstatic struct comedi_driver pcmuio_driver = { 8656b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .driver_name = "pcmuio", 8666b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .module = THIS_MODULE, 8676b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .attach = pcmuio_attach, 8686b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .detach = pcmuio_detach, 8696b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .board_name = &pcmuio_boards[0].name, 8706b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .offset = sizeof(struct pcmuio_board), 8716b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten .num_names = ARRAY_SIZE(pcmuio_boards), 8726b19f9c6bee7afcd1e5dee9528333b2aa52de404H Hartley Sweeten}; 873294f930d98be86fb4f34302c718a49719650857fH Hartley Sweetenmodule_comedi_driver(pcmuio_driver); 87490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 87590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 87690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 87790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 878