From 5242e78c0b67e3c092fc3e20bdf963a6cd8a5615 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Thu, 6 Sep 2001 23:51:32 +0000 Subject: [PATCH] starting to add ai command support, completely nonfunctional so far --- comedi/drivers/cb_pcidas64.c | 341 +++++++++++++++++++++++++++++++++-- comedi/drivers/plx9060.h | 296 ++++++++++++++++++++++++++++++ 2 files changed, 623 insertions(+), 14 deletions(-) create mode 100644 comedi/drivers/plx9060.h diff --git a/comedi/drivers/cb_pcidas64.c b/comedi/drivers/cb_pcidas64.c index 3bb43e22..b1806e98 100644 --- a/comedi/drivers/cb_pcidas64.c +++ b/comedi/drivers/cb_pcidas64.c @@ -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 + are not yet available. + add plx9080 stuff to make interrupts work + need to take care to prevent ai and ao from affecting each others register bits + support prescaled 100khz for slow pacing */ #include @@ -58,6 +62,7 @@ TODO: #include #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); + + /* disable pacing, triggering, etc */ + writew(ADC_ENABLE_BIT, devpriv->main_iobase + ADC_CONTROL0_REG); + writew(0, devpriv->main_iobase + ADC_CONTROL1_REG); // 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 && + cmd->scan_begin_src == TRIG_TIMER) + err++; + + 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) + { + // if scans are timed faster than conversion rate allows + if(cmd->convert_arg * cmd->chanlist_len > cmd->scan_begin_arg) + { + cmd->scan_begin_arg = cmd->convert_arg * cmd->chanlist_len; + err++; + } + } + } + + 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 index 00000000..9cf6dca2 --- /dev/null +++ b/comedi/drivers/plx9060.h @@ -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 + * + * 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 */ -- 2.26.2