/* * comedi/drivers/pcm3730.c * Driver for PCM3730 and clones * Blaine Lee * from pcl725 by David S. */ /* Driver: pcm3730 Description: PCM3730 Author: Blaine Lee Devices: [Advantech] PCM-3730 (pcm3730) Status: unknown Configuration options: [0] - I/O port base */ #include "../comedidev.h" #include #define PCM3730_SIZE 4 /* consecutive io port addresses */ #define PCM3730_DOA 0 /* offsets for each port */ #define PCM3730_DOB 2 #define PCM3730_DOC 3 #define PCM3730_DIA 0 #define PCM3730_DIB 2 #define PCM3730_DIC 3 static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it); static int pcm3730_detach(struct comedi_device *dev); static struct comedi_driver driver_pcm3730 = { .driver_name = "pcm3730", .module = THIS_MODULE, .attach = pcm3730_attach, .detach = pcm3730_detach, }; static int __init driver_pcm3730_init_module(void) { return comedi_driver_register(&driver_pcm3730); } static void __exit driver_pcm3730_cleanup_module(void) { comedi_driver_unregister(&driver_pcm3730); } module_init(driver_pcm3730_init_module); module_exit(driver_pcm3730_cleanup_module); static int pcm3730_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (insn->n != 2) return -EINVAL; if (data[0]) { s->state &= ~data[0]; s->state |= (data[0] & data[1]); outb(s->state, dev->iobase + (unsigned long)(s->private)); } data[1] = s->state; return 2; } static int pcm3730_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (insn->n != 2) return -EINVAL; data[1] = inb(dev->iobase + (unsigned long)(s->private)); return 2; } static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; unsigned long iobase; iobase = it->options[0]; printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) { printk("I/O port conflict\n"); return -EIO; } dev->iobase = iobase; dev->board_name = "pcm3730"; dev->iobase = dev->iobase; dev->irq = 0; if (alloc_subdevices(dev, 6) < 0) return -ENOMEM; s = dev->subdevices + 0; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_do_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DOA; s = dev->subdevices + 1; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_do_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DOB; s = dev->subdevices + 2; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_do_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DOC; s = dev->subdevices + 3; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_di_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DIA; s = dev->subdevices + 4; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_di_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DIB; s = dev->subdevices + 5; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->maxdata = 1; s->n_chan = 8; s->insn_bits = pcm3730_di_insn_bits; s->range_table = &range_digital; s->private = (void *)PCM3730_DIC; printk(KERN_INFO "\n"); return 0; } static int pcm3730_detach(struct comedi_device *dev) { printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor); if (dev->iobase) release_region(dev->iobase, PCM3730_SIZE); return 0; } MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL");