-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mini-drivers for POC (Piece of crap) boards. Currently supports: Keithley Metrabyte DAC-02 Advantech PCL-733, PCL-734 From: David Schleef <ds@schleef.org> Cc: Frank Mori Hess <fmhess@users.sourceforge.net> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
- Loading branch information
David A. Schleef
authored and
Greg Kroah-Hartman
committed
Apr 3, 2009
1 parent
62ed666
commit ac52af9
Showing
1 changed file
with
247 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
/* | ||
comedi/drivers/poc.c | ||
Mini-drivers for POC (Piece of Crap) boards | ||
Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net> | ||
Copyright (C) 2001 David A. Schleef <ds@schleef.org> | ||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program; if not, write to the Free Software | ||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
*/ | ||
/* | ||
Driver: poc | ||
Description: Generic driver for very simple devices | ||
Author: ds | ||
Devices: [Keithley Metrabyte] DAC-02 (dac02), [Advantech] PCL-733 (pcl733), | ||
PCL-734 (pcl734) | ||
Updated: Sat, 16 Mar 2002 17:34:48 -0800 | ||
Status: unknown | ||
This driver is indended to support very simple ISA-based devices, | ||
including: | ||
dac02 - Keithley DAC-02 analog output board | ||
pcl733 - Advantech PCL-733 | ||
pcl734 - Advantech PCL-734 | ||
Configuration options: | ||
[0] - I/O port base | ||
*/ | ||
|
||
#include "../comedidev.h" | ||
|
||
#include <linux/ioport.h> | ||
|
||
static int poc_attach(comedi_device * dev, comedi_devconfig * it); | ||
static int poc_detach(comedi_device * dev); | ||
static int readback_insn(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data); | ||
|
||
static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data); | ||
static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data); | ||
static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data); | ||
|
||
struct boarddef_struct { | ||
const char *name; | ||
unsigned int iosize; | ||
int (*setup) (comedi_device *); | ||
int type; | ||
int n_chan; | ||
int n_bits; | ||
int (*winsn) (comedi_device *, comedi_subdevice *, comedi_insn *, | ||
lsampl_t *); | ||
int (*rinsn) (comedi_device *, comedi_subdevice *, comedi_insn *, | ||
lsampl_t *); | ||
int (*insnbits) (comedi_device *, comedi_subdevice *, comedi_insn *, | ||
lsampl_t *); | ||
const comedi_lrange *range; | ||
}; | ||
static const struct boarddef_struct boards[] = { | ||
{ | ||
name: "dac02", | ||
iosize: 8, | ||
//setup: dac02_setup, | ||
type: COMEDI_SUBD_AO, | ||
n_chan: 2, | ||
n_bits: 12, | ||
winsn: dac02_ao_winsn, | ||
rinsn: readback_insn, | ||
range: &range_unknown, | ||
}, | ||
{ | ||
name: "pcl733", | ||
iosize: 4, | ||
type: COMEDI_SUBD_DI, | ||
n_chan: 32, | ||
n_bits: 1, | ||
insnbits:pcl733_insn_bits, | ||
range: &range_digital, | ||
}, | ||
{ | ||
name: "pcl734", | ||
iosize: 4, | ||
type: COMEDI_SUBD_DO, | ||
n_chan: 32, | ||
n_bits: 1, | ||
insnbits:pcl734_insn_bits, | ||
range: &range_digital, | ||
}, | ||
}; | ||
|
||
#define n_boards (sizeof(boards)/sizeof(boards[0])) | ||
#define this_board ((const struct boarddef_struct *)dev->board_ptr) | ||
|
||
static comedi_driver driver_poc = { | ||
driver_name:"poc", | ||
module:THIS_MODULE, | ||
attach:poc_attach, | ||
detach:poc_detach, | ||
board_name:&boards[0].name, | ||
num_names:n_boards, | ||
offset:sizeof(boards[0]), | ||
}; | ||
|
||
static int poc_attach(comedi_device * dev, comedi_devconfig * it) | ||
{ | ||
comedi_subdevice *s; | ||
unsigned long iobase; | ||
unsigned int iosize; | ||
|
||
iobase = it->options[0]; | ||
printk("comedi%d: poc: using %s iobase 0x%lx\n", dev->minor, | ||
this_board->name, iobase); | ||
|
||
dev->board_name = this_board->name; | ||
|
||
if (iobase == 0) { | ||
printk("io base address required\n"); | ||
return -EINVAL; | ||
} | ||
|
||
iosize = this_board->iosize; | ||
/* check if io addresses are available */ | ||
if (!request_region(iobase, iosize, "dac02")) { | ||
printk("I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + iosize - 1); | ||
return -EIO; | ||
} | ||
dev->iobase = iobase; | ||
|
||
if (alloc_subdevices(dev, 1) < 0) | ||
return -ENOMEM; | ||
if (alloc_private(dev, sizeof(lsampl_t) * this_board->n_chan) < 0) | ||
return -ENOMEM; | ||
|
||
/* analog output subdevice */ | ||
s = dev->subdevices + 0; | ||
s->type = this_board->type; | ||
s->n_chan = this_board->n_chan; | ||
s->maxdata = (1 << this_board->n_bits) - 1; | ||
s->range_table = this_board->range; | ||
s->insn_write = this_board->winsn; | ||
s->insn_read = this_board->rinsn; | ||
s->insn_bits = this_board->insnbits; | ||
if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO) { | ||
s->subdev_flags = SDF_WRITABLE; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int poc_detach(comedi_device * dev) | ||
{ | ||
/* only free stuff if it has been allocated by _attach */ | ||
if (dev->iobase) | ||
release_region(dev->iobase, this_board->iosize); | ||
|
||
printk("comedi%d: dac02: remove\n", dev->minor); | ||
|
||
return 0; | ||
} | ||
|
||
static int readback_insn(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data) | ||
{ | ||
int chan; | ||
|
||
chan = CR_CHAN(insn->chanspec); | ||
data[0] = ((lsampl_t *) dev->private)[chan]; | ||
|
||
return 1; | ||
} | ||
|
||
/* DAC-02 registers */ | ||
#define DAC02_LSB(a) (2 * a) | ||
#define DAC02_MSB(a) (2 * a + 1) | ||
|
||
static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data) | ||
{ | ||
int temp; | ||
int chan; | ||
int output; | ||
|
||
chan = CR_CHAN(insn->chanspec); | ||
((lsampl_t *) dev->private)[chan] = data[0]; | ||
output = data[0]; | ||
#ifdef wrong | ||
// convert to complementary binary if range is bipolar | ||
if ((CR_RANGE(insn->chanspec) & 0x2) == 0) | ||
output = ~output; | ||
#endif | ||
temp = (output << 4) & 0xf0; | ||
outb(temp, dev->iobase + DAC02_LSB(chan)); | ||
temp = (output >> 4) & 0xff; | ||
outb(temp, dev->iobase + DAC02_MSB(chan)); | ||
|
||
return 1; | ||
} | ||
|
||
static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data) | ||
{ | ||
if (insn->n != 2) | ||
return -EINVAL; | ||
|
||
data[1] = inb(dev->iobase + 0); | ||
data[1] |= (inb(dev->iobase + 1) << 8); | ||
data[1] |= (inb(dev->iobase + 2) << 16); | ||
data[1] |= (inb(dev->iobase + 3) << 24); | ||
|
||
return 2; | ||
} | ||
|
||
static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
comedi_insn * insn, lsampl_t * data) | ||
{ | ||
if (insn->n != 2) | ||
return -EINVAL; | ||
if (data[0]) { | ||
s->state &= ~data[0]; | ||
s->state |= (data[0] & data[1]); | ||
if ((data[0] >> 0) & 0xff) | ||
outb((s->state >> 0) & 0xff, dev->iobase + 0); | ||
if ((data[0] >> 8) & 0xff) | ||
outb((s->state >> 8) & 0xff, dev->iobase + 1); | ||
if ((data[0] >> 16) & 0xff) | ||
outb((s->state >> 16) & 0xff, dev->iobase + 2); | ||
if ((data[0] >> 24) & 0xff) | ||
outb((s->state >> 24) & 0xff, dev->iobase + 3); | ||
} | ||
data[1] = s->state; | ||
|
||
return 2; | ||
} | ||
|
||
COMEDI_INITCLEANUP(driver_poc); |