pcm3730.c revision 0707bb04be89b18ee83b5a997e36cc585f0b988d
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, struct comedi_devconfig * it); 32static int pcm3730_detach(struct comedi_device * dev); 33static struct comedi_driver driver_pcm3730 = { 34 driver_name:"pcm3730", 35 module:THIS_MODULE, 36 attach:pcm3730_attach, 37 detach:pcm3730_detach, 38}; 39 40COMEDI_INITCLEANUP(driver_pcm3730); 41 42static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, 43 struct comedi_insn * insn, unsigned int * data) 44{ 45 if (insn->n != 2) 46 return -EINVAL; 47 if (data[0]) { 48 s->state &= ~data[0]; 49 s->state |= (data[0] & data[1]); 50 outb(s->state, dev->iobase + (unsigned long)(s->private)); 51 } 52 data[1] = s->state; 53 54 return 2; 55} 56 57static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, 58 struct comedi_insn * insn, unsigned int * data) 59{ 60 if (insn->n != 2) 61 return -EINVAL; 62 data[1] = inb(dev->iobase + (unsigned long)(s->private)); 63 return 2; 64} 65 66static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it) 67{ 68 struct comedi_subdevice *s; 69 unsigned long iobase; 70 71 iobase = it->options[0]; 72 printk("comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); 73 if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) { 74 printk("I/O port conflict\n"); 75 return -EIO; 76 } 77 dev->iobase = iobase; 78 dev->board_name = "pcm3730"; 79 dev->iobase = dev->iobase; 80 dev->irq = 0; 81 82 if (alloc_subdevices(dev, 6) < 0) 83 return -ENOMEM; 84 85 s = dev->subdevices + 0; 86 s->type = COMEDI_SUBD_DO; 87 s->subdev_flags = SDF_WRITABLE; 88 s->maxdata = 1; 89 s->n_chan = 8; 90 s->insn_bits = pcm3730_do_insn_bits; 91 s->range_table = &range_digital; 92 s->private = (void *)PCM3730_DOA; 93 94 s = dev->subdevices + 1; 95 s->type = COMEDI_SUBD_DO; 96 s->subdev_flags = SDF_WRITABLE; 97 s->maxdata = 1; 98 s->n_chan = 8; 99 s->insn_bits = pcm3730_do_insn_bits; 100 s->range_table = &range_digital; 101 s->private = (void *)PCM3730_DOB; 102 103 s = dev->subdevices + 2; 104 s->type = COMEDI_SUBD_DO; 105 s->subdev_flags = SDF_WRITABLE; 106 s->maxdata = 1; 107 s->n_chan = 8; 108 s->insn_bits = pcm3730_do_insn_bits; 109 s->range_table = &range_digital; 110 s->private = (void *)PCM3730_DOC; 111 112 s = dev->subdevices + 3; 113 s->type = COMEDI_SUBD_DI; 114 s->subdev_flags = SDF_READABLE; 115 s->maxdata = 1; 116 s->n_chan = 8; 117 s->insn_bits = pcm3730_di_insn_bits; 118 s->range_table = &range_digital; 119 s->private = (void *)PCM3730_DIA; 120 121 s = dev->subdevices + 4; 122 s->type = COMEDI_SUBD_DI; 123 s->subdev_flags = SDF_READABLE; 124 s->maxdata = 1; 125 s->n_chan = 8; 126 s->insn_bits = pcm3730_di_insn_bits; 127 s->range_table = &range_digital; 128 s->private = (void *)PCM3730_DIB; 129 130 s = dev->subdevices + 5; 131 s->type = COMEDI_SUBD_DI; 132 s->subdev_flags = SDF_READABLE; 133 s->maxdata = 1; 134 s->n_chan = 8; 135 s->insn_bits = pcm3730_di_insn_bits; 136 s->range_table = &range_digital; 137 s->private = (void *)PCM3730_DIC; 138 139 printk("\n"); 140 141 return 0; 142} 143 144static int pcm3730_detach(struct comedi_device * dev) 145{ 146 printk("comedi%d: pcm3730: remove\n", dev->minor); 147 148 if (dev->iobase) 149 release_region(dev->iobase, PCM3730_SIZE); 150 151 return 0; 152} 153