1bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez/* 2bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez * comedi/drivers/acl7225b.c 3bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez * Driver for Adlink NuDAQ ACL-7225b and clones 4bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez * José Luis Sánchez 5bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez */ 6bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez/* 7bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis SánchezDriver: acl7225b 8bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis SánchezDescription: Adlink NuDAQ ACL-7225b & compatibles 9bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis SánchezAuthor: José Luis Sánchez (jsanchezv@teleline.es) 10bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis SánchezStatus: testing 11bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis SánchezDevices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio) 12bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez*/ 13bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 14bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#include "../comedidev.h" 15bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 16bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#include <linux/ioport.h> 17bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 18bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define ACL7225_SIZE 8 /* Requires 8 ioports, but only 4 are used */ 19bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define P16R16DIO_SIZE 4 20bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define ACL7225_RIO_LO 0 /* Relays input/output low byte (R0-R7) */ 21bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define ACL7225_RIO_HI 1 /* Relays input/output high byte (R8-R15) */ 22bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */ 23bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */ 24bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int acl7225b_attach(struct comedi_device *dev, 260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 2771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int acl7225b_detach(struct comedi_device *dev); 28bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 29502dd07999b48994dc3c86a0c44f1a684299d44fBill Pembertonstruct boardtype { 30ed27614451c3f35412b83aabdcd4af6d76be7cd7Bill Pemberton const char *name; /* driver name */ 31ed27614451c3f35412b83aabdcd4af6d76be7cd7Bill Pemberton int io_range; /* len of I/O space */ 32502dd07999b48994dc3c86a0c44f1a684299d44fBill Pemberton}; 33bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 34502dd07999b48994dc3c86a0c44f1a684299d44fBill Pembertonstatic const struct boardtype boardtypes[] = { 35bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez {"acl7225b", ACL7225_SIZE,}, 36bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez {"p16r16dio", P16R16DIO_SIZE,}, 37bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez}; 38bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 39502dd07999b48994dc3c86a0c44f1a684299d44fBill Pemberton#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) 40502dd07999b48994dc3c86a0c44f1a684299d44fBill Pemberton#define this_board ((const struct boardtype *)dev->board_ptr) 41bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 42139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_acl7225b = { 4368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "acl7225b", 4468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 4568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = acl7225b_attach, 4668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = acl7225b_detach, 4768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &boardtypes[0].name, 4868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .num_names = n_boardtypes, 4968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct boardtype), 50bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez}; 51bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 527114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_acl7225b_init_module(void) 537114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 547114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_acl7225b); 557114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 567114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 577114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_acl7225b_cleanup_module(void) 587114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 597114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_acl7225b); 607114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 617114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 627114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_acl7225b_init_module); 637114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_acl7225b_cleanup_module); 64bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int acl7225b_do_insn(struct comedi_device *dev, 660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 68bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez{ 69bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (insn->n != 2) 70bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return -EINVAL; 71bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 72bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (data[0]) { 73bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->state &= ~data[0]; 74bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->state |= (data[0] & data[1]); 75bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez } 76bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (data[0] & 0x00ff) 77bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez outb(s->state & 0xff, dev->iobase + (unsigned long)s->private); 78bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (data[0] & 0xff00) 79bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez outb((s->state >> 8), 800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + (unsigned long)s->private + 1); 81bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 82bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez data[1] = s->state; 83bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 84bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return 2; 85bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez} 86bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int acl7225b_di_insn(struct comedi_device *dev, 880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 90bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez{ 91bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (insn->n != 2) 92bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return -EINVAL; 93bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 94bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez data[1] = inb(dev->iobase + (unsigned long)s->private) | 950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (inb(dev->iobase + (unsigned long)s->private + 1) << 8); 96bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 97bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return 2; 98bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez} 99bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 1000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int acl7225b_attach(struct comedi_device *dev, 1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it) 102bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez{ 10334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 104bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez int iobase, iorange; 105bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 106bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez iobase = it->options[0]; 107bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez iorange = this_board->io_range; 1080dfd69bfdbf9de7021e81443c0c195f7da208a7dBruce Jones printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor, 1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral this_board->name, iobase); 110bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (!request_region(iobase, iorange, "acl7225b")) { 1110dfd69bfdbf9de7021e81443c0c195f7da208a7dBruce Jones printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n", 1120dfd69bfdbf9de7021e81443c0c195f7da208a7dBruce Jones dev->minor); 113bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return -EIO; 114bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez } 115bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez dev->board_name = this_board->name; 116bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez dev->iobase = iobase; 117bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez dev->irq = 0; 118bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 119bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (alloc_subdevices(dev, 3) < 0) 120bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return -ENOMEM; 121bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 122bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s = dev->subdevices + 0; 123bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez /* Relays outputs */ 124bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->type = COMEDI_SUBD_DO; 125bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->subdev_flags = SDF_WRITABLE; 126bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->maxdata = 1; 127bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->n_chan = 16; 128bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->insn_bits = acl7225b_do_insn; 129bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->range_table = &range_digital; 130bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->private = (void *)ACL7225_RIO_LO; 131bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 132bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s = dev->subdevices + 1; 133bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez /* Relays status */ 134bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->type = COMEDI_SUBD_DI; 135bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->subdev_flags = SDF_READABLE; 136bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->maxdata = 1; 137bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->n_chan = 16; 138bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->insn_bits = acl7225b_di_insn; 139bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->range_table = &range_digital; 140bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->private = (void *)ACL7225_RIO_LO; 141bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 142bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s = dev->subdevices + 2; 143bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez /* Isolated digital inputs */ 144bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->type = COMEDI_SUBD_DI; 145bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->subdev_flags = SDF_READABLE; 146bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->maxdata = 1; 147bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->n_chan = 16; 148bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->insn_bits = acl7225b_di_insn; 149bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->range_table = &range_digital; 150bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez s->private = (void *)ACL7225_DI_LO; 151bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 152bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return 0; 153bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez} 154bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 15571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int acl7225b_detach(struct comedi_device *dev) 156bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez{ 1570dfd69bfdbf9de7021e81443c0c195f7da208a7dBruce Jones printk(KERN_INFO "comedi%d: acl7225b: remove\n", dev->minor); 158bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 159bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez if (dev->iobase) 160bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez release_region(dev->iobase, this_board->io_range); 161bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez 162bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez return 0; 163bcd62c0bd353661b9e722513381c674d1244d93aJosé Luis Sánchez} 16490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 16590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 16690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 16790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 168