along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*****************************************************************
+
+Support for pci-das08 card added by Frank M. Hess
+
*/
#include <linux/malloc.h>
#include <linux/delay.h>
#include <8255.h>
+#include <linux/pci.h>
+
+
+#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
+#define PCI_DEVICE_ID_PCIDAS08 0x29
+#define PCIDAS08_SIZE 128
+
+// pci configuration registers
+#define INTCSR 0x4c
+#define INTR1_ENABLE 0x1
+#define INTR1_HIGH_POLARITY 0x2
+#define PCI_INTR_ENABLE 0x40
+#define INTR1_EDGE_TRIG 0x100 // requires high polarity
+#define CNTRL 0x50
+#define CNTRL_DIR 0x2
+#define CNTRL_INTR 0x4
#define DAS08_SIZE 16
#define DAS08_MSB 1
#define DAS08_TRIG_12BIT 1
#define DAS08_STATUS 2
-#define DAS08_EOC (1<<7)
+#define DAS08_EOC (1<<7)
#define DAS08_IRQ (1<<3)
#define DAS08_IP(x) (((x)>>4)&0x7)
#define DAS08_CONTROL 2
-#define DAS08_MUX(x) ((x)<<0)
+#define DAS08_MUX(x) ((x)<<0)
#define DAS08_INTE (1<<3)
#define DAS08_OP(x) ((x)<<4)
UNI_RANGE(0.01)
}};
-enum { das08_pg_none, das08_pgh, das08_pgl, das08_pgm };
+enum { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, das08_pgm};
static comedi_lrange *das08_ai_lranges[]={
&range_bipolar10, /* XXX guess */
+ &range_bipolar5,
&range_das08_pgh,
&range_das08_pgl,
&range_das08_pgm,
static int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 };
static int *das08_gainlists[] = {
+ NULL,
NULL,
das08_pgh_gainlist,
das08_pgl_gainlist,
i8255_offset: 0,
i8254_offset: 0x04,
},
+ {
+ name: "pci-das08",
+ ai: das08_ai_rinsn,
+ ai_nbits: 12,
+ ai_pg: das08_bipolar5,
+ ao: NULL,
+ ao_nbits: 0,
+ di: das08_di_rbits,
+ do_: das08_do_wbits,
+ i8255_offset: 8,
+ i8254_offset: 0,
+ },
#if 0
{
name: "das08/f",
struct das08_private_struct{
unsigned int do_bits;
unsigned int *pg_gainlist;
+ struct pci_dev *pdev; // struct for pci-das08
+ unsigned int pci_iobase; // additional base address for pci-das08
};
#define devpriv ((struct das08_private_struct *)dev->private)
inb(dev->iobase+DAS08_MSB);
/* set multiplexer */
- outb_p(DAS08_MUX(chan) | devpriv->do_bits,dev->iobase+DAS08_CONTROL);
-
- if(thisboard->ai_pg!=das08_pg_none){
+ outb(DAS08_MUX(chan) | devpriv->do_bits,dev->iobase+DAS08_CONTROL);
+
+ if(s->range_table->length > 1){
/* set gain/range */
range = CR_RANGE(insn->chanspec);
- outb_p(devpriv->pg_gainlist[range],dev->iobase+DAS08AO_GAIN_CONTROL);
+ outb(devpriv->pg_gainlist[range],dev->iobase+DAS08AO_GAIN_CONTROL);
}
- /* How long should we wait for MUX to settle? */
- //udelay(5);
+ /* wait for MUX to settle */
+ udelay(2);
for(n=0;n<insn->n;n++){
/* trigger conversion */
{
comedi_subdevice *s;
int ret;
- int iobase;
+ int iobase, pci_iobase = 0;
+ struct pci_dev *pdev;
+
+ if((ret=alloc_private(dev,sizeof(struct das08_private_struct)))<0)
+ return ret;
+
+ printk("comedi%d: das08", dev->minor);
+ // deal with a pci board
+ if(strcmp(thisboard->name, "pci-das08") == 0)
+ {
+ if(it->options[0] || it->options[1]){
+ printk(": bus %i, slot %i",
+ it->options[0], it->options[1]);
+ }
+ printk("\n");
+ // find card
+ pci_for_each_dev(pdev){
+ if(pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS &&
+ pdev->device == PCI_DEVICE_ID_PCIDAS08){
+ if(it->options[0] || it->options[1]){
+ if(pdev->bus->number == it->options[0] &&
+ PCI_SLOT(pdev->devfn) == it->options[1]){
+ break;
+ }
+ }else{
+ break;
+ }
+ }
+ }
+ if(!pdev){
+ printk("No pci-das08 card found\n");
+ return -EIO;
+ }
+ devpriv->pdev = pdev;
+ // read base addresses
+ pci_iobase = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+ iobase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
+
+ // reserve io ports for 9052 pci chip
+ if(check_region(pci_iobase,PCIDAS08_SIZE)<0){
+ printk(" I/O port conflict\n");
+ return -EIO;
+ }
+ request_region(pci_iobase,PCIDAS08_SIZE,"das08");
+ devpriv->pci_iobase = pci_iobase;
+
+#if 0
+/* We could enable to pci-das08's interrupt here to make it possible
+ * to do timed input in this driver, but there is little point since
+ * conversions would have to be started by the interrupt handler
+ * so you might as well use comedi_rt_timer to emulate commands
+ */
+ /* set source of interrupt trigger to counter2 output */
+ outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL);
+ /* Enable local interrupt 1 and pci interrupt */
+ outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR );
+#endif
+
+ }else{
+ iobase=it->options[0];
+ printk(": 0x%04x\n",iobase);
+ }
+
- iobase=it->options[0];
- printk("comedi%d: das08: 0x%04x",dev->minor,iobase);
if(check_region(iobase,DAS08_SIZE)<0){
printk(" I/O port conflict\n");
return -EIO;
}
+ request_region(iobase,DAS08_SIZE,"das08");
+ dev->iobase = iobase;
dev->board_name = thisboard->name;
dev->n_subdevices=5;
if((ret=alloc_subdevices(dev))<0)
return ret;
- if((ret=alloc_private(dev,sizeof(struct das08_private_struct)))<0)
- return ret;
-
- request_region(iobase,DAS08_SIZE,"das08");
- dev->iobase = iobase;
s=dev->subdevices+0;
/* ai */
if(dev->iobase)
release_region(dev->iobase,DAS08_SIZE);
+ if(devpriv){
+ if(devpriv->pci_iobase){
+ release_region(devpriv->pci_iobase, PCIDAS08_SIZE);
+ }
+ }
+
return 0;
}