118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* 218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel comedi/drivers/ssv_dnp.c 318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel generic comedi driver for SSV Embedded Systems' DIL/Net-PCs 418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel Copyright (C) 2001 Robert Schwebel <robert@schwebel.de> 518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel COMEDI - Linux Control and Measurement Device Interface 718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel Copyright (C) 2000 David A. Schleef <ds@schleef.org> 818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel This program is free software; you can redistribute it and/or modify 1018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel it under the terms of the GNU General Public License as published by 1118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel the Free Software Foundation; either version 2 of the License, or 1218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel (at your option) any later version. 1318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 1418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel This program is distributed in the hope that it will be useful, 1518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel but WITHOUT ANY WARRANTY; without even the implied warranty of 1618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel GNU General Public License for more details. 1818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 1918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel You should have received a copy of the GNU General Public License 2018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel along with this program; if not, write to the Free Software 2118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 2318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel*/ 2418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* 2518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert SchwebelDriver: ssv_dnp 2618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert SchwebelDescription: SSV Embedded Systems DIL/Net-PC 2718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert SchwebelAuthor: Robert Schwebel <robert@schwebel.de> 2818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert SchwebelDevices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486) 2918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert SchwebelStatus: unknown 3018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel*/ 3118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 3218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* include files ----------------------------------------------------------- */ 3318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 3418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel#include "../comedidev.h" 3518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 3618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* Some global definitions: the registers of the DNP ----------------------- */ 3718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* */ 3818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* For port A and B the mode register has bits corresponding to the output */ 3918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* pins, where Bit-N = 0 -> input, Bit-N = 1 -> output. Note that bits */ 4018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* 4 to 7 correspond to pin 0..3 for port C data register. Ensure that bits */ 4118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* 0..3 remain unchanged! For details about Port C Mode Register see */ 4218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* the remarks in dnp_insn_config() below. */ 4318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 4406033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define CSCIR 0x22 /* Chip Setup and Control Index Register */ 4506033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define CSCDR 0x23 /* Chip Setup and Control Data Register */ 4606033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PAMR 0xa5 /* Port A Mode Register */ 4706033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PADR 0xa9 /* Port A Data Register */ 4806033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PBMR 0xa4 /* Port B Mode Register */ 4906033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PBDR 0xa8 /* Port B Data Register */ 5006033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PCMR 0xa3 /* Port C Mode Register */ 5106033fced289985294e5a3f694646014d80b48ccDarren Armstrong#define PCDR 0xa7 /* Port C Data Register */ 5218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 5318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* This data structure holds information about the supported boards -------- */ 5418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 55c0d1482252b9b87c62b8d0ddb7ceecc369c6e34eBill Pembertonstruct dnp_board { 5618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel const char *name; 5718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel int ai_chans; 5818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel int ai_bits; 5918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel int have_dio; 60c0d1482252b9b87c62b8d0ddb7ceecc369c6e34eBill Pemberton}; 6118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 6206033fced289985294e5a3f694646014d80b48ccDarren Armstrong/* We only support one DNP 'board' variant at the moment */ 6306033fced289985294e5a3f694646014d80b48ccDarren Armstrongstatic const struct dnp_board dnp_boards[] = { 6406033fced289985294e5a3f694646014d80b48ccDarren Armstrong{ 650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "dnp-1486", 660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_chans = 16, 670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_bits = 12, 680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .have_dio = 1, 690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 7018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel}; 7118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 7218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* Useful for shorthand access to the particular board structure ----------- */ 73c0d1482252b9b87c62b8d0ddb7ceecc369c6e34eBill Pemberton#define thisboard ((const struct dnp_board *)dev->board_ptr) 7418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 7518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* This structure is for data unique to the DNP driver --------------------- */ 768532530040c05ab60e7d83c705713ef2629cd3bbBill Pembertonstruct dnp_private_data { 778532530040c05ab60e7d83c705713ef2629cd3bbBill Pemberton 788532530040c05ab60e7d83c705713ef2629cd3bbBill Pemberton}; 798532530040c05ab60e7d83c705713ef2629cd3bbBill Pemberton 8018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* Shorthand macro for faster access to the private data ------------------- */ 8118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel#define devpriv ((dnp_private *)dev->private) 8218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 8318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 8406033fced289985294e5a3f694646014d80b48ccDarren Armstrong/* The struct comedi_driver structure tells the Comedi core module which */ 8506033fced289985294e5a3f694646014d80b48ccDarren Armstrong/* functions to call to configure/deconfigure (attach/detach) the board, and */ 8606033fced289985294e5a3f694646014d80b48ccDarren Armstrong/* also about the kernel module that contains the device code. */ 8718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* */ 8818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* In the following section we define the API of this driver. */ 8918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 9018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 91da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it); 92da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_detach(struct comedi_device *dev); 9318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 94139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_dnp = { 9568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "ssv_dnp", 9668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 9768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = dnp_attach, 9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = dnp_detach, 9968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &dnp_boards[0].name, 10018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel /* only necessary for non-PnP devs */ 10106033fced289985294e5a3f694646014d80b48ccDarren Armstrong .offset = sizeof(struct dnp_board), /* like ISA-PnP, PCI or PCMCIA */ 1028629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton .num_names = ARRAY_SIZE(dnp_boards), 10318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel}; 10418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 1057114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_dnp_init_module(void) 1067114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 1077114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_dnp); 1087114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 1097114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 1107114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_dnp_cleanup_module(void) 1117114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 1127114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_dnp); 1137114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 1147114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 1157114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_dnp_init_module); 1167114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_dnp_cleanup_module); 11718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 118da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_dio_insn_bits(struct comedi_device *dev, 1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 12118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 122da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_dio_insn_config(struct comedi_device *dev, 1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 12518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 12618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 12718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* Attach is called by comedi core to configure the driver for a particular */ 12818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* board. If you specified a board_name array in the driver structure, */ 12918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* dev->board_ptr contains that address. */ 13018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 13118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 132da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) 13318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel{ 13418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 13534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 13618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 13706033fced289985294e5a3f694646014d80b48ccDarren Armstrong printk(KERN_INFO "comedi%d: dnp: ", dev->minor); 13818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 13906033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Autoprobing: this should find out which board we have. Currently */ 14006033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* only the 1486 board is supported and autoprobing is not */ 14106033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* implemented :-) */ 1422696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* dev->board_ptr = dnp_probe(dev); */ 14318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 14406033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Initialize the name of the board. */ 14506033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* We can use the "thisboard" macro now. */ 14618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel dev->board_name = thisboard->name; 14718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 14806033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Allocate the private structure area. alloc_private() is a */ 14906033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* convenient macro defined in comedidev.h. */ 1508532530040c05ab60e7d83c705713ef2629cd3bbBill Pemberton if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0) 15118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return -ENOMEM; 15218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 15306033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Allocate the subdevice structures. alloc_subdevice() is a */ 15406033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* convenient macro defined in comedidev.h. */ 15518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 15618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel if (alloc_subdevices(dev, 1) < 0) 15718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return -ENOMEM; 15818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 15918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s = dev->subdevices + 0; 16006033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* digital i/o subdevice */ 16118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->type = COMEDI_SUBD_DIO; 16218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 16318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->n_chan = 20; 16418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->maxdata = 1; 16518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->range_table = &range_digital; 16618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->insn_bits = dnp_dio_insn_bits; 16718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel s->insn_config = dnp_dio_insn_config; 16818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 16918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel printk("attached\n"); 17018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 17118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always 17218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel * allocated for the primary 8259, so we don't need to allocate them 17318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel * ourselves. */ 17418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 17506033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* configure all ports as input (default) */ 17618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PAMR, CSCIR); 17718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(0x00, CSCDR); 17818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PBMR, CSCIR); 17918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(0x00, CSCDR); 18018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PCMR, CSCIR); 18118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb((inb(CSCDR) & 0xAA), CSCDR); 18218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 18318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return 1; 18418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 18518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel} 18618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 18718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 18818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* detach is called to deconfigure a device. It should deallocate the */ 18918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* resources. This function is also called when _attach() fails, so it */ 19018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* should be careful not to release resources that were not necessarily */ 19118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* allocated by _attach(). dev->private and dev->subdevices are */ 19218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* deallocated automatically by the core. */ 19318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 19418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 195da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_detach(struct comedi_device *dev) 19618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel{ 19718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 19806033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* configure all ports as input (default) */ 19918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PAMR, CSCIR); 20018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(0x00, CSCDR); 20118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PBMR, CSCIR); 20218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(0x00, CSCDR); 20318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PCMR, CSCIR); 20418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb((inb(CSCDR) & 0xAA), CSCDR); 20518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 20606033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* announce that we are finished */ 20706033fced289985294e5a3f694646014d80b48ccDarren Armstrong printk(KERN_INFO "comedi%d: dnp: remove\n", dev->minor); 20818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 20918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return 0; 21018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 21118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel} 21218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 21318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 21418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* The insn_bits interface allows packed reading/writing of DIO channels. */ 21518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* The comedi core can convert between insn_bits and insn_read/write, so you */ 21618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* are able to use these instructions as well. */ 21718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 21818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 219da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_dio_insn_bits(struct comedi_device *dev, 2200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 22218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel{ 22318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 22418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel if (insn->n != 2) 22518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return -EINVAL; /* insn uses data[0] and data[1] */ 22618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 22706033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* The insn data is a mask in data[0] and the new data in data[1], */ 22806033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* each channel cooresponding to a bit. */ 22918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 23006033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Ports A and B are straight forward: each bit corresponds to an */ 23106033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* output pin with the same order. Port C is different: bits 0...3 */ 23206033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* correspond to bits 4...7 of the output register (PCDR). */ 23318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 23418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel if (data[0]) { 23518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 23618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PADR, CSCIR); 23718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb((inb(CSCDR) 2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral & ~(u8) (data[0] & 0x0000FF)) 2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral | (u8) (data[1] & 0x0000FF), CSCDR); 24018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 24118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PBDR, CSCIR); 24218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb((inb(CSCDR) 2430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral & ~(u8) ((data[0] & 0x00FF00) >> 8)) 2440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral | (u8) ((data[1] & 0x00FF00) >> 8), CSCDR); 24518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 24618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PCDR, CSCIR); 24718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb((inb(CSCDR) 2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral & ~(u8) ((data[0] & 0x0F0000) >> 12)) 2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral | (u8) ((data[1] & 0x0F0000) >> 12), CSCDR); 25018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } 25118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 25206033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* on return, data[1] contains the value of the digital input lines. */ 25318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PADR, CSCIR); 25418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel data[0] = inb(CSCDR); 25518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PBDR, CSCIR); 25618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel data[0] += inb(CSCDR) << 8; 25718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PCDR, CSCIR); 25818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel data[0] += ((inb(CSCDR) & 0xF0) << 12); 25918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 26018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return 2; 26118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 26218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel} 26318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 26418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 26518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* Configure the direction of the bidirectional digital i/o pins. chanspec */ 26618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* contains the channel to be changed and data[0] contains either */ 26718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* COMEDI_INPUT or COMEDI_OUTPUT. */ 26818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel/* ------------------------------------------------------------------------- */ 26918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 270da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dnp_dio_insn_config(struct comedi_device *dev, 2710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 27318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel{ 27418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 27518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel u8 register_buffer; 27618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 27706033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* reduces chanspec to lower 16 bits */ 27806033fced289985294e5a3f694646014d80b48ccDarren Armstrong int chan = CR_CHAN(insn->chanspec); 27918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 28018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel switch (data[0]) { 28118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel case INSN_CONFIG_DIO_OUTPUT: 28218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel case INSN_CONFIG_DIO_INPUT: 28318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel break; 28418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel case INSN_CONFIG_DIO_QUERY: 28518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel data[1] = 2860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (inb(CSCDR) & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 28718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return insn->n; 28818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel break; 28918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel default: 29018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return -EINVAL; 29118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel break; 29218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } 29306033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Test: which port does the channel belong to? */ 29418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 29506033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* We have to pay attention with port C: this is the meaning of PCMR: */ 29606033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Bit in PCMR: 7 6 5 4 3 2 1 0 */ 29706033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch */ 29818222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 29918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel if ((chan >= 0) && (chan <= 7)) { 30018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel /* this is port A */ 30118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PAMR, CSCIR); 30218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } else if ((chan >= 8) && (chan <= 15)) { 30318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel /* this is port B */ 30418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel chan -= 8; 30518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PBMR, CSCIR); 30618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } else if ((chan >= 16) && (chan <= 19)) { 30706033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* this is port C; multiplication with 2 brings bits into */ 30806033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* correct position for PCMR! */ 30918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel chan -= 16; 31018222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel chan *= 2; 31118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(PCMR, CSCIR); 31218222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } else { 31318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return -EINVAL; 31418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel } 31518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 31606033fced289985294e5a3f694646014d80b48ccDarren Armstrong /* read 'old' direction of the port and set bits (out=1, in=0) */ 31718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel register_buffer = inb(CSCDR); 318dee86e8c9279110d787da64cbca5d4bda63d93c6Greg Kroah-Hartman if (data[0] == COMEDI_OUTPUT) 31918222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel register_buffer |= (1 << chan); 320dee86e8c9279110d787da64cbca5d4bda63d93c6Greg Kroah-Hartman else 32118222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel register_buffer &= ~(1 << chan); 322dee86e8c9279110d787da64cbca5d4bda63d93c6Greg Kroah-Hartman 32318222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel outb(register_buffer, CSCDR); 32418222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 32518222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel return 1; 32618222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel 32718222f98223a00537bcf29ba74c8d5fdb3ae1fb8Robert Schwebel} 32890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 32990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 33090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 33190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 332