1/* 2 * comedi/drivers/pcm3730.c 3 * Driver for PCM3730 and clones 4 * Blaine Lee 5 * from pcl725 by David S. 6 */ 7/* 8Driver: pcm3730 9Description: PCM3730 10Author: Blaine Lee 11Devices: [Advantech] PCM-3730 (pcm3730) 12Status: unknown 13 14Configuration options: 15 [0] - I/O port base 16*/ 17 18#include "../comedidev.h" 19 20#include <linux/ioport.h> 21 22#define PCM3730_SIZE 4 /* consecutive io port addresses */ 23 24#define PCM3730_DOA 0 /* offsets for each port */ 25#define PCM3730_DOB 2 26#define PCM3730_DOC 3 27#define PCM3730_DIA 0 28#define PCM3730_DIB 2 29#define PCM3730_DIC 3 30 31static int pcm3730_attach(struct comedi_device *dev, 32 struct comedi_devconfig *it); 33static int pcm3730_detach(struct comedi_device *dev); 34static struct comedi_driver driver_pcm3730 = { 35 .driver_name = "pcm3730", 36 .module = THIS_MODULE, 37 .attach = pcm3730_attach, 38 .detach = pcm3730_detach, 39}; 40 41static int __init driver_pcm3730_init_module(void) 42{ 43 return comedi_driver_register(&driver_pcm3730); 44} 45 46static void __exit driver_pcm3730_cleanup_module(void) 47{ 48 comedi_driver_unregister(&driver_pcm3730); 49} 50 51module_init(driver_pcm3730_init_module); 52module_exit(driver_pcm3730_cleanup_module); 53 54static int pcm3730_do_insn_bits(struct comedi_device *dev, 55 struct comedi_subdevice *s, 56 struct comedi_insn *insn, unsigned int *data) 57{ 58 if (insn->n != 2) 59 return -EINVAL; 60 if (data[0]) { 61 s->state &= ~data[0]; 62 s->state |= (data[0] & data[1]); 63 outb(s->state, dev->iobase + (unsigned long)(s->private)); 64 } 65 data[1] = s->state; 66 67 return 2; 68} 69 70static int pcm3730_di_insn_bits(struct comedi_device *dev, 71 struct comedi_subdevice *s, 72 struct comedi_insn *insn, unsigned int *data) 73{ 74 if (insn->n != 2) 75 return -EINVAL; 76 data[1] = inb(dev->iobase + (unsigned long)(s->private)); 77 return 2; 78} 79 80static int pcm3730_attach(struct comedi_device *dev, 81 struct comedi_devconfig *it) 82{ 83 struct comedi_subdevice *s; 84 unsigned long iobase; 85 86 iobase = it->options[0]; 87 printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); 88 if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) { 89 printk("I/O port conflict\n"); 90 return -EIO; 91 } 92 dev->iobase = iobase; 93 dev->board_name = "pcm3730"; 94 dev->iobase = dev->iobase; 95 dev->irq = 0; 96 97 if (alloc_subdevices(dev, 6) < 0) 98 return -ENOMEM; 99 100 s = dev->subdevices + 0; 101 s->type = COMEDI_SUBD_DO; 102 s->subdev_flags = SDF_WRITABLE; 103 s->maxdata = 1; 104 s->n_chan = 8; 105 s->insn_bits = pcm3730_do_insn_bits; 106 s->range_table = &range_digital; 107 s->private = (void *)PCM3730_DOA; 108 109 s = dev->subdevices + 1; 110 s->type = COMEDI_SUBD_DO; 111 s->subdev_flags = SDF_WRITABLE; 112 s->maxdata = 1; 113 s->n_chan = 8; 114 s->insn_bits = pcm3730_do_insn_bits; 115 s->range_table = &range_digital; 116 s->private = (void *)PCM3730_DOB; 117 118 s = dev->subdevices + 2; 119 s->type = COMEDI_SUBD_DO; 120 s->subdev_flags = SDF_WRITABLE; 121 s->maxdata = 1; 122 s->n_chan = 8; 123 s->insn_bits = pcm3730_do_insn_bits; 124 s->range_table = &range_digital; 125 s->private = (void *)PCM3730_DOC; 126 127 s = dev->subdevices + 3; 128 s->type = COMEDI_SUBD_DI; 129 s->subdev_flags = SDF_READABLE; 130 s->maxdata = 1; 131 s->n_chan = 8; 132 s->insn_bits = pcm3730_di_insn_bits; 133 s->range_table = &range_digital; 134 s->private = (void *)PCM3730_DIA; 135 136 s = dev->subdevices + 4; 137 s->type = COMEDI_SUBD_DI; 138 s->subdev_flags = SDF_READABLE; 139 s->maxdata = 1; 140 s->n_chan = 8; 141 s->insn_bits = pcm3730_di_insn_bits; 142 s->range_table = &range_digital; 143 s->private = (void *)PCM3730_DIB; 144 145 s = dev->subdevices + 5; 146 s->type = COMEDI_SUBD_DI; 147 s->subdev_flags = SDF_READABLE; 148 s->maxdata = 1; 149 s->n_chan = 8; 150 s->insn_bits = pcm3730_di_insn_bits; 151 s->range_table = &range_digital; 152 s->private = (void *)PCM3730_DIC; 153 154 printk(KERN_INFO "\n"); 155 156 return 0; 157} 158 159static int pcm3730_detach(struct comedi_device *dev) 160{ 161 printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor); 162 163 if (dev->iobase) 164 release_region(dev->iobase, PCM3730_SIZE); 165 166 return 0; 167} 168 169MODULE_AUTHOR("Comedi http://www.comedi.org"); 170MODULE_DESCRIPTION("Comedi low-level driver"); 171MODULE_LICENSE("GPL"); 172