hardware driver for Winsystems PCM-A/D12 and PCM-A/D16
COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@stm.lbl.gov>
+ Copyright (C) 2000,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
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/comedidev.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/timex.h>
#include <linux/timer.h>
#include <asm/io.h>
-#include <comedi_module.h>
#define PCMAD_SIZE 4
#define PCMAD_MSB 2
#define PCMAD_CONVERT 1
-static int pcmad_attach(comedi_device *dev,comedi_devconfig *it);
-static int pcmad_detach(comedi_device *dev);
-static int pcmad_recognize(char *name);
-comedi_driver driver_pcmad={
- driver_name: "pcmad",
- module: THIS_MODULE,
- attach: pcmad_attach,
- detach: pcmad_detach,
- recognize: pcmad_recognize,
-};
-
struct pcmad_board_struct{
char *name;
int n_ai_bits;
},
};
#define this_board ((struct pcmad_board_struct *)(dev->board_ptr))
-static int n_pcmad_boards=(sizeof(pcmad_boards)/sizeof(pcmad_boards[0]));
+#define n_pcmad_boards (sizeof(pcmad_boards)/sizeof(pcmad_boards[0]))
struct pcmad_priv_struct{
int differential;
};
#define devpriv ((struct pcmad_priv_struct *)dev->private)
+static int pcmad_attach(comedi_device *dev,comedi_devconfig *it);
+static int pcmad_detach(comedi_device *dev);
+comedi_driver driver_pcmad={
+ driver_name: "pcmad",
+ module: THIS_MODULE,
+ attach: pcmad_attach,
+ detach: pcmad_detach,
+ board_name: pcmad_boards,
+ num_names: n_pcmad_boards,
+ offset: sizeof(pcmad_boards[0]),
+};
+COMEDI_INITCLEANUP(driver_pcmad);
+
#define TIMEOUT 100
-static int pcmad_ai_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
+static int pcmad_ai_insn_read(comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
{
- int i,msb,lsb;
+ int i;
int chan;
- int data;
+ int n;
- chan=CR_CHAN(it->chanlist[0]);
+ chan=CR_CHAN(insn->chanspec);
- outb(chan,dev->iobase+PCMAD_CONVERT);
+ for(n=0;n<insn->n;n++){
+ outb(chan,dev->iobase+PCMAD_CONVERT);
- for(i=0;i<TIMEOUT;i++){
- if((inb(dev->iobase+PCMAD_STATUS)&0x3) == 0x3)
- break;
- }
- lsb=inb(dev->iobase+PCMAD_LSB);
- msb=inb(dev->iobase+PCMAD_MSB);
-
- data=(msb<<8)|(lsb);
+ for(i=0;i<TIMEOUT;i++){
+ if((inb(dev->iobase+PCMAD_STATUS)&0x3) == 0x3)
+ break;
+ }
+ data[n]=inb(dev->iobase+PCMAD_LSB);
+ data[n]|=(inb(dev->iobase+PCMAD_MSB)<<8);
- if(devpriv->twos_comp){
- data ^= (1<<(this_board->n_ai_bits-1));
+ if(devpriv->twos_comp){
+ data[n] ^= (1<<(this_board->n_ai_bits-1));
+ }
}
- it->data[0]=data;
- return 1;
-}
-
-static int pcmad_recognize(char *name)
-{
- int i;
-
- for(i=0;i<n_pcmad_boards;i++){
- if(!strcmp(pcmad_boards[i].name,name))
- return i;
- }
-
- return -1;
+ return n;
}
/*
{
int ret;
comedi_subdevice *s;
+ int iobase;
- dev->iobase=it->options[0];
- printk("comedi%d: pcmad: 0x%04x ",dev->minor,dev->iobase);
- if(check_region(dev->iobase,PCMAD_SIZE)<0){
+ iobase=it->options[0];
+ printk("comedi%d: pcmad: 0x%04x ",dev->minor,iobase);
+ if(check_region(iobase,PCMAD_SIZE)<0){
printk("I/O port conflict\n");
return -EIO;
}
- request_region(dev->iobase,PCMAD_SIZE,"pcmad");
- dev->iobase=dev->iobase;
- dev->iosize=PCMAD_SIZE;
+ request_region(iobase,PCMAD_SIZE,"pcmad");
+ dev->iobase=iobase;
dev->n_subdevices=1;
if((ret=alloc_subdevices(dev))<0)
if((ret=alloc_private(dev,sizeof(struct pcmad_priv_struct)))<0)
return ret;
- dev->board_ptr = pcmad_boards+dev->board;
+ dev->board_name = this_board->name;
s=dev->subdevices+0;
s->type=COMEDI_SUBD_AI;
s->subdev_flags=SDF_READABLE;
s->n_chan=16; /* XXX */
s->len_chanlist=1;
- s->trig[0]=pcmad_ai_mode0;
+ s->insn_read=pcmad_ai_insn_read;
s->maxdata=(1<<this_board->n_ai_bits)-1;
s->range_table=&range_unknown;
if(dev->irq){
free_irq(dev->irq,dev);
}
- release_region(dev->iobase,dev->iosize);
+ if(dev->iobase)
+ release_region(dev->iobase,PCMAD_SIZE);
return 0;
}
-
-COMEDI_INITCLEANUP(driver_pcmad);
-