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