cb_das16_cs.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
1f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 2f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef comedi/drivers/das16cs.c 3f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef Driver for Computer Boards PC-CARD DAS16/16. 4f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 5f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef COMEDI - Linux Control and Measurement Device Interface 6f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org> 7f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 8f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef This program is free software; you can redistribute it and/or modify 9f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef it under the terms of the GNU General Public License as published by 10f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef the Free Software Foundation; either version 2 of the License, or 11f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef (at your option) any later version. 12f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 13f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef This program is distributed in the hope that it will be useful, 14f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 15f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef GNU General Public License for more details. 17f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 18f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef You should have received a copy of the GNU General Public License 19f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef along with this program; if not, write to the Free Software 20f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 22f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 23f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 24f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDriver: cb_das16_cs 25f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDescription: Computer Boards PC-CARD DAS16/16 26f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefDevices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO 27f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefAuthor: ds 28f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefUpdated: Mon, 04 Nov 2002 20:04:21 -0800 29f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefStatus: experimental 30f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 31f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 32f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 33f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 3425436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 35f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "../comedidev.h" 36f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/delay.h> 37f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <linux/pci.h> 38f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 39f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs_types.h> 40f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cs.h> 41f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/cistpl.h> 42f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include <pcmcia/ds.h> 43f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 44f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#include "8253.h" 45f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 46f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_SIZE 18 47f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 48f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_ADC_DATA 0 49f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO_MUX 2 50f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC1 4 51f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_MISC2 6 52f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR0 8 53f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR1 10 54f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR2 12 55f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_CTR_CONTROL 14 56f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DAS16CS_DIO 16 57f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 583281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstruct das16cs_board { 59f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef const char *name; 60f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int device_id; 61f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int n_ao_chans; 623281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton}; 633281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pembertonstatic const struct das16cs_board das16cs_boards[] = { 64f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef { 650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = 0x0000, /* unknown */ 660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "PC-CARD DAS16/16", 670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .n_ao_chans = 0, 680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 69f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef { 700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = 0x0039, 710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "PC-CARD DAS16/16-AO", 720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .n_ao_chans = 2, 730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 74f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef { 750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = 0x4009, 760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "PCM-DAS16s/16", 770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .n_ao_chans = 0, 780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 79f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}; 80f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 81f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0])) 823281a63d0b1eecbb21848c3e123c2fc0cd1d4a80Bill Pemberton#define thisboard ((const struct das16cs_board *)dev->board_ptr) 83f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 84bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pembertonstruct das16cs_private { 85f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef struct pcmcia_device *link; 86f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 87790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int ao_readback[2]; 88f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned short status1; 89f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned short status2; 90bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton}; 91bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton#define devpriv ((struct das16cs_private *)dev->private) 92f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev, 940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 95da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev); 96139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das16cs = { 9768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "cb_das16_cs", 9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 9968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = das16cs_attach, 10068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = das16cs_detach, 101f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}; 102f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 103f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device *cur_dev = NULL; 104f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1059ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange das16cs_ai_range = { 4, { 1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral RANGE(-10, 10), 1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral RANGE(-5, 5), 1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral RANGE(-2.5, 2.5), 1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral RANGE(-1.25, 1.25), 1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 111f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}; 112f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 11370265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d); 1140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev, 1150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmd(struct comedi_device *dev, 1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s); 1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev, 1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_cmd *cmd); 1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev, 1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev, 1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev, 1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev, 1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data); 1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev, 1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 1380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data); 1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev, 1400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data); 143814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton 144814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int get_prodid(struct comedi_device *dev, struct pcmcia_device *link) 145f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 146f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple_t tuple; 147f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef u_short buf[128]; 148f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int prodid = 0; 149f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 150f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleData = (cisdata_t *) buf; 151f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleOffset = 0; 152f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleDataMax = 255; 153f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.DesiredTuple = CISTPL_MANFID; 154f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.Attributes = TUPLE_RETURN_COMMON; 155f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if ((pcmcia_get_first_tuple(link, &tuple) == 0) && 1560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (pcmcia_get_tuple_data(link, &tuple) == 0)) { 157f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef prodid = le16_to_cpu(buf[1]); 158f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 159f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 160f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return prodid; 161f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 162f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic const struct das16cs_board *das16cs_probe(struct comedi_device *dev, 1640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct pcmcia_device *link) 165f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 166f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int id; 167f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int i; 168f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 169f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef id = get_prodid(dev, link); 170f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 171f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (i = 0; i < n_boards; i++) { 172f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (das16cs_boards[i].device_id == id) { 173f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return das16cs_boards + i; 174f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 175f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 176f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 177f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("unknown board!\n"); 178f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 179f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return NULL; 180f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 181f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_attach(struct comedi_device *dev, 1830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it) 184f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 185f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef struct pcmcia_device *link; 18634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 187f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int ret; 188f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int i; 189f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 190f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("comedi%d: cb_das16_cs: ", dev->minor); 191f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 192f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link = cur_dev; /* XXX hack */ 193f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!link) 194f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EIO; 195f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 196f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->iobase = link->io.BasePort1; 197f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("I/O base=0x%04lx ", dev->iobase); 198f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 199f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("fingerprint:\n"); 200f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (i = 0; i < 48; i += 2) { 201f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("%04x ", inw(dev->iobase + i)); 202f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 203f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("\n"); 204f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 2055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman ret = request_irq(link->irq.AssignedIRQ, das16cs_interrupt, 2065f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman IRQF_SHARED, "cb_das16_cs", dev); 207f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (ret < 0) { 208f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return ret; 209f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 210f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->irq = link->irq.AssignedIRQ; 211f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("irq=%u ", dev->irq); 212f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 213f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->board_ptr = das16cs_probe(dev, link); 214f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!dev->board_ptr) 215f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EIO; 216f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 217f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->board_name = thisboard->name; 218f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 219bfae362ab6a9737e67a07ff82632a16181bb2d3cBill Pemberton if (alloc_private(dev, sizeof(struct das16cs_private)) < 0) 220f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -ENOMEM; 221f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 222f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (alloc_subdevices(dev, 4) < 0) 223f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -ENOMEM; 224f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 225f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s = dev->subdevices + 0; 226f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->read_subdev = s; 227f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* analog input subdevice */ 228f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_AI; 229f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; 230f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->n_chan = 16; 231f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->maxdata = 0xffff; 232f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->range_table = &das16cs_ai_range; 233f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->len_chanlist = 16; 234f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_read = das16cs_ai_rinsn; 235f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->do_cmd = das16cs_ai_cmd; 236f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->do_cmdtest = das16cs_ai_cmdtest; 237f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 238f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s = dev->subdevices + 1; 239f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* analog output subdevice */ 240f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (thisboard->n_ao_chans) { 241f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_AO; 242f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->subdev_flags = SDF_WRITABLE; 243f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->n_chan = thisboard->n_ao_chans; 244f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->maxdata = 0xffff; 245f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->range_table = &range_bipolar10; 246f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_write = &das16cs_ao_winsn; 247f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_read = &das16cs_ao_rinsn; 248f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 249f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 250f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s = dev->subdevices + 2; 251f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* digital i/o subdevice */ 252f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (1) { 253f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_DIO; 254f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 255f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->n_chan = 8; 256f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->maxdata = 1; 257f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->range_table = &range_digital; 258f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_bits = das16cs_dio_insn_bits; 259f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_config = das16cs_dio_insn_config; 260f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } else { 261f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_UNUSED; 262f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 263f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 264f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s = dev->subdevices + 3; 265f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* timer subdevice */ 266f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (0) { 267f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_TIMER; 268f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 269f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->n_chan = 1; 270f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->maxdata = 0xff; 271f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->range_table = &range_unknown; 272f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_read = das16cs_timer_insn_read; 273f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->insn_config = das16cs_timer_insn_config; 274f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } else { 275f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->type = COMEDI_SUBD_UNUSED; 276f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 277f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 278f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("attached\n"); 279f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 280f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 1; 281f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 282f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 283da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_detach(struct comedi_device *dev) 284f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 285f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("comedi%d: das16cs: remove\n", dev->minor); 286f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 287f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (dev->irq) { 2885f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(dev->irq, dev); 289f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 290f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 291f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 292f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 293f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 29470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das16cs_interrupt(int irq, void *d) 295f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 2962696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* struct comedi_device *dev = d; */ 297f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return IRQ_HANDLED; 298f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 299f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 300f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 301f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered" 302f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * mode. 303f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_rinsn(struct comedi_device *dev, 3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 307f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 308f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int i; 309f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int to; 310f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int aref; 311f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int range; 312f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int chan; 313f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 }; 314f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 315f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef chan = CR_CHAN(insn->chanspec); 316f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef aref = CR_AREF(insn->chanspec); 317f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef range = CR_RANGE(insn->chanspec); 318f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 319f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(chan, dev->iobase + 2); 320f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 321f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status1 &= ~0xf320; 322f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020; 323f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(devpriv->status1, dev->iobase + 4); 324f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 325f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status2 &= ~0xff00; 326f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status2 |= range_bits[range]; 327f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(devpriv->status2, dev->iobase + 6); 328f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 329f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (i = 0; i < insn->n; i++) { 330f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(0, dev->iobase); 331f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 332f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define TIMEOUT 1000 333f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (to = 0; to < TIMEOUT; to++) { 334f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (inw(dev->iobase + 4) & 0x0080) 335f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 336f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 337f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (to == TIMEOUT) { 338f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("cb_das16_cs: ai timeout\n"); 339f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -ETIME; 340f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 341f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef data[i] = (unsigned short)inw(dev->iobase + 0); 342f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 343f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 344f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return i; 345f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 346f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 347da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 348f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 349f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EINVAL; 350f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 351f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ai_cmdtest(struct comedi_device *dev, 3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_cmd *cmd) 355f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 356f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int err = 0; 357f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int tmp; 358f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 359f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* cmdtest tests a particular command to see if it is valid. 360f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Using the cmdtest ioctl, a user can create a valid cmd 361f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * and then have it executes by the cmd ioctl. 362f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * 363f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * cmdtest returns 1,2,3,4 or 0, depending on which tests 364f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * the command passes. */ 365f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 366f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* step 1: make sure trigger sources are trivially valid */ 367f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 368f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->start_src; 369f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->start_src &= TRIG_NOW; 370f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!cmd->start_src || tmp != cmd->start_src) 371f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 372f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 373f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->scan_begin_src; 374f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 375f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 376f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 377f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 378f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->convert_src; 379f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 380f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 381f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 382f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 383f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->scan_end_src; 384f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_end_src &= TRIG_COUNT; 385f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 386f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 387f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 388f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->stop_src; 389f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 390f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 391f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 392f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 393f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (err) 394f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 1; 395f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 396f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* step 2: make sure trigger sources are unique and mutually compatible */ 397f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 398f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* note that mutual compatiblity is not an issue here */ 399f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_src != TRIG_TIMER && 4000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_EXT) 401f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 402f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 403f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 404f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 405f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 406f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 407f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (err) 408f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 2; 409f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 410f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* step 3: make sure arguments are trivially compatible */ 411f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 412f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->start_arg != 0) { 413f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->start_arg = 0; 414f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 415f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 416f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MAX_SPEED 10000 /* in nanoseconds */ 417f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define MIN_SPEED 1000000000 /* in nanoseconds */ 418f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 419f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 420f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_arg < MAX_SPEED) { 421f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_begin_arg = MAX_SPEED; 422f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 423f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 424f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_arg > MIN_SPEED) { 425f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_begin_arg = MIN_SPEED; 426f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 427f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 428f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } else { 429f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* external trigger */ 430f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* should be level/edge, hi/lo specification here */ 431f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* should specify multiple external triggers */ 432f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_arg > 9) { 433f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_begin_arg = 9; 434f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 435f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 436f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 437f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_src == TRIG_TIMER) { 438f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_arg < MAX_SPEED) { 439f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->convert_arg = MAX_SPEED; 440f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 441f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 442f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_arg > MIN_SPEED) { 443f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->convert_arg = MIN_SPEED; 444f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 445f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 446f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } else { 447f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* external trigger */ 448f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* see above */ 449f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_arg > 9) { 450f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->convert_arg = 9; 451f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 452f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 453f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 454f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 455f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_end_arg != cmd->chanlist_len) { 456f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_end_arg = cmd->chanlist_len; 457f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 458f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 459f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->stop_src == TRIG_COUNT) { 460f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->stop_arg > 0x00ffffff) { 461f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->stop_arg = 0x00ffffff; 462f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 463f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 464f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } else { 465f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* TRIG_NONE */ 466f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->stop_arg != 0) { 467f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->stop_arg = 0; 468f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 469f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 470f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 471f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 472f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (err) 473f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 3; 474f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 475f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* step 4: fix up any arguments */ 476f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 477f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 478f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned int div1, div2; 479f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 480f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->scan_begin_arg; 481f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef i8253_cascade_ns_to_timer(100, &div1, &div2, 4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &cmd->scan_begin_arg, 4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 484f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (tmp != cmd->scan_begin_arg) 485f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 486f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 487f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->convert_src == TRIG_TIMER) { 488f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned int div1, div2; 489f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 490f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tmp = cmd->convert_arg; 491f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef i8253_cascade_ns_to_timer(100, &div1, &div2, 4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &cmd->scan_begin_arg, 4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 494f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (tmp != cmd->convert_arg) 495f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 496f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER && 4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_arg < 4980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->scan_end_arg) { 499f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cmd->scan_begin_arg = 5000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->scan_end_arg; 501f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef err++; 502f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 503f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 504f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 505f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (err) 506f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 4; 507f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 508f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 509f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 510f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 5110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_winsn(struct comedi_device *dev, 5120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 514f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 515f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int i; 516f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int chan = CR_CHAN(insn->chanspec); 517f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned short status1; 518f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef unsigned short d; 519f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int bit; 520f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 521f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (i = 0; i < insn->n; i++) { 522f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->ao_readback[chan] = data[i]; 523f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef d = data[i]; 524f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 525f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(devpriv->status1, dev->iobase + 4); 5265f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 527f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 528f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef status1 = devpriv->status1 & ~0xf; 529f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (chan) 530f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef status1 |= 0x0001; 531f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef else 532f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef status1 |= 0x0008; 533f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 534f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* printk("0x%04x\n",status1);*/ 535f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(status1, dev->iobase + 4); 5365f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 537f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 538f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (bit = 15; bit >= 0; bit--) { 539f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int b = (d >> bit) & 0x1; 540f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef b <<= 1; 541f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* printk("0x%04x\n",status1 | b | 0x0000);*/ 542f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(status1 | b | 0x0000, dev->iobase + 4); 5435f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 544f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* printk("0x%04x\n",status1 | b | 0x0004);*/ 545f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(status1 | b | 0x0004, dev->iobase + 4); 5465f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 547f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 548f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* make high both DAC0CS and DAC1CS to load 549f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef new data and update analog output*/ 550f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(status1 | 0x9, dev->iobase + 4); 551f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 552f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 553f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return i; 554f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 555f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 556f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* AO subdevices should have a read insn as well as a write insn. 557f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * Usually this means copying a value stored in devpriv. */ 5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_ao_rinsn(struct comedi_device *dev, 5590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 561f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 562f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int i; 563f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int chan = CR_CHAN(insn->chanspec); 564f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 565f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef for (i = 0; i < insn->n; i++) 566f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef data[i] = devpriv->ao_readback[chan]; 567f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 568f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return i; 569f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 570f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 571f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* DIO devices are slightly special. Although it is possible to 572f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * implement the insn_read/insn_write interface, it is much more 573f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * useful to applications if you implement the insn_bits interface. 574f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * This allows packed reading/writing of the DIO channels. The 575f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * comedi core can convert between insn_bits and insn_read/write */ 5760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_bits(struct comedi_device *dev, 5770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 579f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 580f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (insn->n != 2) 581f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EINVAL; 582f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 583f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (data[0]) { 584f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->state &= ~data[0]; 585f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->state |= data[0] & data[1]; 586f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 587f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(s->state, dev->iobase + 16); 588f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 589f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 590f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* on return, data[1] contains the value of the digital 591f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef * input and output lines. */ 592f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef data[1] = inw(dev->iobase + 16); 593f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 594f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 2; 595f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 596f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 5970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_dio_insn_config(struct comedi_device *dev, 5980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 600f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 601f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int chan = CR_CHAN(insn->chanspec); 602f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int bits; 603f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 604f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (chan < 4) 605f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef bits = 0x0f; 606f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef else 607f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef bits = 0xf0; 608f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 609f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef switch (data[0]) { 610f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef case INSN_CONFIG_DIO_OUTPUT: 611f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->io_bits |= bits; 612f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 613f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef case INSN_CONFIG_DIO_INPUT: 614f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef s->io_bits &= bits; 615f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 616f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef case INSN_CONFIG_DIO_QUERY: 617f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef data[1] = 6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 619f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return insn->n; 620f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 621f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef default: 622f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EINVAL; 623f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 624f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 625f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 626f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status2 &= ~0x00c0; 627f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0; 628f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0; 629f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 630f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef outw(devpriv->status2, dev->iobase + 6); 631f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 632f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return insn->n; 633f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 634f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 6350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_read(struct comedi_device *dev, 6360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 6370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 638f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 639f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EINVAL; 640f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 641f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 6420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das16cs_timer_insn_config(struct comedi_device *dev, 6430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 6440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 6450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data) 646f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 647f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -EINVAL; 648f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 649f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 650f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* PCMCIA stuff */ 651f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 652f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================== 653f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 654f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef The following pcmcia code for the pcm-das08 is adapted from the 655f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dummy_cs.c driver of the Linux PCMCIA Card Services package. 656f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 657f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef The initial developer of the original code is David A. Hinds 658f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 659f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 660f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 661f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/ 662f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 663f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 664f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If 665f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef you do not define PCMCIA_DEBUG at all, all the debug code will be 666f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef left out. If you compile with PCMCIA_DEBUG=0, the debug code will 667f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef be present but disabled -- but it can then be enabled for specific 668f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef modules at load time with a 'pc_debug=#' option to insmod. 669f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 670f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) 671f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 672f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#ifdef PCMCIA_DEBUG 673f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int pc_debug = PCMCIA_DEBUG; 674f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefmodule_param(pc_debug, int, 0644); 675f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) 676f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic char *version = 6770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; 678f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else 679f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#define DEBUG(n, args...) 680f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#endif 681f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 682f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/ 683f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 684f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link); 685f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link); 686f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev); 687f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *p_dev); 688f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 689f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 690f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef The attach() and detach() entry points are used to create and destroy 691f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef "instances" of the driver, where each instance represents everything 692f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef needed to manage one actual PCMCIA card. 693f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 694f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 695f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *); 696f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *); 697f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 698f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 699f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef You'll also need to prototype all the functions that will actually 700f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef be used to talk to your device. See 'memory_cs' for a good example 701f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef of a fully self-sufficient driver; the other drivers rely more or 702f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef less on other parts of the kernel. 703f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 704f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 705f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* 706f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef The dev_info variable is the "key" that is used to match up this 707f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef device driver with appropriate cards, through the card configuration 708f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef database. 709f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 710f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 711f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic dev_info_t dev_info = "cb_das16_cs"; 712f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 713d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pembertonstruct local_info_t { 714f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef struct pcmcia_device *link; 715f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev_node_t node; 716f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int stop; 717f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef struct bus_operations *bus; 718d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton}; 719f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 720f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================== 721f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 722f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef das16cs_pcmcia_attach() creates an "instance" of the driver, allocating 723f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef local data structures for one device. The device is registered 724f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef with Card Services. 725f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 726f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef The dev_link structure is initialized, but we don't actually 727f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef configure the card at this point -- we wait until we receive a 728f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef card insertion event. 729f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 730f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef======================================================================*/ 731f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 732f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_attach(struct pcmcia_device *link) 733f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 734d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton struct local_info_t *local; 735f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 736f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "das16cs_pcmcia_attach()\n"); 737f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 738f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Allocate space for private device-specific data */ 739d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); 740f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!local) 741f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return -ENOMEM; 742f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef local->link = link; 743f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->priv = local; 744f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 745f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Initialize the pcmcia_device structure */ 746f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Interrupt setup */ 747f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 748f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->irq.IRQInfo1 = IRQ_LEVEL_ID; 749f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->irq.Handler = NULL; 750f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 751f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.Attributes = 0; 752f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.IntType = INT_MEMORY_AND_IO; 753f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 754f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cur_dev = link; 755f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 756f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef das16cs_pcmcia_config(link); 757f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 758f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 759f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_attach */ 760f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 761f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_detach(struct pcmcia_device *link) 762f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 763f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link); 764f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 765f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->dev_node) { 7660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((struct local_info_t *)link->priv)->stop = 1; 767f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef das16cs_pcmcia_release(link); 768f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 769d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton /* This points to the parent struct local_info_t struct */ 770f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->priv) 771f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef kfree(link->priv); 772f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_detach */ 773f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 774f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_config(struct pcmcia_device *link) 775f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 776d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton struct local_info_t *dev = link->priv; 777f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple_t tuple; 778f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cisparse_t parse; 779f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int last_fn, last_ret; 780f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef u_char buf[64]; 781f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cistpl_cftable_entry_t dflt = { 0 }; 782f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 783f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link); 784f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 785f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* 786f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef This reads the card's CONFIG tuple to find its configuration 787f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef registers. 788f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 789f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.DesiredTuple = CISTPL_CONFIG; 790f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.Attributes = 0; 791f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleData = buf; 792f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleDataMax = sizeof(buf); 793f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.TupleOffset = 0; 794c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 795f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = GetFirstTuple; 796c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_get_first_tuple(link, &tuple); 797c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret != 0) 798f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 799c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 800f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = GetTupleData; 801c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_get_tuple_data(link, &tuple); 802c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret != 0) 803f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 804c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 805f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = ParseTuple; 806c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_parse_tuple(&tuple, &parse); 807c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret != 0) 808f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 809c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 810f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.ConfigBase = parse.config.base; 811f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.Present = parse.config.rmask[0]; 812f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 813f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* 814f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef In this loop, we scan the CIS for configuration table entries, 815f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef each of which describes a valid card configuration, including 816f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef voltage, IO window, memory window, and interrupt settings. 817f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 818f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef We make no assumptions about the card to be configured: we use 819f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef just the information available in the CIS. In an ideal world, 820f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef this would work for any PCMCIA card, but it requires a complete 821f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef and accurate CIS. In practice, a driver usually "knows" most of 822f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef these things without consulting the CIS, and most client drivers 823f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef will only use the CIS to fill in implementation-defined details. 824f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 825f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 826f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = GetFirstTuple; 827c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 828c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_get_first_tuple(link, &tuple); 829c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret) 830f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 831c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 832f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef while (1) { 833f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 834f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (pcmcia_get_tuple_data(link, &tuple)) 835f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto next_entry; 836de15d7fcd6452894e82657fb44b7b93c2afe97a4Ian Abbott if (pcmcia_parse_tuple(&tuple, &parse)) 837f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto next_entry; 838f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 839f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 840f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dflt = *cfg; 841f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cfg->index == 0) 842f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto next_entry; 843f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.ConfigIndex = cfg->index; 844f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 845f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Does this card need audio output? */ 846f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { 847f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.Attributes |= CONF_ENABLE_SPKR; 848f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.Status = CCSR_AUDIO_ENA; 849f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 850f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef*/ 851f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Do we need to allocate an interrupt? */ 852f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 853f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->conf.Attributes |= CONF_ENABLE_IRQ; 854f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 855f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* IO window settings */ 856f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.NumPorts1 = link->io.NumPorts2 = 0; 857f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 858f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 859f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 860f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!(io->flags & CISTPL_IO_8BIT)) 861f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 862f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (!(io->flags & CISTPL_IO_16BIT)) 863f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 864f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 865f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.BasePort1 = io->win[0].base; 866f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.NumPorts1 = io->win[0].len; 867f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (io->nwin > 1) { 868f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.Attributes2 = link->io.Attributes1; 869f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.BasePort2 = io->win[1].base; 870f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->io.NumPorts2 = io->win[1].len; 871f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 872f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* This reserves IO space but doesn't actually enable it */ 873f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (pcmcia_request_io(link, &link->io)) 874f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto next_entry; 875f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 876f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 877f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* If we got this far, we're cool! */ 878f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef break; 879f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 8800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralnext_entry: 881f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = GetNextTuple; 882c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 883c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_get_next_tuple(link, &tuple); 884c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret) 885f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 886f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 887f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 888f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* 889f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef Allocate an interrupt line. Note that this does not assign a 890f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef handler to the interrupt, unless the 'Handler' member of the 891f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef irq structure is initialized. 892f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 893f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->conf.Attributes & CONF_ENABLE_IRQ) { 894f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = RequestIRQ; 895c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 896c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_request_irq(link, &link->irq); 897c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret) 898f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 899f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef } 900f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* 901f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef This actually configures the PCMCIA socket -- setting up 902f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef the I/O windows and the interrupt mapping, and putting the 903f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef card and host interface into "Memory and IO" mode. 904f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 905f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef last_fn = RequestConfiguration; 906c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton last_ret = pcmcia_request_configuration(link, &link->conf); 907c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (last_ret) 908f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef goto cs_failed; 909f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 910f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* 911f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef At this point, the dev_node_t structure(s) need to be 912f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef initialized and arranged in a linked list at link->dev. 913f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef */ 914f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef sprintf(dev->node.dev_name, "cb_das16_cs"); 915f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef dev->node.major = dev->node.minor = 0; 916f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef link->dev_node = &dev->node; 917f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 918f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Finally, report what we've done */ 919f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk(KERN_INFO "%s: index 0x%02x", 9200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->node.dev_name, link->conf.ConfigIndex); 921f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->conf.Attributes & CONF_ENABLE_IRQ) 922f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk(", irq %u", link->irq.AssignedIRQ); 923f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->io.NumPorts1) 924f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk(", io 0x%04x-0x%04x", link->io.BasePort1, 9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral link->io.BasePort1 + link->io.NumPorts1 - 1); 926f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (link->io.NumPorts2) 927f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk(" & 0x%04x-0x%04x", link->io.BasePort2, 9280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral link->io.BasePort2 + link->io.NumPorts2 - 1); 929f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef printk("\n"); 930f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 931f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return; 932f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 9330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralcs_failed: 934f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef cs_error(link, last_fn, last_ret); 935f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef das16cs_pcmcia_release(link); 936f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_config */ 937f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 938f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void das16cs_pcmcia_release(struct pcmcia_device *link) 939f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 940f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link); 941f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef pcmcia_disable_device(link); 942f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_release */ 943f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 944f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_suspend(struct pcmcia_device *link) 945f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 946d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton struct local_info_t *local = link->priv; 947f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 948f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef /* Mark the device as stopped, to block IO until later */ 949f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef local->stop = 1; 950f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 951f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 952f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_suspend */ 953f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 954f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int das16cs_pcmcia_resume(struct pcmcia_device *link) 955f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 956d2755d518620bfa3ab6d25aed4048a2d35868e3dBill Pemberton struct local_info_t *local = link->priv; 957f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 958f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef local->stop = 0; 959f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 960f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} /* das16cs_pcmcia_resume */ 961f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 962f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef/*====================================================================*/ 963f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 964f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic struct pcmcia_device_id das16cs_id_table[] = { 965f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039), 966f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009), 967f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef PCMCIA_DEVICE_NULL 968f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}; 969f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 970f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefMODULE_DEVICE_TABLE(pcmcia, das16cs_id_table); 971f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 972f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstruct pcmcia_driver das16cs_driver = { 973f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .probe = das16cs_pcmcia_attach, 974f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .remove = das16cs_pcmcia_detach, 975f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .suspend = das16cs_pcmcia_suspend, 976f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .resume = das16cs_pcmcia_resume, 977f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .id_table = das16cs_id_table, 978f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .owner = THIS_MODULE, 979f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef .drv = { 9800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = dev_info, 981f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef }, 982f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef}; 983f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 984f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic int __init init_das16cs_pcmcia_cs(void) 985f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 986f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "%s\n", version); 987f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef pcmcia_register_driver(&das16cs_driver); 988f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return 0; 989f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 990f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 991f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefstatic void __exit exit_das16cs_pcmcia_cs(void) 992f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 993f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef DEBUG(0, "das16cs_pcmcia_cs: unloading\n"); 994f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef pcmcia_unregister_driver(&das16cs_driver); 995f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 996f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 997f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefint __init init_module(void) 998f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 999f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef int ret; 1000f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1001f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef ret = init_das16cs_pcmcia_cs(); 1002f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef if (ret < 0) 1003f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return ret; 1004f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1005f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef return comedi_driver_register(&driver_das16cs); 1006f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 1007f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1008f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleefvoid __exit cleanup_module(void) 1009f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef{ 1010f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef exit_das16cs_pcmcia_cs(); 1011f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef comedi_driver_unregister(&driver_das16cs); 1012f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef} 1013f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef 1014f0922ec52c3f575aef2860b52dbb246274aec03fDavid Schleef#else 1015f0922ec52c3f575aef2860b52dbb246274aec03fDavid SchleefCOMEDI_INITCLEANUP(driver_das16cs); 10162696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#endif /* CONFIG_PCMCIA */ 1017