added support for pci-das08 card
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 25 May 2001 21:39:54 +0000 (21:39 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 25 May 2001 21:39:54 +0000 (21:39 +0000)
comedi/drivers/das08.c

index 6ce8293eb39b631245eaf0e3415398ab401cdcb0..4a1e767803021dd532d687bc30a94a3bc05da8a9 100644 (file)
     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)
 
@@ -170,10 +190,11 @@ static comedi_lrange range_das08_pgm = { 9, {
        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,
@@ -184,6 +205,7 @@ static int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 };
 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,
@@ -308,6 +330,18 @@ static struct das08_board_struct das08_boards[]={
        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",
@@ -332,6 +366,8 @@ static struct das08_board_struct das08_boards[]={
 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)
@@ -354,16 +390,16 @@ static int das08_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *in
        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 */
@@ -498,25 +534,82 @@ static int das08_attach(comedi_device *dev,comedi_devconfig *it)
 {
        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 */
@@ -593,6 +686,12 @@ static int das08_detach(comedi_device *dev)
        if(dev->iobase)
                release_region(dev->iobase,DAS08_SIZE);
 
+       if(devpriv){
+               if(devpriv->pci_iobase){
+                       release_region(devpriv->pci_iobase, PCIDAS08_SIZE);
+               }
+       }
+
        return 0;
 }