1456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* 2456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef comedi/drivers/pcl711.c 3456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef hardware driver for PC-LabCard PCL-711 and AdSys ACL-8112 4456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef and compatibles 5456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 6456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef COMEDI - Linux Control and Measurement Device Interface 7456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Copyright (C) 1998 David A. Schleef <ds@schleef.org> 8456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Janne Jalkanen <jalkanen@cs.hut.fi> 9456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Eric Bunn <ebu@cs.hut.fi> 10456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 11456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef This program is free software; you can redistribute it and/or modify 12456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef it under the terms of the GNU General Public License as published by 13456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef the Free Software Foundation; either version 2 of the License, or 14456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef (at your option) any later version. 15456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 16456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef This program is distributed in the hope that it will be useful, 17456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 18456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef GNU General Public License for more details. 20456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 21456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef You should have received a copy of the GNU General Public License 22456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef along with this program; if not, write to the Free Software 23456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 25456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 26456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* 27456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefDriver: pcl711 28456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefDescription: Advantech PCL-711 and 711b, ADLink ACL-8112 29456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefAuthor: ds, Janne Jalkanen <jalkanen@cs.hut.fi>, Eric Bunn <ebu@cs.hut.fi> 30456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefStatus: mostly complete 31456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefDevices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b), 32456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg) 33456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 34456af2011ce33efa3bc037e793cad4a6f113619bDavid SchleefSince these boards do not have DMA or FIFOs, only immediate mode is 35456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleefsupported. 36456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 37456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef*/ 38456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 39456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* 40456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Dave Andruczyk <dave@tech.buffalostate.edu> also wrote a 41456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef driver for the PCL-711. I used a few ideas from his driver 42456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef here. His driver also has more comments, if you are 43456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef interested in understanding how this driver works. 44456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef http://tech.buffalostate.edu/~dave/driver/ 45456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 46456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef The ACL-8112 driver was hacked from the sources of the PCL-711 47456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef driver (the 744 chip used on the 8112 is almost the same as 48456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef the 711b chip, but it has more I/O channels) by 49456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Janne Jalkanen (jalkanen@cs.hut.fi) and 50456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef Erik Bunn (ebu@cs.hut.fi). Remerged with the PCL-711 driver 51456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef by ds. 52456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 53456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef [acl-8112] 54456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef This driver supports both TRIGNOW and TRIGCLK, 55456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef but does not yet support DMA transfers. It also supports 56456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef both high (HG) and low (DG) versions of the card, though 57456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef the HG version has been untested. 58456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 59456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 60456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 6125436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 62456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#include "../comedidev.h" 63456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 64456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#include <linux/ioport.h> 65456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#include <linux/delay.h> 66456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 67456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#include "8253.h" 68456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 69456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_SIZE 16 70456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 71456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_CTR0 0 72456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_CTR1 1 73456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_CTR2 2 74456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_CTRCTL 3 75456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_AD_LO 4 76456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DA0_LO 4 77456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_AD_HI 5 78456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DA0_HI 5 79456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DI_LO 6 80456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DA1_LO 6 81456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DI_HI 7 82456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DA1_HI 7 83456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_CLRINTR 8 84456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_GAIN 9 85456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_MUX 10 86456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_MODE 11 87456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_SOFTTRIG 12 88456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DO_LO 13 89456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DO_HI 14 90456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 919ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_pcl711b_ai = { 5, { 920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1.25), 950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.625), 960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.3125) 970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 98456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef}; 990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1009ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_acl8112hg_ai = { 12, { 1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 1020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.5), 1030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.05), 1040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.005), 1050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(1), 1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.1), 1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.01), 1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(10), 1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1), 1110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.1), 1120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.01) 1130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 114456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef}; 1150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1169ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_acl8112dg_ai = { 9, { 1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1.25), 1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.625), 1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(5), 1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(2.5), 1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(1.25), 1250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(10) 1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 127456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef}; 128456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 129456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* 130456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * flags 131456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 132456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 133456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_TIMEOUT 100 134456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define PCL711_DRDY 0x10 135456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 136456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleefstatic const int i8253_osc_base = 500; /* 2 Mhz */ 137456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 1386445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pembertonstruct pcl711_board { 1396445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pemberton 140456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef const char *name; 141456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int is_pcl711b; 142456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int is_8112; 143456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int is_dg; 144456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int n_ranges; 145456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int n_aichan; 146456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int n_aochan; 147456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int maxirq; 1489ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton const struct comedi_lrange *ai_range_type; 1496445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pemberton}; 1506445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pemberton 1516445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pembertonstatic const struct pcl711_board boardtypes[] = { 152456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef {"pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5}, 153456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef {"pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai}, 154456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef {"acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai}, 155456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef {"acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai}, 156456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef}; 157456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 1586445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pemberton#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl711_board)) 1596445296e9857ff4a3992454eda7ebb63f90cdca9Bill Pemberton#define this_board ((const struct pcl711_board *)dev->board_ptr) 160456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl711_attach(struct comedi_device *dev, 1620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 163da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_detach(struct comedi_device *dev); 164139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_pcl711 = { 16568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "pcl711", 16668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 16768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = pcl711_attach, 16868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = pcl711_detach, 16968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &boardtypes[0].name, 17068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .num_names = n_boardtypes, 17168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct pcl711_board), 172456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef}; 173456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 1747114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_pcl711_init_module(void) 1757114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 1767114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_pcl711); 1777114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 1787114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 1797114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_pcl711_cleanup_module(void) 1807114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 1817114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_pcl711); 1827114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 1837114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 1847114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_pcl711_init_module); 1857114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_pcl711_cleanup_module); 186456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 187e1c8638f3fb47c25b8dba170aadc8e29619fcd67Bill Pembertonstruct pcl711_private { 188e1c8638f3fb47c25b8dba170aadc8e29619fcd67Bill Pemberton 189456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int board; 190456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int adchan; 191456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int ntrig; 192456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int aip[8]; 193456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int mode; 194790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int ao_readback[2]; 195456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef unsigned int divisor1; 196456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef unsigned int divisor2; 197e1c8638f3fb47c25b8dba170aadc8e29619fcd67Bill Pemberton}; 198e1c8638f3fb47c25b8dba170aadc8e29619fcd67Bill Pemberton 199e1c8638f3fb47c25b8dba170aadc8e29619fcd67Bill Pemberton#define devpriv ((struct pcl711_private *)dev->private) 200456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 20170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pcl711_interrupt(int irq, void *d) 202456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 203456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int lo, hi; 204456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int data; 20571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = d; 20634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->subdevices + 0; 207456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 208456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!dev->attached) { 209456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef comedi_error(dev, "spurious interrupt"); 210456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return IRQ_HANDLED; 211456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 212456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 213456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef hi = inb(dev->iobase + PCL711_AD_HI); 214456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef lo = inb(dev->iobase + PCL711_AD_LO); 215456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_CLRINTR); 216456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 217456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef data = (hi << 8) | lo; 218456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 219456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* FIXME! Nothing else sets ntrig! */ 220456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!(--devpriv->ntrig)) { 221266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi if (this_board->is_8112) 222456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(1, dev->iobase + PCL711_MODE); 223266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi else 224456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_MODE); 225456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 226456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->async->events |= COMEDI_CB_EOA; 227456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 228456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef comedi_event(dev, s); 229456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return IRQ_HANDLED; 230456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 231456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 232da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pcl711_set_changain(struct comedi_device *dev, int chan) 233456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 234456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int chan_register; 235456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 236456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN); 237456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 238456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef chan_register = CR_CHAN(chan); 239456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 240456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (this_board->is_8112) { 241456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 242456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 243456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * Set the correct channel. The two channel banks are switched 244456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * using the mask value. 245266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi * NB: To use differential channels, you should use 246266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi * mask = 0x30, but I haven't written the support for this 247266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi * yet. /JJ 248456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 249456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 250266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi if (chan_register >= 8) 251456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef chan_register = 0x20 | (chan_register & 0x7); 252266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi else 253456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef chan_register |= 0x10; 254456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } else { 255456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(chan_register, dev->iobase + PCL711_MUX); 256456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 257456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 258456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 259da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, 2600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 261456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 262456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int i, n; 263456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int hi, lo; 264456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 265456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef pcl711_set_changain(dev, insn->chanspec); 266456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 267456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef for (n = 0; n < insn->n; n++) { 268456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 269266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi * Write the correct mode (software polling) and start polling 270266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi * by writing to the trigger register 271456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 272456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(1, dev->iobase + PCL711_MODE); 273456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 274266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi if (!this_board->is_8112) 275456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_SOFTTRIG); 276456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 277456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef i = PCL711_TIMEOUT; 278456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef while (--i) { 279456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef hi = inb(dev->iobase + PCL711_AD_HI); 280456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!(hi & PCL711_DRDY)) 281456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef goto ok; 2825f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 283456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 2848f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor); 285456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -ETIME; 286456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralok: 288456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef lo = inb(dev->iobase + PCL711_AD_LO); 289456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 290456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef data[n] = ((hi & 0xf) << 8) | lo; 291456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 292456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 293456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return n; 294456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 295456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl711_ai_cmdtest(struct comedi_device *dev, 2970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 298456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 299456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int tmp; 300456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int err = 0; 301456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 302456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* step 1 */ 303456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->start_src; 304456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->start_src &= TRIG_NOW; 305456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!cmd->start_src || tmp != cmd->start_src) 306456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 307456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 308456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->scan_begin_src; 309456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 310456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 311456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 312456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 313456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->convert_src; 314456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->convert_src &= TRIG_NOW; 315456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 316456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 317456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 318456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->scan_end_src; 319456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->scan_end_src &= TRIG_COUNT; 320456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 321456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 322456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 323456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->stop_src; 324456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 325456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 326456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 327456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 328456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (err) 329456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 1; 330456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 331456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* step 2 */ 332456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 333456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_src != TRIG_TIMER && 3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_EXT) 335456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 336456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 337456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 338456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 339456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (err) 340456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 2; 341456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 342456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* step 3 */ 343456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 344456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->start_arg != 0) { 345456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->start_arg = 0; 346456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 347456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 348456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_src == TRIG_EXT) { 349456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_arg != 0) { 350456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->scan_begin_arg = 0; 351456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 352456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 353456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } else { 354456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define MAX_SPEED 1000 355456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef#define TIMER_BASE 100 356456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_arg < MAX_SPEED) { 357456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->scan_begin_arg = MAX_SPEED; 358456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 359456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 360456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 361456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->convert_arg != 0) { 362456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->convert_arg = 0; 363456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 364456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 365456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_end_arg != cmd->chanlist_len) { 366456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->scan_end_arg = cmd->chanlist_len; 367456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 368456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 369456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->stop_src == TRIG_NONE) { 370456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->stop_arg != 0) { 371456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef cmd->stop_arg = 0; 372456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 373456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 374456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } else { 375456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* ignore */ 376456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 377456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 378456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (err) 379456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 3; 380456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 381456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* step 4 */ 382456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 383456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 384456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef tmp = cmd->scan_begin_arg; 385456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef i8253_cascade_ns_to_timer_2div(TIMER_BASE, 3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &devpriv->divisor1, 3870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &devpriv->divisor2, 3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &cmd->scan_begin_arg, 3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 390456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (tmp != cmd->scan_begin_arg) 391456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef err++; 392456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 393456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 394456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (err) 395456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 4; 396456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 397456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 0; 398456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 399456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 400da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 401456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 402456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int timer1, timer2; 403ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 404456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 405456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef pcl711_set_changain(dev, cmd->chanlist[0]); 406456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 407456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 408456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 409456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * Set timers 410456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * timer chip is an 8253, with timers 1 and 2 411456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * cascaded 412456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * 0x74 = Select Counter 1 | LSB/MSB | Mode=2 | Binary 413456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * Mode 2 = Rate generator 414456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * 415456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * 0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary 416456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 417456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 41848b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott timer1 = timer2 = 0; 419456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2, 4200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &cmd->scan_begin_arg, 4210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral TRIG_ROUND_NEAREST); 422456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 423456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0x74, dev->iobase + PCL711_CTRCTL); 424456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(timer1 & 0xff, dev->iobase + PCL711_CTR1); 425456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb((timer1 >> 8) & 0xff, dev->iobase + PCL711_CTR1); 426456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0xb4, dev->iobase + PCL711_CTRCTL); 427456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(timer2 & 0xff, dev->iobase + PCL711_CTR2); 428456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb((timer2 >> 8) & 0xff, dev->iobase + PCL711_CTR2); 429456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 430456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* clear pending interrupts (just in case) */ 431456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_CLRINTR); 432456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 433456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 434456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef * Set mode to IRQ transfer 435456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 436456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(devpriv->mode | 6, dev->iobase + PCL711_MODE); 437456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } else { 438456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* external trigger */ 439456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(devpriv->mode | 3, dev->iobase + PCL711_MODE); 440456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 441456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 442456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 0; 443456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 444456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 445456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* 446456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef analog output 447456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef*/ 448da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, 4490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 450456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 451456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int n; 452456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int chan = CR_CHAN(insn->chanspec); 453456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 454456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef for (n = 0; n < insn->n; n++) { 455456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb((data[n] & 0xff), 4560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + (chan ? PCL711_DA1_LO : PCL711_DA0_LO)); 457456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb((data[n] >> 8), 4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + (chan ? PCL711_DA1_HI : PCL711_DA0_HI)); 459456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 460456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef devpriv->ao_readback[chan] = data[n]; 461456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 462456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 463456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return n; 464456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 465456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 4660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl711_ao_insn_read(struct comedi_device *dev, 4670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 469456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 470456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int n; 471456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int chan = CR_CHAN(insn->chanspec); 472456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 473266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi for (n = 0; n < insn->n; n++) 474456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef data[n] = devpriv->ao_readback[chan]; 475456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 476456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return n; 477456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 478456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 479456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 480456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* Digital port read - Untested on 8112 */ 4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl711_di_insn_bits(struct comedi_device *dev, 4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 484456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 485456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (insn->n != 2) 486456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -EINVAL; 487456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 488456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef data[1] = inb(dev->iobase + PCL711_DI_LO) | 4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (inb(dev->iobase + PCL711_DI_HI) << 8); 490456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 491456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 2; 492456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 493456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 494456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* Digital port write - Untested on 8112 */ 4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pcl711_do_insn_bits(struct comedi_device *dev, 4960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 498456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 499456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (insn->n != 2) 500456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -EINVAL; 501456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 502456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (data[0]) { 503456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->state &= ~data[0]; 504456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->state |= data[0] & data[1]; 505456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 506456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (data[0] & 0x00ff) 507456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(s->state & 0xff, dev->iobase + PCL711_DO_LO); 508456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (data[0] & 0xff00) 509456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb((s->state >> 8), dev->iobase + PCL711_DO_HI); 510456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 511456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef data[1] = s->state; 512456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 513456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 2; 514456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 515456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 516456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* Free any resources that we have claimed */ 517da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_detach(struct comedi_device *dev) 518456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 5198f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_INFO "comedi%d: pcl711: remove\n", dev->minor); 520456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 521456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (dev->irq) 5225f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(dev->irq, dev); 523456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 524456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (dev->iobase) 525456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef release_region(dev->iobase, PCL711_SIZE); 526456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 527456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 0; 528456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 529456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 530456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef/* Initialization */ 531da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) 532456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef{ 533456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef int ret; 534456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef unsigned long iobase; 535456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef unsigned int irq; 53634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 537456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 538456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* claim our I/O space */ 539456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 540456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef iobase = it->options[0]; 5418f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_INFO "comedi%d: pcl711: 0x%04lx ", dev->minor, iobase); 542456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (!request_region(iobase, PCL711_SIZE, "pcl711")) { 543456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef printk("I/O port conflict\n"); 544456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -EIO; 545456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 546456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef dev->iobase = iobase; 547456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 548456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* there should be a sanity check here */ 549456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 550456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* set up some name stuff */ 551456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef dev->board_name = this_board->name; 552456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 553456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* grab our IRQ */ 554456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef irq = it->options[1]; 555456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (irq > this_board->maxirq) { 5568f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_ERR "irq out of range\n"); 557456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -EINVAL; 558456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 559456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (irq) { 5605f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman if (request_irq(irq, pcl711_interrupt, 0, "pcl711", dev)) { 5618f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_ERR "unable to allocate irq %u\n", irq); 562456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return -EINVAL; 563456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } else { 5648f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_INFO "( irq = %u )\n", irq); 565456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 566456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 567456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef dev->irq = irq; 568456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 569c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_subdevices(dev, 4); 570c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 571456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return ret; 572c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 573c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_private(dev, sizeof(struct pcl711_private)); 574c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 575456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return ret; 576456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 577456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s = dev->subdevices + 0; 578456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* AI subdevice */ 579456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->type = COMEDI_SUBD_AI; 580456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->subdev_flags = SDF_READABLE | SDF_GROUND; 581456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->n_chan = this_board->n_aichan; 582456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->maxdata = 0xfff; 583456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->len_chanlist = 1; 584456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->range_table = this_board->ai_range_type; 585456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->insn_read = pcl711_ai_insn; 586456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef if (irq) { 587456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef dev->read_subdev = s; 588456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->subdev_flags |= SDF_CMD_READ; 589456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->do_cmdtest = pcl711_ai_cmdtest; 590456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->do_cmd = pcl711_ai_cmd; 591456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef } 592456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 593456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s++; 594456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* AO subdevice */ 595456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->type = COMEDI_SUBD_AO; 596456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->subdev_flags = SDF_WRITABLE; 597456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->n_chan = this_board->n_aochan; 598456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->maxdata = 0xfff; 599456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->len_chanlist = 1; 600456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->range_table = &range_bipolar5; 601456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->insn_write = pcl711_ao_insn; 602456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->insn_read = pcl711_ao_insn_read; 603456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 604456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s++; 605456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 16-bit digital input */ 606456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->type = COMEDI_SUBD_DI; 607456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->subdev_flags = SDF_READABLE; 608456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->n_chan = 16; 609456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->maxdata = 1; 610456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->len_chanlist = 16; 611456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->range_table = &range_digital; 612456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->insn_bits = pcl711_di_insn_bits; 613456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 614456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s++; 615456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 16-bit digital out */ 616456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->type = COMEDI_SUBD_DO; 617456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->subdev_flags = SDF_WRITABLE; 618456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->n_chan = 16; 619456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->maxdata = 1; 620456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->len_chanlist = 16; 621456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->range_table = &range_digital; 622456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->state = 0; 623456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef s->insn_bits = pcl711_do_insn_bits; 624456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 625456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* 626456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef this is the "base value" for the mode register, which is 627456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef used for the irq on the PCL711 628456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef */ 629266bfbdd3eb7f080612977f22055c82b951b179eBenjamin Adolphi if (this_board->is_pcl711b) 630456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef devpriv->mode = (dev->irq << 4); 631456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 632456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef /* clear DAC */ 633456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_DA0_LO); 634456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_DA0_HI); 635456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_DA1_LO); 636456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef outb(0, dev->iobase + PCL711_DA1_HI); 637456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 6388f4e80af3aa509902bd2319c3b5512580f64868fGustavo Silva printk(KERN_INFO "\n"); 639456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef 640456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef return 0; 641456af2011ce33efa3bc037e793cad4a6f113619bDavid Schleef} 64290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 64390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 64490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 64590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 646