starting to add ai command support, completely nonfunctional so far
authorFrank Mori Hess <fmhess@speakeasy.net>
Thu, 6 Sep 2001 23:51:32 +0000 (23:51 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Thu, 6 Sep 2001 23:51:32 +0000 (23:51 +0000)
comedi/drivers/cb_pcidas64.c
comedi/drivers/plx9060.h [new file with mode: 0644]

index 3bb43e2200b81efba7c944781e56ce4839eadec7..b1806e988f991b43303365c93ad76e0978fb64f0 100644 (file)
@@ -37,8 +37,12 @@ TODO:
        command support
        calibration subdevice
        user counter subdevice
-       there are a number of boards this driver could support, but does not since
-               I don't know the pci device id numbers
+       there are a number of boards this driver will support when they are
+               fully released, but does not since yet since the pci device id numbers\r
+               are not yet available.
+       add plx9080 stuff to make interrupts work\r
+       need to take care to prevent ai and ao from affecting each others register bits\r
+       support prescaled 100khz for slow pacing
 */
 
 #include <linux/kernel.h>
@@ -58,6 +62,7 @@ TODO:
 #include <linux/comedidev.h>
 #include "8253.h"
 #include "8255.h"
+#include "plx9060.h"
 
 #define PCIDAS64_DEBUG // enable debugging code
 //#undef PCIDAS64_DEBUG        // disable debugging code
@@ -65,6 +70,7 @@ TODO:
 // PCI vendor number of ComputerBoards/MeasurementComputing
 #define PCI_VENDOR_ID_CB       0x1307
 #define TIMER_BASE 25  // 40MHz master clock
+#define PRESCALED_TIMER_BASE   10000   // 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday
 
 /* PCI-DAS64xxx base addresses */
 
@@ -77,18 +83,37 @@ TODO:
 #define MAIN_IOSIZE 0x302
 #define DIO_COUNTER_IOSIZE 0x29
 
-// plx pci9080 configuration registers
-// XXX could steal plx9060 header file from kernel
-
 // devpriv->main_iobase registers
 // write-only
 #define INTR_ENABLE_REG        0x0     // interrupt enable register
+#define    EN_ADC_OVERRUN_BIT  0x8000  // enable adc overrun status bit
+#define    EN_DAC_UNDERRUN_BIT 0x4000  // enable dac underrun status bit
+#define    EN_ADC_DONE_INTR_BIT        0x8     // enable adc aquisition done interrupt
+#define    EN_ADC_INTR_SRC_BIT 0x4     // enable adc interrupt source
+#define    ADC_INTR_SRC_MASK   0x3     // bits that set adc interrupt source
+#define    ADC_INTR_QFULL_BITS 0x0     // interrupt fifo quater full
+#define    ADC_INTR_EOC_BITS   0x1     // interrupt end of conversion
+#define    ADC_INTR_EOSCAN_BITS        0x2     // interrupt end of scan
+#define    ADC_INTR_EOSEQ_BITS 0x3     // interrupt end of sequence (probably wont use this it's pretty fancy)
 #define HW_CONFIG_REG  0x2     // hardware config register
 #define    HW_CONFIG_DUMMY_BITS        0x2400  // bits that don't do anything yet but are given default values
+#define    HW_CONFIG_DUMMY_BITS_6402   0x0400  // dummy bits in 6402 manual are slightly different, probably doesn't matter
+#define    EXT_QUEUE   0x200   // use external channel/gain queue (more versatile than internal queue)
+#define FIFO_SIZE_REG  0x4     // allows adjustment of fifo sizes, we will always use maximum
+#define    FIFO_SIZE_DUMMY_BITS        0xf038  // bits that don't do anything yet but are given default values
+#define    ADC_FIFO_SIZE_MASK  0x7     // bits that set adc fifo size
+#define    ADC_FIFO_8K_BITS    0x0     // 8 kilosample adc fifo
+#define    DAC_FIFO_SIZE_MASK  0xf00   // bits that set dac fifo size
+#define    DAC_FIFO_16K_BITS 0x0
 #define ADC_CONTROL0_REG       0x10    // adc control register 0
+#define    TRIG1_FALLING_BIT   0x20    // trig 1 uses falling edge
+#define    ADC_EXT_CONV_FALLING_BIT    0x800   // external pacing uses falling edge
 #define    ADC_ENABLE_BIT      0x8000  // master adc enable
 #define ADC_CONTROL1_REG       0x12    // adc control register 1
 #define    SW_NOGATE_BIT       0x40    // disables software gate of adc
+#define    ADC_MODE_BITS(x)    (((x) & 0xf) << 12)
+#define ADC_SAMPLE_INTERVAL_LOWER_REG  0x16    // lower 16 bits of sample interval counter
+#define ADC_SAMPLE_INTERVAL_UPPER_REG  0x18    // upper 8 bits of sample interval counter
 #define ADC_CONVERT_REG        0x24    // initiates single conversion
 #define ADC_QUEUE_CLEAR_REG    0x26    // clears adc queue
 #define ADC_QUEUE_LOAD_REG     0x28    // loads adc queue
@@ -337,17 +362,19 @@ comedi_driver driver_cb_pcidas={
 static int ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
 static int ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
 static int ao_readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
-//static int ai_cmd(comedi_device *dev,comedi_subdevice *s);
-//static int ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
+static int ai_cmd(comedi_device *dev,comedi_subdevice *s);
+static int ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
 //static int ao_cmd(comedi_device *dev,comedi_subdevice *s);
 //static int ao_inttrig(comedi_device *dev, comedi_subdevice *subdev, unsigned int trig_num);
 //static int ao_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
-//static void handle_interrupt(int irq, void *d, struct pt_regs *regs);
-//static int ai_cancel(comedi_device *dev, comedi_subdevice *s);
+static void handle_interrupt(int irq, void *d, struct pt_regs *regs);
+static int ai_cancel(comedi_device *dev, comedi_subdevice *s);
 //static int ao_cancel(comedi_device *dev, comedi_subdevice *s);
 static int dio_callback(int dir, int port, int data, void *arg);
 static int di_rbits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
 static int do_wbits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+static void check_adc_timing(comedi_cmd *cmd);
+static unsigned int get_divisor(unsigned int ns, unsigned int flags);
 
 /*
  * A convenient macro that defines init_module() and cleanup_module(),
@@ -584,7 +611,7 @@ printk(" stc hardware revision %i\n", devpriv->hw_revision);
 
        // calibration subd XXX
        s = dev->subdevices + 6;
-       s->type = COMEDI_SUBD_UNUSED;
+       s->type = COMEDI_SUBD_UNUSED; 
 
        return 0;
 }
@@ -634,14 +661,14 @@ static int ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsa
 
        // disable card's interrupt sources
        writew(0, devpriv->main_iobase + INTR_ENABLE_REG);
+\r
+       /* disable pacing, triggering, etc */\r
+       writew(ADC_ENABLE_BIT, devpriv->main_iobase + ADC_CONTROL0_REG);\r
+       writew(0, devpriv->main_iobase + ADC_CONTROL1_REG);\r
 
        // use internal queue
        writew(HW_CONFIG_DUMMY_BITS, devpriv->main_iobase + HW_CONFIG_REG);
 
-       /* disable pacing, triggering, etc */
-       writew(ADC_ENABLE_BIT, devpriv->main_iobase + ADC_CONTROL0_REG);
-       writew(0, devpriv->main_iobase + ADC_CONTROL1_REG);
-
        // load internal queue
        bits = 0;
        // set channel
@@ -683,6 +710,239 @@ static int ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsa
        return n;
 }
 
+static int ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd)
+{      int err = 0;
+       int tmp;
+       unsigned int tmp_arg, tmp_arg2;
+       int i;
+       int aref;
+
+       /* step 1: make sure trigger sources are trivially valid */
+
+       tmp = cmd->start_src;
+       cmd->start_src &= TRIG_NOW | TRIG_EXT;
+       if(!cmd->start_src || tmp != cmd->start_src) err++;
+
+       tmp = cmd->scan_begin_src;
+       cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
+       if(!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++;
+
+       tmp = cmd->convert_src;
+       cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
+       if(!cmd->convert_src || tmp != cmd->convert_src) err++;
+
+       tmp = cmd->scan_end_src;
+       cmd->scan_end_src &= TRIG_COUNT;
+       if(!cmd->scan_end_src || tmp != cmd->scan_end_src) err++;
+
+       tmp=cmd->stop_src;
+       cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
+       if(!cmd->stop_src || tmp != cmd->stop_src) err++;
+
+       if(err) return 1;
+
+       /* step 2: make sure trigger sources are unique and mutually compatible */
+
+       // uniqueness check
+       if(cmd->start_src != TRIG_NOW &&
+               cmd->start_src != TRIG_EXT) err++;
+       if(cmd->scan_begin_src != TRIG_TIMER &&
+               cmd->scan_begin_src != TRIG_FOLLOW) err++;
+       if(cmd->convert_src != TRIG_TIMER &&
+               cmd->convert_src != TRIG_EXT) err++;
+       if(cmd->stop_src != TRIG_COUNT &&
+               cmd->stop_src != TRIG_NONE &&
+               cmd->stop_src != TRIG_EXT) err++;
+
+       // compatibility check
+       if(cmd->convert_src == TRIG_EXT &&\r
+               cmd->scan_begin_src == TRIG_TIMER)\r
+               err++;\r
+
+       if(err) return 2;
+
+       /* step 3: make sure arguments are trivially compatible */
+
+       if(cmd->start_arg != 0)
+       {
+               cmd->start_arg = 0;
+               err++;
+       }
+       if(cmd->convert_src == TRIG_TIMER)
+       {
+               if(cmd->convert_arg < thisboard->ai_speed)
+               {
+                       cmd->convert_arg = thisboard->ai_speed;
+                       err++;
+               }
+               if(cmd->scan_begin_src == TRIG_TIMER)\r
+               {\r
+                       // if scans are timed faster than conversion rate allows\r
+                       if(cmd->convert_arg * cmd->chanlist_len > cmd->scan_begin_arg)\r
+                       {\r
+                               cmd->scan_begin_arg = cmd->convert_arg * cmd->chanlist_len;\r
+                               err++;\r
+                       }\r
+               }\r
+       }
+\r
+       if(!cmd->chanlist_len)
+       {
+               cmd->chanlist_len = 1;
+               err++;
+       }
+       if(cmd->scan_end_arg != cmd->chanlist_len)
+       {
+               cmd->scan_end_arg = cmd->chanlist_len;
+               err++;
+       }
+
+       switch(cmd->stop_src)
+       {
+               case TRIG_EXT:
+                       if(cmd->stop_arg)
+                       {
+                               cmd->stop_arg = 0;
+                               err++;
+                       }
+                       break;
+               case TRIG_COUNT:
+                       if(!cmd->stop_arg)
+                       {
+                               cmd->stop_arg = 1;
+                               err++;
+                       }
+                       break;
+               case TRIG_NONE:
+                       if(cmd->stop_arg != 0)
+                       {
+                               cmd->stop_arg = 0;
+                               err++;
+                       }
+                       break;
+               default:
+                       break;
+       }
+
+       if(err) return 3;
+
+       /* step 4: fix up any arguments */
+
+       if(cmd->convert_src == TRIG_TIMER)
+       {
+               tmp_arg = cmd->convert_arg;
+               tmp_arg2 = cmd->scan_begin_arg;
+               check_adc_timing(cmd);
+               if(tmp_arg != cmd->convert_arg) err++;
+               if(tmp_arg2 != cmd->scan_begin_arg) err++;
+       }
+
+       if(err) return 4;
+
+       // make sure user is doesn't change analog reference mid chanlist
+       if(cmd->chanlist)
+       {
+               aref = CR_AREF(cmd->chanlist[0]);
+               for(i = 1; i < cmd->chanlist_len; i++)
+               {
+                       if(aref != CR_AREF(cmd->chanlist[i]))
+                       {
+                               comedi_error(dev, "all elements in chanlist must use the same analog reference");
+                               err++;
+                               break;
+                       }
+               }
+       }
+
+       if(err) return 5;
+
+       return 0;
+}
+
+static int ai_cmd(comedi_device *dev,comedi_subdevice *s)
+{
+       comedi_async *async = s->async;
+       comedi_cmd *cmd = &async->cmd;
+       unsigned int bits;
+       unsigned int counter_value;
+
+       // disable card's interrupt sources
+       writew(0, devpriv->main_iobase + INTR_ENABLE_REG);
+
+       /* disable pacing, triggering, etc */
+       writew(0, devpriv->main_iobase + ADC_CONTROL0_REG);
+       writew(0, devpriv->main_iobase + ADC_CONTROL1_REG);
+
+       // use external queue
+       writew(EXT_QUEUE | HW_CONFIG_DUMMY_BITS, devpriv->main_iobase + HW_CONFIG_REG);
+
+       // set fifo size
+       writew(ADC_FIFO_8K_BITS | FIFO_SIZE_DUMMY_BITS, devpriv->main_iobase + FIFO_SIZE_REG);
+
+       // set conversion pacing
+       if(cmd->convert_src == TRIG_TIMER)
+       {
+               check_adc_timing(cmd);
+               // supposed to load counter with desired divisor minus 3
+               counter_value = cmd->scan_begin_arg / TIMER_BASE - 3;
+               // load lower 16 bits
+               writew(counter_value & 0xffff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+               // load upper 8 bits
+               writew((counter_value >> 16) & 0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+       }
+
+#if 0
+       // load external queue
+       bits = 0;
+       // set channel
+       bits |= CHAN_BITS(CR_CHAN(insn->chanspec));
+       // set gain
+       bits |= GAIN_BITS(CR_RANGE(insn->chanspec));
+       // set unipolar / bipolar
+       bits |= UNIP_BIT(CR_RANGE(insn->chanspec));
+       // set single-ended / differential
+       if(CR_AREF(insn->chanspec) != AREF_DIFF)
+               bits |= SE_BIT;
+       // set stop channel
+       writew(CHAN_BITS(CR_CHAN(insn->chanspec)), devpriv->main_iobase + ADC_QUEUE_HIGH_REG);
+       // set start channel, and rest of settings
+       writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
+#endif
+
+       // clear adc buffer
+       writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
+
+       // enable interrupts
+       bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT;
+       if(cmd->flags & TRIG_WAKE_EOS)
+               bits |= ADC_INTR_EOSCAN_BITS;
+       writew(bits, devpriv->main_iobase + INTR_ENABLE_REG);
+
+       /* set mode, disable software conversion gate */
+       bits = SW_NOGATE_BIT;
+       if(cmd->convert_src == TRIG_EXT)
+               bits |= ADC_MODE_BITS(13);      // good old mode 13
+       else
+               bits |= ADC_MODE_BITS(8);       // mode 8.  What else could you need?
+       writew(bits, devpriv->main_iobase + ADC_CONTROL1_REG);
+
+       /* enable pacing, triggering, etc */
+       bits = ADC_ENABLE_BIT;
+       writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG);
+
+       return 0;
+}
+
+static void handle_interrupt(int irq, void *d, struct pt_regs *regs)
+{
+       return;
+}
+
+static int ai_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+       return 0;
+}
+
 static int ao_winsn(comedi_device *dev, comedi_subdevice *s,
        comedi_insn *insn, lsampl_t *data)
 {
@@ -762,3 +1022,56 @@ static int do_wbits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn,
        return 2;
 }
 
+// utility function that rounds desired timing to an achievable time.
+// adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number
+static void check_adc_timing(comedi_cmd *cmd)
+{
+       unsigned int convert_divisor, scan_divisor;
+       const int min_convert_divisor = 3;
+       const int max_convert_divisor = 0xffffff + min_convert_divisor;
+       unsigned long long max_scan_divisor, min_scan_divisor;
+
+       if(cmd->convert_src == TRIG_TIMER)
+       {
+               convert_divisor = get_divisor(cmd->convert_arg, cmd->flags);
+               if(convert_divisor > max_convert_divisor) convert_divisor = max_convert_divisor;
+               if(convert_divisor < min_convert_divisor) convert_divisor = min_convert_divisor;
+               cmd->convert_arg = convert_divisor * TIMER_BASE;
+
+               if(cmd->scan_begin_src == TRIG_TIMER)
+               {
+                       scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags);
+                       min_scan_divisor = convert_divisor * cmd->chanlist_len;
+                       max_scan_divisor = min_scan_divisor + 0xffffff;
+                       if(scan_divisor > max_scan_divisor) scan_divisor = max_scan_divisor;
+                       if(scan_divisor < min_scan_divisor) scan_divisor = min_scan_divisor;
+                       cmd->scan_begin_arg = scan_divisor * TIMER_BASE;
+               }
+       }
+
+       return;
+}
+
+/* Gets nearest achievable timing given master clock speed, does not
+ * take into account possible minimum/maximum divisor values.  Used
+ * by other timing checking functions. */
+static unsigned int get_divisor(unsigned int ns, unsigned int flags)
+{
+       unsigned int divisor;
+
+       switch(flags & TRIG_ROUND_MASK)
+       {
+               case TRIG_ROUND_UP:
+                       divisor = (ns + TIMER_BASE - 1) / TIMER_BASE;
+                       break;
+               case TRIG_ROUND_DOWN:
+                       divisor = ns / TIMER_BASE;
+                       break;
+               case TRIG_ROUND_NEAREST:
+               default:
+                       divisor = (ns + TIMER_BASE / 2) / TIMER_BASE;
+                       break;
+       }
+
+       return divisor;
+}
diff --git a/comedi/drivers/plx9060.h b/comedi/drivers/plx9060.h
new file mode 100644 (file)
index 0000000..9cf6dca
--- /dev/null
@@ -0,0 +1,296 @@
+/* plx9060.h
+ *
+ * I took this file from the wanXL device driver in the linux kernel,
+ * for the register offsets and bit definitions.  Minor modifications,
+ * stripped out stuff that was specifically for the wanXL driver.  I
+ * use this for the plx9080 chip used in the cards supported by
+ * the cb_pcidas64.c driver.
+ * Frank Mori Hess
+ ********************************************************************
+ *
+ * SBE wanXL device driver
+ * Copyright (C) 1999 RG Studio s.c., http://www.rgstudio.com.pl/
+ * Written by Krzysztof Halasa <khc@rgstudio.com.pl>
+ *
+ * Portions (C) SBE Inc., used by permission.
+ *
+ * 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.
+ */
+
+#ifndef __COMEDI_PLX9060_H
+#define __COMEDI_PLX9060_H
+
+/**********************************************************************
+**            Register Offsets and Bit Definitions
+**
+** Note: All offsets zero relative.  IE. Some standard base address
+** must be added to the Register Number to properly access the register.
+**
+**********************************************************************/
+
+#define PLX_LASMAP_REG         0x0000 /* L, Local Addr Space Range Register */
+#define  LASMAP_IO         0x00000001 /* Map to: 1=I/O, 0=Mem */
+#define  LMAP_ANY32        0x00000000 /* Locate anywhere in 32 bit */
+#define  LMAP_LT1MB        0x00000002 /* Locate in 1st meg */
+#define  LMAP_ANY64        0x00000004 /* Locate anywhere in 64 bit */
+
+#define PLX_LASRNG_REG         0x0004 /* L, Local Addr Space Range Register */
+#define  LRNG_EN           0x00000001 /* Enable slave decode */
+#define  LRNG_IO           0xFFFFFFFC /* Decode bits if I/O spc */
+#define  LRNG_MEM          0xFFFFFFF0 /* Decode bits if mem spc */
+
+
+/* Note: The Local Arbitration Register is only present on the 9060ES part.
+**       The 9060 part with DMA does not have this register
+*/
+#define PLX_LCLARB_REG         0x0008 /* L, Local Arbitration Register */
+#define  LARB_LLT          0x0000000F /* Local Bus Latency Timer */
+#define  LARB_LPT          0x000000F0 /* Local Bus Pause Timer */
+#define  LARB_LTEN         0x00000100 /* Latency Timer Enable */
+#define  LARB_LPEN         0x00000200 /* Pause Timer Enable */
+#define  LARB_BREQ         0x00000400 /* Local Bus BREQ Enable */
+
+/* Note: The Expansion ROM  stuff is only relevant to the PC environment.
+**       This expansion ROM code is executed by the host CPU at boot time.
+**       For this reason no bit definitions are provided here.
+*/
+#define PLX_ROMRNG_REG         0x0010 /* L, Expn ROM Space Range Register */
+#define PLX_ROMMAP_REG         0x0014 /* L, Local Addr Space Range Register */
+
+
+#define PLX_REGION_REG         0x0018 /* L, Local Bus Region Descriptor */
+#define  RGN_WIDTH         0x00000002 /* Local bus width bits */
+#define  RGN_8BITS         0x00000000 /* 08 bit Local Bus */
+#define  RGN_16BITS        0x00000001 /* 16 bit Local Bus */
+#define  RGN_32BITS        0x00000002 /* 32 bit Local Bus */
+#define  RGN_MWS           0x0000003C /* Memory Access Wait States */
+#define  RGN_0MWS          0x00000000
+#define  RGN_1MWS          0x00000004
+#define  RGN_2MWS          0x00000008
+#define  RGN_3MWS          0x0000000C
+#define  RGN_4MWS          0x00000010
+#define  RGN_6MWS          0x00000018
+#define  RGN_8MWS          0x00000020
+#define  RGN_MRE           0x00000040 /* Memory Space Ready Input Enable */
+#define  RGN_MBE           0x00000080 /* Memory Space Bterm Input Enable */
+#define  RGN_RWS           0x003C0000 /* Expn ROM Wait States */
+#define  RGN_RRE           0x00400000 /* ROM Space Ready Input Enable */
+#define  RGN_RBE           0x00800000 /* ROM Space Bterm Input Enable */
+#define  RGN_MBEN          0x01000000 /* Memory Space Burst Enable */
+#define  RGN_RBEN          0x04000000 /* ROM Space Burst Enable */
+#define  RGN_THROT         0x08000000 /* De-assert TRDY when FIFO full */
+#define  RGN_TRD           0xF0000000 /* Target Ready Delay /8 */
+
+
+#define PLX_DMRNG_REG          0x001C /* L, Direct Master Range Register */
+
+#define PLX_LBAPMEM_REG        0x0020 /* L, Lcl Base Addr for PCI mem space */
+
+#define PLX_LBAPIO_REG         0x0024 /* L, Lcl Base Addr for PCI I/O space */
+
+#define PLX_DMMAP_REG          0x0028 /* L, Direct Master Remap Register */
+#define  DMM_MAE           0x00000001 /* Direct Mstr Memory Acc Enable */
+#define  DMM_IAE           0x00000002 /* Direct Mstr I/O Acc Enable */
+#define  DMM_LCK           0x00000004 /* LOCK Input Enable */
+#define  DMM_PF4           0x00000008 /* Prefetch 4 Mode Enable */
+#define  DMM_THROT         0x00000010 /* Assert IRDY when read FIFO full */
+#define  DMM_PAF0          0x00000000 /* Programmable Almost fill level */
+#define  DMM_PAF1          0x00000020 /* Programmable Almost fill level */
+#define  DMM_PAF2          0x00000040 /* Programmable Almost fill level */
+#define  DMM_PAF3          0x00000060 /* Programmable Almost fill level */
+#define  DMM_PAF4          0x00000080 /* Programmable Almost fill level */
+#define  DMM_PAF5          0x000000A0 /* Programmable Almost fill level */
+#define  DMM_PAF6          0x000000C0 /* Programmable Almost fill level */
+#define  DMM_PAF7          0x000000D0 /* Programmable Almost fill level */
+#define  DMM_MAP           0xFFFF0000 /* Remap Address Bits */
+
+#define PLX_CAR_REG            0x002C /* L, Configuration Address Register */
+#define  CAR_CT0           0x00000000 /* Config Type 0 */
+#define  CAR_CT1           0x00000001 /* Config Type 1 */
+#define  CAR_REG           0x000000FC /* Register Number Bits */
+#define  CAR_FUN           0x00000700 /* Function Number Bits */
+#define  CAR_DEV           0x0000F800 /* Device Number Bits */
+#define  CAR_BUS           0x00FF0000 /* Bus Number Bits */
+#define  CAR_CFG           0x80000000 /* Config Spc Access Enable */
+
+
+#define PLX_DBR_IN_REG         0x0060 /* L, PCI to Local Doorbell Register */
+
+#define PLX_DBR_OUT_REG        0x0064 /* L, Local to PCI Doorbell Register */
+
+#define PLX_INTRCS_REG         0x0068 /* L, Interrupt Control/Status Reg */
+#define  ICS_AERR          0x00000001 /* Assert LSERR on ABORT */
+#define  ICS_PERR          0x00000002 /* Assert LSERR on Parity Error */
+#define  ICS_SERR          0x00000004 /* Generate PCI SERR# */
+#define  ICS_PIE           0x00000100 /* PCI Interrupt Enable */
+#define  ICS_PDIE          0x00000200 /* PCI Doorbell Interrupt Enable */
+#define  ICS_PAIE          0x00000400 /* PCI Abort Interrupt Enable */
+#define  ICS_PLIE          0x00000800 /* PCI Local Int Enable */
+#define  ICS_RAE           0x00001000 /* Retry Abort Enable */
+#define  ICS_PDIA          0x00002000 /* PCI Doorbell Interrupt Active */
+#define  ICS_PAIA          0x00004000 /* PCI Abort Interrupt Active */
+#define  ICS_LIA           0x00008000 /* Local Interrupt Active */
+#define  ICS_LIE           0x00010000 /* Local Interrupt Enable */
+#define  ICS_LDIE          0x00020000 /* Local Doorbell Int Enable */
+#define  ICS_DMA0_E        0x00040000 /* DMA #0 Interrupt Enable */
+#define  ICS_DMA1_E        0x00080000 /* DMA #1 Interrupt Enable */
+#define  ICS_LDIA          0x00100000 /* Local Doorbell Int Active */
+#define  ICS_DMA0_A        0x00200000 /* DMA #0 Interrupt Active */
+#define  ICS_DMA1_A        0x00400000 /* DMA #1 Interrupt Active */
+#define  ICS_BIA           0x00800000 /* BIST Interrupt Active */
+#define  ICS_TA_DM         0x01000000 /* Target Abort - Direct Master */
+#define  ICS_TA_DMA0       0x02000000 /* Target Abort - DMA #0 */
+#define  ICS_TA_DMA1       0x04000000 /* Target Abort - DMA #1 */
+#define  ICS_TA_RA         0x08000000 /* Target Abort - Retry Timeout */
+
+#define PLX_CONTROL_REG        0x006C /* L, EEPROM Cntl & PCI Cmd Codes */
+#define  CTL_RDMA          0x0000000F /* DMA Read Command */
+#define  CTL_WDMA          0x000000F0 /* DMA Write Command */
+#define  CTL_RMEM          0x00000F00 /* Memory Read Command */
+#define  CTL_WMEM          0x0000F000 /* Memory Write Command */
+#define  CTL_USER0         0x00010000 /* USER0 pin control bit */
+#define  CTL_USER1         0x00020000 /* USER1 pin control bit */
+#define  CTL_EE_CLK        0x01000000 /* EEPROM Clock line */
+#define  CTL_EE_CS         0x02000000 /* EEPROM Chip Select */
+#define  CTL_EE_W          0x04000000 /* EEPROM Write bit */
+#define  CTL_EE_R          0x08000000 /* EEPROM Read bit */
+#define  CTL_EECHK         0x10000000 /* EEPROM Present bit */
+#define  CTL_EERLD         0x20000000 /* EEPROM Reload Register */
+#define  CTL_RESET         0x40000000 /* !! Adapter Reset !! */
+#define  CTL_READY         0x80000000 /* Local Init Done */
+
+/*
+ * Accesses near the end of memory can cause the PLX chip
+ * to pre-fetch data off of end-of-ram.  Limit the size of
+ * memory so host-side accesses cannot occur.
+ */
+
+#define PLX_PREFETCH   32
+
+/*
+ * The PCI Interface, via the PCI-9060 Chip, has up to eight (8) Mailbox
+ * Registers.  The PUTS (Power-Up Test Suite) handles the board-side
+ * interface/interaction using the first 4 registers.  Specifications for
+ * the use of the full PUTS' command and status interface is contained
+ * within a separate SBE PUTS Manual.  The Host-Side Device Driver only
+ * uses a subset of the full PUTS interface.
+ */
+
+
+/*****************************************/
+/***    MAILBOX #(-1) - MEM ACCESS STS ***/
+/*****************************************/
+
+#define MBX_STS_VALID      0x57584744 /* 'WXGD' */
+#define MBX_STS_DILAV      0x44475857 /* swapped = 'DGXW' */
+
+/*****************************************/
+/***    MAILBOX #0  -  PUTS STATUS     ***/
+/*****************************************/
+
+#define MBX_STS_MASK       0x000000ff /* PUTS Status Register bits */
+#define MBX_STS_TMASK      0x0000000f /* register bits for TEST number */
+
+#define MBX_STS_PCIRESET   0x00000100 /* Host issued PCI reset request */
+#define MBX_STS_BUSY       0x00000080 /* PUTS is in progress */
+#define MBX_STS_ERROR      0x00000040 /* PUTS has failed */
+#define MBX_STS_RESERVED   0x000000c0 /* Undefined -> status in transition.
+                                        We are in process of changing
+                                        bits; we SET Error bit before
+                                         RESET of Busy bit */
+
+#define MBX_RESERVED_5     0x00000020 /* FYI: reserved/unused bit */
+#define MBX_RESERVED_4     0x00000010 /* FYI: reserved/unused bit */
+
+
+/******************************************/
+/***    MAILBOX #1  -  PUTS COMMANDS    ***/
+/******************************************/
+
+/*
+ * Any attempt to execute an unimplement command results in the PUTS
+ * interface executing a NOOP and continuing as if the offending command
+ * completed normally.  Note: this supplies a simple method to interrogate
+ * mailbox command processing functionality.
+ */
+
+#define MBX_CMD_MASK       0xffff0000 /* PUTS Command Register bits */
+
+#define MBX_CMD_ABORTJ     0x85000000 /* abort and jump */
+#define MBX_CMD_RESETP     0x86000000 /* reset and pause at start */
+#define MBX_CMD_PAUSE      0x87000000 /* pause immediately */
+#define MBX_CMD_PAUSEC     0x88000000 /* pause on completion */
+#define MBX_CMD_RESUME     0x89000000 /* resume operation */
+#define MBX_CMD_STEP       0x8a000000 /* single step tests */
+
+#define MBX_CMD_BSWAP      0x8c000000 /* identify byte swap scheme */
+#define MBX_CMD_BSWAP_0    0x8c000000 /* use scheme 0 */
+#define MBX_CMD_BSWAP_1    0x8c000001 /* use scheme 1 */
+
+#define MBX_CMD_SETHMS     0x8d000000 /* setup host memory access window
+                                        size */
+#define MBX_CMD_SETHBA     0x8e000000 /* setup host memory access base
+                                        address */
+#define MBX_CMD_MGO        0x8f000000 /* perform memory setup and continue
+                                        (IE. Done) */
+#define MBX_CMD_NOOP       0xFF000000 /* dummy, illegal command */
+
+/*****************************************/
+/***    MAILBOX #2  -  MEMORY SIZE     ***/
+/*****************************************/
+
+#define MBX_MEMSZ_MASK     0xffff0000 /* PUTS Memory Size Register bits */
+
+#define MBX_MEMSZ_128KB    0x00020000 /* 128 kilobyte board */
+#define MBX_MEMSZ_256KB    0x00040000 /* 256 kilobyte board */
+#define MBX_MEMSZ_512KB    0x00080000 /* 512 kilobyte board */
+#define MBX_MEMSZ_1MB      0x00100000 /* 1 megabyte board */
+#define MBX_MEMSZ_2MB      0x00200000 /* 2 megabyte board */
+#define MBX_MEMSZ_4MB      0x00400000 /* 4 megabyte board */
+#define MBX_MEMSZ_8MB      0x00800000 /* 8 megabyte board */
+#define MBX_MEMSZ_16MB     0x01000000 /* 16 megabyte board */
+
+
+/***************************************/
+/***    MAILBOX #2  -  BOARD TYPE    ***/
+/***************************************/
+
+#define MBX_BTYPE_MASK          0x0000ffff /* PUTS Board Type Register */
+#define MBX_BTYPE_FAMILY_MASK   0x0000ff00 /* PUTS Board Family Register */
+#define MBX_BTYPE_SUBTYPE_MASK  0x000000ff /* PUTS Board Subtype */
+
+#define MBX_BTYPE_PLX9060       0x00000100 /* PLX family type */
+#define MBX_BTYPE_PLX9080       0x00000300 /* PLX wanXL100s family type */
+
+#define MBX_BTYPE_WANXL_4       0x00000104 /* wanXL400, 4-port */
+#define MBX_BTYPE_WANXL_2       0x00000102 /* wanXL200, 2-port */
+#define MBX_BTYPE_WANXL_1s      0x00000301 /* wanXL100s, 1-port */
+#define MBX_BTYPE_WANXL_1t      0x00000401 /* wanXL100T1, 1-port */
+
+
+/*****************************************/
+/***    MAILBOX #3  -  SHMQ MAILBOX    ***/
+/*****************************************/
+
+#define MBX_SMBX_MASK           0x000000ff /* PUTS SHMQ Mailbox bits */
+
+
+/***************************************/
+/***    GENERIC HOST-SIDE DRIVER     ***/
+/***************************************/
+
+#define MBX_ERR    0
+#define MBX_OK     1
+
+/* mailbox check routine - type of testing */
+#define MBXCHK_STS      0x00    /* check for PUTS status */
+#define MBXCHK_NOWAIT   0x01    /* dont care about PUTS status */
+
+/* system allocates this many bytes for address mapping mailbox space */
+#define MBX_ADDR_SPACE_360 0x80        /* wanXL100s/200/400 */
+#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360-1)
+
+#endif /* __PLX9060_H */