acl7225b.c revision bcd62c0bd353661b9e722513381c674d1244d93a
1/* 2 * comedi/drivers/acl7225b.c 3 * Driver for Adlink NuDAQ ACL-7225b and clones 4 * José Luis Sánchez 5 */ 6/* 7Driver: acl7225b 8Description: Adlink NuDAQ ACL-7225b & compatibles 9Author: José Luis Sánchez (jsanchezv@teleline.es) 10Status: testing 11Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio) 12*/ 13 14#include "../comedidev.h" 15 16#include <linux/ioport.h> 17 18#define ACL7225_SIZE 8 /* Requires 8 ioports, but only 4 are used */ 19#define P16R16DIO_SIZE 4 20#define ACL7225_RIO_LO 0 /* Relays input/output low byte (R0-R7) */ 21#define ACL7225_RIO_HI 1 /* Relays input/output high byte (R8-R15) */ 22#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */ 23#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */ 24 25static int acl7225b_attach(comedi_device * dev, comedi_devconfig * it); 26static int acl7225b_detach(comedi_device * dev); 27 28typedef struct { 29 const char *name; // driver name 30 int io_range; // len of I/O space 31} boardtype; 32 33static const boardtype boardtypes[] = { 34 {"acl7225b", ACL7225_SIZE,}, 35 {"p16r16dio", P16R16DIO_SIZE,}, 36}; 37 38#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) 39#define this_board ((const boardtype *)dev->board_ptr) 40 41static comedi_driver driver_acl7225b = { 42 driver_name:"acl7225b", 43 module:THIS_MODULE, 44 attach:acl7225b_attach, 45 detach:acl7225b_detach, 46 board_name:&boardtypes[0].name, 47 num_names:n_boardtypes, 48 offset:sizeof(boardtype), 49}; 50 51COMEDI_INITCLEANUP(driver_acl7225b); 52 53static int acl7225b_do_insn(comedi_device * dev, comedi_subdevice * s, 54 comedi_insn * insn, lsampl_t * data) 55{ 56 if (insn->n != 2) 57 return -EINVAL; 58 59 if (data[0]) { 60 s->state &= ~data[0]; 61 s->state |= (data[0] & data[1]); 62 } 63 if (data[0] & 0x00ff) 64 outb(s->state & 0xff, dev->iobase + (unsigned long)s->private); 65 if (data[0] & 0xff00) 66 outb((s->state >> 8), 67 dev->iobase + (unsigned long)s->private + 1); 68 69 data[1] = s->state; 70 71 return 2; 72} 73 74static int acl7225b_di_insn(comedi_device * dev, comedi_subdevice * s, 75 comedi_insn * insn, lsampl_t * data) 76{ 77 if (insn->n != 2) 78 return -EINVAL; 79 80 data[1] = inb(dev->iobase + (unsigned long)s->private) | 81 (inb(dev->iobase + (unsigned long)s->private + 1) << 8); 82 83 return 2; 84} 85 86static int acl7225b_attach(comedi_device * dev, comedi_devconfig * it) 87{ 88 comedi_subdevice *s; 89 int iobase, iorange; 90 91 iobase = it->options[0]; 92 iorange = this_board->io_range; 93 printk("comedi%d: acl7225b: board=%s 0x%04x ", dev->minor, 94 this_board->name, iobase); 95 if (!request_region(iobase, iorange, "acl7225b")) { 96 printk("I/O port conflict\n"); 97 return -EIO; 98 } 99 dev->board_name = this_board->name; 100 dev->iobase = iobase; 101 dev->irq = 0; 102 103 if (alloc_subdevices(dev, 3) < 0) 104 return -ENOMEM; 105 106 s = dev->subdevices + 0; 107 /* Relays outputs */ 108 s->type = COMEDI_SUBD_DO; 109 s->subdev_flags = SDF_WRITABLE; 110 s->maxdata = 1; 111 s->n_chan = 16; 112 s->insn_bits = acl7225b_do_insn; 113 s->range_table = &range_digital; 114 s->private = (void *)ACL7225_RIO_LO; 115 116 s = dev->subdevices + 1; 117 /* Relays status */ 118 s->type = COMEDI_SUBD_DI; 119 s->subdev_flags = SDF_READABLE; 120 s->maxdata = 1; 121 s->n_chan = 16; 122 s->insn_bits = acl7225b_di_insn; 123 s->range_table = &range_digital; 124 s->private = (void *)ACL7225_RIO_LO; 125 126 s = dev->subdevices + 2; 127 /* Isolated digital inputs */ 128 s->type = COMEDI_SUBD_DI; 129 s->subdev_flags = SDF_READABLE; 130 s->maxdata = 1; 131 s->n_chan = 16; 132 s->insn_bits = acl7225b_di_insn; 133 s->range_table = &range_digital; 134 s->private = (void *)ACL7225_DI_LO; 135 136 printk("\n"); 137 138 return 0; 139} 140 141static int acl7225b_detach(comedi_device * dev) 142{ 143 printk("comedi%d: acl7225b: remove\n", dev->minor); 144 145 if (dev->iobase) 146 release_region(dev->iobase, this_board->io_range); 147 148 return 0; 149} 150