pcl725.c revision 7114a28011f9d5f3d981731ad341177c21f9d948
1/* 2 * comedi/drivers/pcl725.c 3 * Driver for PCL725 and clones 4 * David A. Schleef 5 */ 6/* 7Driver: pcl725 8Description: Advantech PCL-725 (& compatibles) 9Author: ds 10Status: unknown 11Devices: [Advantech] PCL-725 (pcl725) 12*/ 13 14#include "../comedidev.h" 15 16#include <linux/ioport.h> 17 18#define PCL725_SIZE 2 19 20#define PCL725_DO 0 21#define PCL725_DI 1 22 23static int pcl725_attach(struct comedi_device *dev, 24 struct comedi_devconfig *it); 25static int pcl725_detach(struct comedi_device *dev); 26static struct comedi_driver driver_pcl725 = { 27 .driver_name = "pcl725", 28 .module = THIS_MODULE, 29 .attach = pcl725_attach, 30 .detach = pcl725_detach, 31}; 32 33static int __init driver_pcl725_init_module(void) 34{ 35 return comedi_driver_register(&driver_pcl725); 36} 37 38static void __exit driver_pcl725_cleanup_module(void) 39{ 40 comedi_driver_unregister(&driver_pcl725); 41} 42 43module_init(driver_pcl725_init_module); 44module_exit(driver_pcl725_cleanup_module); 45 46static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s, 47 struct comedi_insn *insn, unsigned int *data) 48{ 49 if (insn->n != 2) 50 return -EINVAL; 51 52 if (data[0]) { 53 s->state &= ~data[0]; 54 s->state |= (data[0] & data[1]); 55 outb(s->state, dev->iobase + PCL725_DO); 56 } 57 58 data[1] = s->state; 59 60 return 2; 61} 62 63static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, 64 struct comedi_insn *insn, unsigned int *data) 65{ 66 if (insn->n != 2) 67 return -EINVAL; 68 69 data[1] = inb(dev->iobase + PCL725_DI); 70 71 return 2; 72} 73 74static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) 75{ 76 struct comedi_subdevice *s; 77 unsigned long iobase; 78 79 iobase = it->options[0]; 80 printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase); 81 if (!request_region(iobase, PCL725_SIZE, "pcl725")) { 82 printk("I/O port conflict\n"); 83 return -EIO; 84 } 85 dev->board_name = "pcl725"; 86 dev->iobase = iobase; 87 dev->irq = 0; 88 89 if (alloc_subdevices(dev, 2) < 0) 90 return -ENOMEM; 91 92 s = dev->subdevices + 0; 93 /* do */ 94 s->type = COMEDI_SUBD_DO; 95 s->subdev_flags = SDF_WRITABLE; 96 s->maxdata = 1; 97 s->n_chan = 8; 98 s->insn_bits = pcl725_do_insn; 99 s->range_table = &range_digital; 100 101 s = dev->subdevices + 1; 102 /* di */ 103 s->type = COMEDI_SUBD_DI; 104 s->subdev_flags = SDF_READABLE; 105 s->maxdata = 1; 106 s->n_chan = 8; 107 s->insn_bits = pcl725_di_insn; 108 s->range_table = &range_digital; 109 110 printk(KERN_INFO "\n"); 111 112 return 0; 113} 114 115static int pcl725_detach(struct comedi_device *dev) 116{ 117 printk(KERN_INFO "comedi%d: pcl725: remove\n", dev->minor); 118 119 if (dev->iobase) 120 release_region(dev->iobase, PCL725_SIZE); 121 122 return 0; 123} 124 125MODULE_AUTHOR("Comedi http://www.comedi.org"); 126MODULE_DESCRIPTION("Comedi low-level driver"); 127MODULE_LICENSE("GPL"); 128