// Sample code file: cntr2000.c

// Warning: This code has been marked up for HTML

/*--------------------------------------------------------------------------*
 * $name: CNTR2000.C
 * $version: 7
 * $date_modified: 11181999 
 * $description: This module contains the HardWare specific routines
 *               to initialize and control the Novell NTR2000 board.  
 * $owner:  ODI LAN Driver Manager
 * Copyright (c) 1996, 1997, 1998, 1999 Novell, Inc. All Rights Reserved.
 *
 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND 
 * TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE
 * AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS
 * THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS 
 * TO DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S 
 * SAMPLE CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE 
 * DISTRIBUTION RIGHTS TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE
 * AS A COMPONENT OF DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO 
 * OBLIGATIONS TO DEVELOPER OR DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS 
 * CODE.
 *--------------------------------------------------------------------------*/
/*****************************************************************************
 *
 * Title:         C language NTR2000 HSM
 *
 * Filename:      CNTR2000.C
 *
 * ODI Spec Ver:   1.11
 *
 * Description:       This module contains the HardWare specific routines
 *               to initialize and control the Novell NTR2000 board.
 *
 * Modification History: 
 *
 * 02-13-97 WTT      Changed call CMSMShutdownMlid back to DriverShutdown
 *               in the DriverReset code.  DriverReset gets called by
 *               DriverInit before the CMSMRegisterMLID has been called.
 *               CMSMShutdownMLID can not be called before the MLID has
 *               been registered with the CMSM.
 *               SPD #149696
 *
 * 02-19-97 MPK      Changed DriverInit to call CMSMInitParser befoer parsing.  
 *               There was no need to change anything else in this module 
 *               for the new   Parser changes.
 *
 * 03-05-97 WTT      Added fixes to queuing problems found by the CPR team.
 *               The first fix was in ARB_JMP_TransmitData when setting
 *               nextTCB.  The second was in CheckNextSRBCommand when setting 
 *               txTail.
 *
 * 03-05-97 WTT      Changed Configuration Table template MLIDCFG_SharingFlags
 *               to default to shutdown (See CNTR2000.H) state.  The shutdown 
 *               state is then cleared once the CHSM/Adapter is fully 
 *               functional.
 * 04-30-97 AYD        SPD# 150139   
 *               Replaced return code in DriverReset 
 *               (ODISTAT_RESPONSE_DELAYED). Added CMSMControlComplete in 
 *               IV_SRBResponse function when reset procedure completed DirOpen
 *
 * 07-22-97 JCJ     SPD# 161861
 *               Implemeted a check on scope of the operation in DriverShutdown
 *               and if it is with OP_SCOPE_LOGICAL_BOARD does nothing.
 *
 * 09-18-97 JCJ     SPD#163281
 *                  SHUTDOWN bit of MLIDStatusFlags has been taken of from
 *                  DriverEnableInterrupt and DriverShutdown routines since
 *                  DriverReset has to return with ODI_STATUS_COMPLETE.  In
 *                  such cases driver will not be interrupted.  Now SHUTDOWN
 *                  bit is checked in receive paths(IV_ARBRequest)
 *
 * 12-02-97 WTT   Added code to the beginning of driverInit to initialize the 
 *                  range/max field of MemOption and TBZOption, which may have 
 *                  still have selected value from previous load.
 *                  SPD #172576
 *
 * 01-13-98 WTT   Added code to the end of ARB_JMP_RingStatusRoutine to set 
 *                  alertMSG to CNTR2000_ALERT_CORRECT_MSG before calling 
 *                  CMSMPrintString.  Before this change alertMSG was 
 *                  uninitialized and caused an ABEND on the server when 
 *                  CMSMPrintString was called.
 *                  SPD 175616
 *
 * 11-18-99 mcd Changed incorrect check for error return on call to
 *                      CTokenTSMRegisterHSM
 *                      BQ Defect120538
 *
 ****************************************************************************/

#define  USE_NBI

#define  NO_TX_LIMIT       1
#define  USE_FAST_CALLS    1

#ifdef DEBUG
#define  OUT_CHAR          1 
#define  ATTRIB            COLOR
#endif

/*===[ Include files specific to current platform ]======================*/
#include <portable.h>

/*===[ Generic HSM Include files ]===========================*/
#include <odi.h>
#include <odi_nbi.h>
#include <odi_nesl.h>
#include <nesl_str.h>
#include <parser.h>
#include <cmsm.h>
#include <cntr2000.txt>

/*===[Cntr2000 Specific Include Files]=======================*/
#include "cntr2000.h"

/**************************************************************************\
**
**    Global declarations
**
\**************************************************************************/

/*  temporary storage for custom keywords                                 */

UINT8    LinkStationsValue = OPEN_LINK_STATIONS;
UINT8    MaxSAPsValue      = OPEN_MAX_SAPS;
UINT8    TxBuffersValue    = OPEN_TX_BUFFERS;
UINT16   TxBufferLenValue  = 0;

UINT8    microChannelSignature [] =
{
   'M'/16,'M'-'M'/16*16,
   'A'/16,'A'-'A'/16*16,
   'R'/16,'R'-'R'/16*16,
   'S'/16,'S'-'S'/16*16,
   '6'/16,'6'-'6'/16*16,
   '3'/16,'3'-'3'/16*16,
   'X'/16,'X'-'X'/16*16,
   '4'/16,'4'-'4'/16*16,
   '5'/16,'5'-'5'/16*16,
   '1'/16,'1'-'1'/16*16,
   '8'/16,'8'-'8'/16*16
};

UINT8    pcSignature [] =
{
   'P'/16,'P'-'P'/16*16,
   'I'/16,'I'-'I'/16*16,
   'C'/16,'C'-'C'/16*16,
   'O'/16,'O'-'O'/16*16,
   '6'/16,'6'-'6'/16*16,
   '1'/16,'1'-'1'/16*16,
   '1'/16,'1'-'1'/16*16,
   '0'/16,'0'-'0'/16*16,
   '9'/16,'9'-'9'/16*16,
   '9'/16,'9'-'9'/16*16,
   '0'/16,'0'-'0'/16*16
};

UINT16   transmitSizeTable4Mb [] =
{
   4464,
   4464,
   4464,
   4096,
   2048
};

UINT16   transmitSizeTable16Mb [] =
{
   17960,
   16384,
   8192,
   4096,
   2048
};

UINT8    TxDIRFrame [SRB_SIZE] = {SRB_TX_DIR_FRAME, 0, SRB_NOT_PROCESSED, 0, 0, 0};

void     (* ARBJumpTable [])() =
{
   ARB_JMP_ReceiveDataRoutine,               /* ARB 81 -- Rx Data         */
   ARB_JMP_TransmitDataRequest,              /* ARB 82 -- Tx Data Req     */
   ARB_JMP_InvalidARBEntry,                  /* ARB 83 -- DLC Status      */
   ARB_JMP_RingStatusRoutine,                /* ARB 84 -- Ring Status     */

#ifdef BROUTER

   ARB_JMP_BReceiveDataRoutine,              /* ARB 85 -- Rx Bridge Data  */

#else

   ARB_JMP_InvalidARBEntry,                  /* ARB 85 -- Invalid ARB Req */

#endif /* BROUTER */
};

/* Data pointers needed for NESL event production   */

EPB        *NESL_EPBPtr = NULL;
NESL_ECB *NESLServiceResumeNECBPtr = NULL;
BOOLEAN   NESLRegisterDone = FALSE;

MEON   **DriverMessages = NULL;

/* Driver Data Space template. MSMRegisterHardwareOptions will initialize */
/* each adapter data space with the values in this template.              */

#define   NUMBER_OF_GENERICS 20
#define   NUMBER_OF_MEDIAS 13
#define   NUMBER_OF_CUSTOMS 6

MEON_STRING CHSMSPEC[] = {CNTR2000_SPECVER_TXTMSG};

MEON_STRING ShortName[] = {CNTR2000_SHORTNAME_TXTMSG};

static DRIVER_DATA ADSTemplate =
{
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,            /* ARB area                        */
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,            /* ARB area                        */

   0,                                      /* FunctionalAddress               */
   0,                                      /* SendQueueHead                   */
   0,                                      /* SendQueueTail                   */
   0,                                      /* TxStartTime                     */
   0,                                      /* TxInProcessHead                 */
   0,                                      /* FirstRxBuffer                   */
   0,                                      /* CompletionQHead                 */
   0,                                      /* CheckAlertTimer                 */
   0,                                      /* TotalBytes                      */
   0,                                      /* TxCorrelator                    */
   0,                                      /* TxBuffersUsed                   */
   0,                                      /* pageSize8KFlag                  */
   0,                                      /* pageSizeMSG                     */
   0,                                      /* sendMSG                         */
   0,                                      /* LastErrorMessage                */

   0,                                      /* tcbInProcess                    */
   0,                                      /* BusType                         */
   0,                                      /* BusTag                          */

   0x4000,                                 /* pageSize                        */
   0xc0,                                   /* pagingMask                      */
   0xff,                                   /* pageSizeMask                    */

   0,                                      /* startSendFlag                   */
   0,                                      /* SRAFlag                         */
   0,                                      /* MLIDStatusFlag                  */
   0,                                      /* inDriverReset                   */
  -1,                                      /* OpeningAdapter                  */
   0,                                      /* initRetryCounter                */
   0,                                      /* initStatus                      */
   0,                                      /* interruptResetLevel             */
   0,                                      /* boardNumber                     */
   0,                                      /* absoluteMMIOAddress             */
   0,                                      /* sharedRAMRelative               */

   0,                                      /* AdapterParmsPageValue           */
   0,                                      /* AdapterParmsAddr                */
   0,                                      /* TxLastBuffer                    */
   0,                                      /* TxBufferSpace                   */
   0,                                      /* TxCurrentBuffer                 */
   0,                                      /* TxCurrentTCB                    */
   0,                                      /* TxFragmentCount                 */

   0,                                      /* brouterState                    */

   0x0c,0,0,0,0x0a,0x04,                   /* bConfigCommand                  */
   0x09,0,0,0,0,0,                         /* bParmsCommand                   */

   0,                                      /* bParmsSRing                     */
   0,                                      /* bParmsTRing                     */
   0,                                      /* bParmsBNumber                   */
   0,                                      /* bParmsPBits                     */
   1,4,                                    /* bParmsCopySTE                   */

   0x12,0,0,0,0,0,0,0,0,0,0x02,0,          /* configFastPath                  */

   {                                       /* DIROpenAdapter Structure        */
      SRB_OPEN_ADAPTER,                    /* OpenCommandCode                 */
      0,                                   /* Reserved1                       */
      SRB_NOT_PROCESSED,                   /* OpenReturnCode                  */
      0,0,0,0,0,                           /* Reserved2                       */
      OPEN_OPTIONS_HIGH, OPEN_OPTIONS_LOW, /* OpenOptions                     */
      0,0,0,0,0,0,                         /* OpenNodeAddress                 */
      OPEN_GROUP_ADDRESS,                  /* OpenGroupAddress                */
      OPEN_FUNCTIONAL_ADDR,                  /* OpenFunctionalAddr            */
      OPEN_RX_BUFFS_HIGH, OPEN_RX_BUFFS_LOW, /* OpenRxBuffers                 */
      OPEN_RX_LENGTH_HI, OPEN_RX_LENGTH_LO,  /* OpenRxLength                  */
      0,                                     /* OpenTxLength                  */
      OPEN_TX_BUFFERS,                       /* OpenTxBuffers                 */
      0,                                     /* Reserved3                     */
      OPEN_MAX_SAPS,                         /* OpenMaximumSAPs               */
      0,0,0,0,0,0,0,0,0,                     /* misc                          */
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    /* OpenProductID                 */
   },

   {IV_AdapterError,   ADAPTER_ERROR_BIT      ,  0xff, 0xff, 0},  /* ivt_AER  */
   {IV_AdapterCheck,   ADAPTER_CHECK_BIT  << 8,  0xff, 0xff, 0},  /* ivt_ACK  */
   {IV_InvalidASB,     ASB_FREE_BIT       << 8,  0,    0,    0},  /* ivt_ASB  */
   {IV_SRBResponse,    SRB_RESPONSE_BIT   << 8,  0,    0,    0},  /* ivt_SRB  */
   {IV_FastTxComplete, BRIDGE_FORWARD_BIT << 8,  0,    0,    0},  /* ivt_FTX  */
   {IV_ARBRequest,     ARB_COMMAND_BIT    << 8,  0,    0,    0},  /* ivt_ARB  */
   {IV_SSBResponse,    SSB_RESPONSE_BIT   << 8,  0,    0,    0},  /* ivt_SSB  */
   {IV_ARBReturn,      0xffff                 ,  0,    0,    0},  /* ivt_RET  */

   0,0,0,0,0,0,                              /* commonNodeAddress             */
   0,                                        /* commonIOPort                  */
   4,                                        /* commonLineSpeed               */
   0,                                        /* *commonMemoryDecode0          */
   0,                                        /* *commonLinearMemory0          */
   0,                                        /* commonMaximumSize             */

   {   
      NULL,                                  /* DAES->NextLink                */
      DriverCallBack,                        /* DAES->DriverAES               */
      AES_TYPE_PROCESS_CONTINUOUS,           /* DAES->AesType                 */
      4000,                                  /* DAES->TimeInterval            */
      NULL,                                  /* DAES->AesContext              */
      {0}                                    /* DAES->AesReserved             */
   },

   {
      4,                                   /* StatsTable->MStatTableMajorVer  */
      00,                                  /* StatsTable->MStatTableMinorVer  */
      NUMBER_OF_GENERICS,                  /* StatsTable->MNumGenericCounters */
      (StatTableEntry (*)[])&ADSTemplate.TotalTxPacketTable,
                                           /* StatsTable->MGenericCountsPtr   */
      NUMBER_OF_MEDIAS,                    /* StatsTable->MNumMediaCounters   */
      (StatTableEntry (*)[])&ADSTemplate.ACErrorTable,
                                           /* StatsTable->MMediaCountersPtr   */
      NUMBER_OF_CUSTOMS,                   /* StatsTable->MNumCustomCounters  */
      (StatTableEntry (*)[])&ADSTemplate.BadCorrelatorTable
                                           /* StatsTable->MCustomCountersPtr  */
   },

   {
      ODI_STAT_UINT32,                     /* TotalTxPacketTable->StatUseFlag */
      &ADSTemplate.TotalTxPacketCount,     /* TotalTxPacketTable->StatCounter */
      0                                    /* TotalTxPacketTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                     /* TotalRxPacketTable->StatUseFlag */
      &ADSTemplate.TotalRxPacketCount,     /* TotalRxPacketTable->StatCounter */
      0                                    /* TotalRxPacketTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* NoECBAvailableTable->StatUseFlag */
      &ADSTemplate.NoECBAvailableCount,   /* NoECBAvailableTable->StatCounter */
      0                                   /* NoECBAvailableTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* PacketTxTooBigTable->StatUseFlag */
      &ADSTemplate.PacketTxTooBigCount,   /* PacketTxTooBigTable->StatCounter */
      0                                   /* PacketTxTooBigTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                   /*PacketTxTooSmallTable->StatUseFlag */
      &ADSTemplate.PacketTxTooSmallCount,/*PacketTxTooSmallTable->StatCounter */
      0                                  /*PacketTxTooSmallTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /*PacketRxOverflowTable->StatUseFlag*/
      &ADSTemplate.PacketRxOverflowCount, /*PacketRxOverflowTable->StatCounter*/
      0                                   /*PacketRxOverflowTable->StatString */
   },

   {
      ODI_STAT_UINT32,                    /* PacketRxTooBigTable->StatUseFlag */
      &ADSTemplate.PacketRxTooBigCount,   /* PacketRxTooBigTable->StatCounter */
      0                                   /* PacketRxTooBigTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                   /*PacketRxTooSmallTable->StatUseFlag */
      &ADSTemplate.PacketRxTooSmallCount,/*PacketRxTooSmallTable->StatCounter */
      0                                  /*PacketRxTooSmallTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                   /*PacketTxMiscErrorTable->StatUseFlag*/
      &ADSTemplate.PacketTxMiscErrorCount,/*PacketTxMiscErrorTable->StatCountr*/
      0                                   /*PacketTxMiscErrorTable->StatString*/
   },

   {
      ODI_STAT_UINT32,                   /*PacketRxMiscErrorTable->StatUseFlag*/
      &ADSTemplate.PacketRxMiscErrorCount,/*PacketRxMiscErrorTable->StatCountr*/
      0                                   /*PacketRxMiscErrorTable->StatString*/
   },

   {
      ODI_STAT_UINT32,                     /* RetryTxTable->StatUseFlag */
      &ADSTemplate.RetryTxCount,           /* RetryTxTable->StatCounter */
      0                                    /* RetryTxTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                     /* ChecksumErrorTable->StatUseFlag */
      &ADSTemplate.ChecksumErrorCount,     /* ChecksumErrorTable->StatCounter */
      0                                    /* ChecksumErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                  /*HardwareRxMismatchTable->StatUseFlag*/
      &ADSTemplate.HardwareRxMismatchCount,/*HardwareRxMismatchTable->StatCntr*/
      0                                  /*HardwareRxMismatchTable->StatString*/
   },

   {
      ODI_STAT_UINT64,                     /* TotalTxOKByteTable->StatUseFlag */
      &ADSTemplate.TotalTxOKByteCount,     /* TotalTxOKByteTable->StatCounter */
      0                                    /* TotalTxOKByteTable->StatString  */
   },

   {
      ODI_STAT_UINT64,                     /* TotalRxOKByteTable->StatUseFlag */
      &ADSTemplate.TotalRxOKByteCount,     /* TotalRxOKByteTable->StatCounter */
      0                                    /* TotalRxOKByteTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                   /* TotalGroupAddrTxTable->StatUseFlag*/
      &ADSTemplate.TotalGroupAddrTxCount,/* TotalGroupAddrTxTable->StatCounter*/
      0                                  /* TotalGroupAddrTxTable->StatString */
   },

   {
      ODI_STAT_UINT32,                   /*TotalGroupAddrRxTable->StatUseFlag */
      &ADSTemplate.TotalGroupAddrRxCount,/*TotalGroupAddrRxTable->StatCounter */
      0                                  /*TotalGroupAddrRxTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                     /* AdapterResetTable->StatUseFlag */
      &ADSTemplate.AdapterResetCount,      /* AdapterResetTable->StatCounter */
      0                                    /* AdapterResetTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                 /*AdapterOprTimeStampTable->StatUseFlag*/
      &ADSTemplate.AdapterOprTimeStamp,/*AdapterOprTimeStampTable->StatCounter*/
      0                                /*AdapterOprTimeStampTable->StatString */
   },

   {
      ODI_STAT_UINT32,                       /* QDepthTable->StatUseFlag  */
      &ADSTemplate.QDepth,                   /* QDepthTable->StatCounter  */
      0                                      /* QDepthTable->StatString   */
   },

/* Media Counters */
   {
      ODI_STAT_UINT32,                       /* ACErrorTable->StatUseFlag */
      &ADSTemplate.ACError,                  /* ACErrorTable->StatCounter */
      0                                      /* ACErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* AbortDelimiterTable->StatUseFlag */
      &ADSTemplate.AbortDelimiter,        /* AbortDelimiterTable->StatCounter */
      0                                   /* AbortDelimiterTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* BurstErrorTable->StatUseFlag */
      &ADSTemplate.BurstError,               /* BurstErrorTable->StatCounter */
      0                                      /* BurstErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                  /* FrameCopiedErrorTable->StatUseFlag */
      &ADSTemplate.FrameCopiedError,    /* FrameCopiedErrorTable->StatCounter */
      0                                 /* FrameCopiedErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* FrequencyErrorTable->StatUseFlag */
      &ADSTemplate.FrequencyError,        /* FrequencyErrorTable->StatCounter */
      0                                   /* FrequencyErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                     /* InternalErrorTable->StatUseFlag */
      &ADSTemplate.InternalError,          /* InternalErrorTable->StatCounter */
      0                                    /* InternalErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* LastRingStatusTable->StatUseFlag */
      &ADSTemplate.LastRingStatus,        /* LastRingStatusTable->StatCounter */
      0                                   /* LastRingStatusTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* LineErrorTable->StatUseFlag */
      &ADSTemplate.LineError,                /* LineErrorTable->StatCounter */
      0                                      /* LineErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* LostFrameTable->StatUseFlag */
      &ADSTemplate.LostFrame,                /* LostFrameTable->StatCounter */
      0                                      /* LostFrameTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* TokenErrorTable->StatUseFlag */
      &ADSTemplate.TokenError,               /* TokenErrorTable->StatCounter */
      0                                      /* TokenErrorTable->StatString  */
   },

   {
      ODI_STAT_UINT64,                 /*UpstreamNodeAddressTable->StatUseFlag*/
      &ADSTemplate.UpstreamNodeAddress,/*UpstreamNodeAddressTable->StatCounter*/
      0                                /*UpstreamNodeAddressTable->StatString */
   },

   {
      ODI_STAT_UINT32,                       /* LastRingIDTable->StatUseFlag */
      &ADSTemplate.LastRingID,               /* LastRingIDTable->StatCounter */
      0                                      /* LastRingIDTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                    /* LastBeaconTypeTable->StatUseFlag */
      &ADSTemplate.LastBeaconType,        /* LastBeaconTypeTable->StatCounter */
      0                                   /* LastBeaconTypeTable->StatString  */
   },

/* custom counters                                                        */

   {
      ODI_STAT_UINT32,                     /* BadCorrelatorTable->StatUseFlag */
      &ADSTemplate.BadCorrelator,          /* BadCorrelatorTable->StatCounter */
      0                                    /* BadCorrelatorTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* UnknownARBTable->StatUseFlag */
      &ADSTemplate.UnknownARB,               /* UnknownARBTable->StatCounter */
      0                                      /* UnknownARBTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* QDepthEqualTwoTable->StatUseFlag */
      &ADSTemplate.QDepthEqualTwo,           /* QDepthEqualTwoTable->StatCounter */
      0                                      /* QDepthEqualTwoTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* CardIsDeadTable->StatUseFlag */
      &ADSTemplate.CardIsDead,               /* CardIsDeadTable->StatCounter */
      0                                      /* CardIsDeadTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* TxFreeCountZeroTable->StatUseFlag */
      &ADSTemplate.TxFreeCountZero,          /* TxFreeCountZeroTable->StatCounter */
      0                                      /* TxFreeCountZeroTable->StatString  */
   },

   {
      ODI_STAT_UINT32,                       /* TxFreeCountZeroAndResetTable->StatUseFlag */
      &ADSTemplate.TxFreeCountZeroAndReset,  /* TxFreeCountZeroAndResetTable->StatCounter */
      0                                      /* TxFreeCountZeroAndResetTable->StatString  */
   },

   0,                                        /* TotalTxPacketCount        */
   0,                                        /* TotalRxPacketCount        */
   0,                                        /* NoECBAvailableCount       */
   0,                                        /* PacketTxTooBigCount       */
   0,                                        /* PacketTxTooSmallCount     */
   0,                                        /* PacketRxOverflowCount     */
   0,                                        /* PacketRxTooBigCount       */
   0,                                        /* PacketRxTooSmallCount     */
   0,                                        /* PacketTxMiscErrorCount    */
   0,                                        /* PacketRxMiscErrorCount    */
   0,                                        /* RetryTxCount              */
   0,                                        /* ChecksumErrorCount        */
   0,                                        /* HardwareRxMismatchCount   */
   {0, 0},                                   /* TotalRxOKByteCount        */
   {0, 0},                                   /* TotalTxOKByteCount        */
   0,                                        /* TotalGroupAddrTxCount     */
   0,                                        /* TotalGroupAddrRxCount     */
   0,                                        /* AdapterResetCount         */
   0,                                        /* AdapterOprTimeStamp       */
   0,                                        /* QDepth                    */

   0,                                        /* ACError                   */
   0,                                        /* AbortDelimiter;           */
   0,                                        /* BurstError;               */
   0,                                        /* FrameCopiedError;         */
   0,                                        /* FrequencyError;           */
   0,                                        /* InternalError;            */
   0,                                        /* LastRingStatus;           */
   0,                                        /* LineError;                */
   0,                                        /* LostFrame;                */
   0,                                        /* TokenError;               */
   {0, 0},                                   /* UpstreamNodeAddress;      */
   0,                                        /* LastRingID;               */
   0,                                        /* LastBeaconType;           */

/* custom counters                                                        */

   0,                                        /* BadCorrelator             */
   0,                                        /* UnknownARB                */
   0,                                        /* QDepthEqualTwo            */
   0,                                        /* CardIsDead                */
   0,                                        /* TxFreeCountZero           */
   0,                                        /* TxFreeCountZeroAndReset   */

};

static MLID_ConfigTable DriverConfigTemplate =
{
   {CNTR2000_CONFIGSIG_TXTMSG},                /* MLIDCFG_Signature       */
   01,                                         /* MLIDCFG_MajorVersion    */
   21,                                         /* MLIDCFG_MinorVersion    */
   {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},       /* MLIDCFG_NodeAddress     */
   MODE_FLAGS,                                 /* MLIDCFG_ModeFlags       */
   0,                                          /* MLIDCFG_BoardNumber     */
   0,                                          /* MLIDCFG_BoardInstance   */
   0,                                          /* MLIDCFG_MaxFrameSize    */
   0,                                          /* MLIDCFG_BestDataSize    */
   0,                                          /* MLIDCFG_WorstDataSize   */
   NULL,                                       /* MLIDCFG_CardName        */
   ShortName,                                  /* MLIDCFG_ShortName       */
   NULL,                                       /* MLIDCFG_FrameTypeString */
   0,                                          /* MLIDCFG_Reserved0       */
   0,                                          /* MLIDCFG_FrameID         */
   1,                                          /* MLIDCFG_TransportTime   */
   NULL,                                       /* MLIDCFG_SourceRouting   */
   4,                                          /* MLIDCFG_LineSpeed       */
   0,                                          /* MLIDCFG_LookAheadSize   */
   0,                                            /* MLIDCFG_SGCount            */
   0,                                            /* MLIDCFG_Reserved1         */
   0,                                          /* MLIDCFG_PrioritySup     */
   NULL,                                       /* MLIDCFG_Reserved2       */
   0,                                          /* MLIDCFG_DriverMajorVer  */
   0,                                         /* MLIDCFG_DriverMinorVer  */
   FLAGS,                                      /* MLIDCFG_Flags           */
   0,                                          /* MLIDCFG_SendRetries     */
   0,                                          /* MLIDCFG_DriverLink      */
   SHARING_FLAGS,                              /* MLIDCFG_SharingFlags    */
   0xffff,                                     /* MLIDCFG_Slot            */
   PRIMARY_PIO,                                /* MLIDCFG_IOPort0         */
   4,                                          /* MLIDCFG_IORange0        */
   0,                                          /* MLIDCFG_IOPort1         */
   0,                                          /* MLIDCFG_IORange1        */
   NULL,                                       /* MLIDCFG_MemoryAddress0  */
   RAM_PAGE_RANGE0,                            /* MLIDCFG_MemorySize0     */
   NULL,                                       /* MLIDCFG_MemoryAddress1  */
   RAM_PAGE_RANGE1,                            /* MLIDCFG_MemorySize1     */
   7,                                          /* MLIDCFG_Interrupt0      */
   0xff,                                       /* MLIDCFG_Interrupt1      */
   0xff,                                       /* MLIDCFG_DMALine0        */
   0xff,                                       /* MLIDCFG_DMALine1        */
   NULL,                                       /* MLIDCFG_ResourceTag     */
   NULL,                                       /* MLIDCFG_Config          */
   NULL,                                       /* MLIDCFG_CommandString   */
   {0},                                        /* MLIDCFG_LogicalName     */
   0,                                          /* MLIDCFG_LinearMemory0   */
   0,                                          /* MLIDCFG_LinearMemory1   */
   0,                                          /* MLIDCFG_ChannelNumber   */
   NULL,                                       /* MLIDCFG_DBusTag         */
   1,                                          /* MLIDCFG_DIOConfigMajor  */
   0,                                          /* MLIDCFG_DIOConfigMinor  */
};

static struct _DRIVER_PARM_BLOCK_ DriverParameterBlock =
{
   sizeof(DRIVER_PARM_BLOCK),                /* DriverParameterSize        */
   NULL,                                     /* DriverInitParmPointer      */
   NULL,                                     /* DriverModuleHandle         */
   NULL,                                     /* DPB_Reserved0              */
   NULL,                                     /* DriverAdapterPointer       */
   &DriverConfigTemplate,                    /* DriverConfigTemplatePtr    */
   0,                                        /* DriverFirmwareSize         */
   NULL,                                     /* DriverFirmwareBuffer       */
   NULL,                                     /* DPB_Reserved1              */
   NULL,                                     /* DPB_Reserved2              */
   NULL,                                     /* DPB_Reserved3              */
   NULL,                                     /* DPB_Reserved4              */    
   sizeof (DRIVER_DATA),                     /* DriverAdapterDataSpaceSize */
   &ADSTemplate,                             /* DriverAdapterDataSpacePtr  */
   (UINT32) &(((DRIVER_DATA*)0)->StatsTable),/* DriverStatisticsTableOffset*/
   0,                                        /* DriverEndOfChainFlag       */
   0,                                        /* DriverSendWantsECBs        */
   -1,                                       /* DriverMaxMulticast         */
   0,                                        /* DriverNeedsBelow16Meg      */
   NULL,                                       /* DPB_Reserved5              */
   NULL,                                       /* DPB_Reserved6              */
   DriverISR,                                /* DriverISRPtr               */
   DriverMulticastChange,                    /* DriverMulticastChangePtr   */
   NULL,                                     /* DriverPollPtr              */
   DriverReset,                              /* DriverResetPtr             */
   DriverSend,                               /* DriverSendPtr              */
   DriverShutdown,                           /* DriverShutdownPtr          */
   NULL,                                     /* DriverTxTimeoutPtr         */
   NULL,                                     /* DriverPromiscuousChangePtr */
   NULL,                                     /* DriverStatisticsChangePtr  */
   NULL,                                     /* DriverRxLookAheadChangePtr */
#ifdef BROUTER
   DriverManagement,                         /* DriverManagementPtr        */
#else
   NULL,                                     /* DriverManagementPtr        */
#endif /* BROUTER */
   DriverEnableInterrupt,                    /* DriverEnableInterruptPtr   */
   DriverDisableInterrupt,                   /* DriverDisableInterruptPtr  */
   NULL,                                     /* DriverISRPtr2              */
   &DriverMessages,                          /* DriverMessagesPtr          */
   &CHSMSPEC,            /* HSM Specification Version */
   NULL,               /* Driver Priority Queue Ptr */
   NULL               /* DriverDisableInterrupt2Ptr */
};

/**************************************************************************\
**
**    Parameters required by ParseDriverParameters.
**
\**************************************************************************/
DRIVER_OPTION *IIoOptio;

struct
{
   UINT32   OptionCount;
   UINT32   UNumOptVal[2];
} IoOptionList = {2, { PRIMARY_PIO, SECONDARY_PIO }};

struct
{
   UINT32   OptionCount;
   UINT32   UNumOptVal[8];
} SlotsWithMyBoard = {0, {0, 0, 0, 0, 0, 0, 0, 0}};

DRIVER_OPTION MemOption =
         { NULL, NULL, 0, 0x100000, 0xD8000,
         MEMPARAM, OPTIONALPARAM | RANGEPARAM | DEFAULTPRESENT, };

DRIVER_OPTION TBZOption =
         { &MemOption, CNTR2000_TBZPROMPT_TXTMSG, 0, 17954, 0,
         CUSTOMPARAM, OPTIONALPARAM | RANGEPARAM | DEFAULTPRESENT, };

DRIVER_OPTION IoOption =
         { &TBZOption, NULL, (PARAMETER_OPTIONS *)&IoOptionList, 0, PRIMARY_PIO,
         PORTPARAM, REQUIREDPARAM | DEFAULTPRESENT | ENUMPARAM, };

DRIVER_OPTION SlotOption =
         { &TBZOption, NULL, (PARAMETER_OPTIONS *)&SlotsWithMyBoard, 0, 0,
         SLOTPARAM, REQUIREDPARAM | ENUMPARAM, };

UINT32   SlotsWithMyBoardCount;

/**************************************************************************\
**
**    Procedures
**
\**************************************************************************/

/**************************************************************************\
**
** PROC NAME:     WaitForEvent
**
**                This routine is called to wait for a specific event to
**                occur.
**
** Parameters:    IN    UINT32   busTag
**                IN    UINT32   waitTicks
**                IN    UINT16   memMask
**                IN    UINT16   *memAddress
**                IN    void     *smemAddress
**
** Return Value:  0     = successful
**                -1    = unsuccessful
**
** See Also:
**
\**************************************************************************/

UINT32
WaitForEvent (
   DRIVER_DATA   *driverData,
   void         *busTag,
   UINT32      waitTicks,
   UINT16      memMask,
   UINT16      *memAddress,
   void         *smemAddress)
{
   UINT32   ticks;

   driverData   = driverData;
   ticks  = (CMSMGetCurrentTime ()) + waitTicks;

   do
   {
      CMSMYieldWithDelay();

      if (smemAddress)
      {
         if ((Rd16 ((void *)busTag, NULL, smemAddress)) & memMask)
         {
            return 0;
         }
      }
      else
      {
         if (*memAddress & memMask)
         {
            return 0;
         }
      }
   }
   while (ticks > CMSMGetCurrentTime ());

   return -1;
}

/**************************************************************************\
**
** PROC NAME:     DriverInit
**
**                This routine will call CTokenTSMRegisterHSM,
**                CMSMParseDriverParameters, CMSMRegisterHardwareOptions,
**                CMSMSetHardwareInterrupt, CMSMRegisterMLID, initialize
**                variables in the Adapter Data Space and reset/initialize
**                the card.
**
** Parameters:    IN    struct _HSM_STACK    *HSMStack
**
**                HSMStack    -  Pointer to HSM's stack parameters
**                               which will be dealt with by the MSM at
**                               diferent stages of DriverInit.
**
** Return Value:  0     = successful
**                -1    = unsuccessful
**
** See Also:
**
\**************************************************************************/

ODISTAT
DriverInit(
   struct _MODULE_HANDLE_  *ModuleHandle,
   SCREEN_HANDLE            *ScreenHandle,
   MEON                     *CommandLine,
   MEON                     *ModuleLoadPath,
   UINT32                  UnitializedDataLength,
   void                     *CustomDataFileHandle,
   UINT32                  (* FileRead)(
                              void *FileHandle,
                              UINT32 FileOffset,
                              void *FileBuffer,
                              UINT32 FileSize),
   UINT32                  CustomDataOffset,
   UINT32                  CustomDataSize,
   UINT32                  NumMsgs,
   MEON                     **Msgs)
{
   CONFIG_TABLE   *configTable;
   DRIVER_DATA    *driverData;

   UINT8            i;
   UINT8          *busSignature;
   UINT8          signature;
   UINT8          nodeHI;
   UINT8          nodeLO;
   UINT8          myINT;

   UINT32         myMMIO;
   REG_TYPE       ccode;
   UINT32         busType;

   CHSM_STACK     chsmStack;
   void           *temp_DBusTag;

#ifdef USE_NBI
   MEON            *busName;
   UINT8          cfgBlock [MCA_CFG_BLOCK_SIZE];   
   UINT32         scanSeq = -1;                     
   UINT32         uniqueID;
   MEON            productID[PRODUCT_ID_LEN] = {TOKEN_ID_LO,
                                               TOKEN_ID_HI};
#endif


/* Setup a Stack */
   chsmStack.ModuleHandle          = ModuleHandle;
   chsmStack.ScreenHandle          = ScreenHandle;
   chsmStack.CommandLine           = CommandLine;
   chsmStack.ModuleLoadPath        = ModuleLoadPath;
   chsmStack.UnitializedDataLength = UnitializedDataLength;
   chsmStack.CustomDataFileHandle  = CustomDataFileHandle;
   chsmStack.FileRead              = FileRead;
   chsmStack.CustomDataOffset      = CustomDataOffset;
   chsmStack.CustomDataSize        = CustomDataSize;
   chsmStack.NumMsgs               = NumMsgs;
   chsmStack.Msgs                  = Msgs;

   DriverParameterBlock.DriverInitParmPointer = (CHSM_STACK *) &chsmStack;

/***********************************************************************\
   Initalize the Range/Max field, which may have still have selected 
   value from previous load.
\***********************************************************************/

   IoOption.Parameter1.Range = 0;
   MemOption.Parameter1.Range = 0x100000;
   TBZOption.Parameter1.Range = 17954;

/* MPK 970219  - Initialize Parser */
   CMSMInitParser(&DriverParameterBlock);

   if (CTokenTSMRegisterHSM (&DriverParameterBlock, &configTable) != ODISTAT_SUCCESSFUL)
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

/***********************************************************************\
 ** TNL 12/06/95 Register with NESL as producer of Service Resume event.
\***********************************************************************/

   if (!NESLRegisterDone)
   {
      if ((NESLServiceResumeNECBPtr = 
         (NESL_ECB *)CMSMInitAlloc(sizeof(NESL_ECB))) == NULL)
      {
         CMSMReturnDriverResources(configTable);
           return ODISTAT_FAIL;
      }

      NESLServiceResumeNECBPtr->NecbVersion = NESL_VERSION2;
      NESLServiceResumeNECBPtr->NecbEventName = NESL_Service_Resume;
      NESLServiceResumeNECBPtr->NecbRefData = NESL_NOT_UNIQUE_PRODUCER |
         NESL_BROADCAST_EVENT | NESL_SORT_CONSUMER_BOTTOM_UP; 
      NESLServiceResumeNECBPtr->NecbOwner = ModuleHandle;
      NESLServiceResumeNECBPtr->NecbContext = NULL;

      if (CMSMNESLRegisterProducer(NESLServiceResumeNECBPtr) != NESL_OK)
      {
         CMSMReturnDriverResources(configTable);
          return ODISTAT_FAIL;
      }

      if ((NESL_EPBPtr = (EPB *)CMSMInitAlloc(sizeof(EPB))) == NULL)
      {
         CMSMReturnDriverResources(configTable);
           return ODISTAT_FAIL;
      }
                  
      NESL_EPBPtr->EPBMajorVersion = EPBMajVer;
      NESL_EPBPtr->EPBMinorVersion = EPBMinVer;
      NESLRegisterDone = TRUE;
   }

   /* Set up to produce NESL MLID Card Insertion Complete event */

   NESL_EPBPtr->EPBEventName  = NESL_Service_Resume;
   NESL_EPBPtr->EPBEventType  = NESL_MLID_Card_Insertion_Complete;
   NESL_EPBPtr->EPBModuleName   = ShortName;
   NESL_EPBPtr->EPBDataPtr1   = NULL;
   NESL_EPBPtr->EPBEventScope = EPB_SPECIFIC_EVENT;
   NESL_EPBPtr->EPBReserved   = 0;

   if (CMSMScanBusInfo (&scanSeq, &configTable->MLIDCFG_DBusTag,
                        &busType, &busName) != ODI_NBI_SUCCESSFUL)
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   /***********************************************************************\
   **    if bus == MCA check POS registers and do the following stuff
   \***********************************************************************/

   if (busType == ODI_BUSTYPE_MCA)
   {
      /********************************************************************\
      **    scan all slots for our card
      \********************************************************************/
#ifdef USE_NBI

      scanSeq = -1;
      SlotsWithMyBoardCount = 0;
      while (CMSMSearchAdapter (
                  &scanSeq,
                   ODI_BUSTYPE_MCA,
                  PRODUCT_ID_LEN,
                  productID,
                  &temp_DBusTag,
                  &uniqueID)
                  == ODI_NBI_SUCCESSFUL)
         
      {
         configTable->MLIDCFG_DBusTag = temp_DBusTag;
         if ( CMSMGetInstanceNumber(
                  configTable->MLIDCFG_DBusTag,
                  uniqueID,
                  (UINT16 *)&SlotsWithMyBoard.UNumOptVal[SlotsWithMyBoardCount])
                  == ODI_NBI_SUCCESSFUL)
         {
            SlotsWithMyBoardCount++;
         }
      }
#else
      for (i = SLOT_0, SlotsWithMyBoardCount = 0; i <= MAXIMUM_SLOTS; i++)
      {
         Out8 (configTable->MLIDCFG_DBusTag, (void *) SLOT_SELECT_REG, i);

         if ((In8 (configTable->MLIDCFG_DBusTag, (void *) POS_IO_PORT)) < TOKEN_ID_LO)
         {
            if ((In8 (configTable->MLIDCFG_DBusTag, (void *) (POS_IO_PORT + 1)))
               != TOKEN_ID_HI)
            {
               if ((In8 (configTable->MLIDCFG_DBusTag, (void *) (POS_IO_PORT + 2)))
                  & CARD_ENABLE_BIT)
               {
                  SlotsWithMyBoard.UNumOptVal[SlotsWithMyBoardCount] =
                     i - SLOT_0 + 1;
                  SlotsWithMyBoardCount++;
               }
            }
         }
      }
      Out8 (configTable->MLIDCFG_DBusTag, (void *) SLOT_SELECT_REG, 0);
#endif

      SlotsWithMyBoard.OptionCount = SlotsWithMyBoardCount;

      if (!SlotsWithMyBoardCount)
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }

      /********************************************************************\
      **    let the MSM parse the command line
      \********************************************************************/
      if (SlotsWithMyBoardCount == 1)   
      {   /* If only one board then no need to parse for slot   */
         configTable->MLIDCFG_Slot    = SlotsWithMyBoard.UNumOptVal[0];

         if (CMSMParseDriverParameters(&DriverParameterBlock, &TBZOption)
            != ODISTAT_SUCCESSFUL)
         {
            CMSMReturnDriverResources(configTable);
            return (ODISTAT_FAIL);
         }
      }
      else
      {
           if (CMSMParseDriverParameters(&DriverParameterBlock, &SlotOption)
            != ODISTAT_SUCCESSFUL)
         {
            CMSMReturnDriverResources(configTable);
            return (ODISTAT_FAIL);
         }
      }

      /********************************************************************\
      **    use slot chosen by user to determine MEM, I/O and INT level
      \********************************************************************/

#ifdef USE_NBI
      if ( CMSMGetInstanceNumberMapping( 
               configTable->MLIDCFG_Slot,
               &configTable->MLIDCFG_DBusTag,
               &uniqueID)
               != ODI_NBI_SUCCESSFUL)
      {
           CMSMReturnDriverResources(configTable);
           return ODISTAT_FAIL;
      }

      if (CMSMGetCardConfigInfo (
             configTable->MLIDCFG_DBusTag,
            uniqueID,
            MCA_CFG_BLOCK_SIZE,
               NULL,
                NULL,
                cfgBlock)
             != ODI_NBI_SUCCESSFUL)
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }

      configTable->MLIDCFG_IOPort0 = ((UINT16) ((cfgBlock[3] & PRIMARY_ADAPTER_BIT)
                                          << 2) + LOW_PRIMARY_PIO) | 0xa00;
#else
      Out8 (configTable->MLIDCFG_DBusTag, (void *) SLOT_SELECT_REG,
         (configTable->MLIDCFG_Slot - 1) | SLOT_0);

      configTable->MLIDCFG_IOPort0 =
         ((UINT16) (((In8 (configTable->MLIDCFG_DBusTag, (void *) (POS_IO_PORT + 3)) )
            & PRIMARY_ADAPTER_BIT) << 2) + LOW_PRIMARY_PIO) | 0xa00;

      Out8 (configTable->MLIDCFG_DBusTag, (void *) SLOT_SELECT_REG, 0);
#endif

      myINT   = In8 (configTable->MLIDCFG_DBusTag, (void *) configTable->MLIDCFG_IOPort0);
      myMMIO  = (UINT32) myINT;
      myINT  &= INTERRUPT_MASK;
      myMMIO &= MMIO_SEGMENT_MASK;

      /********************************************************************\
      **    decode INT and MMIO/BIOS segment info and save
      \********************************************************************/

      myMMIO = ((myMMIO << 7) | MMIO_BIT) << 4;
      configTable->MLIDCFG_MemoryAddress1 = (void *)myMMIO;
      configTable->MLIDCFG_Interrupt0     = (myINT | (myINT << 1)) | 2;

      if (configTable->MLIDCFG_Interrupt0 >= 6)
         configTable->MLIDCFG_Interrupt0 += 4;

      myMMIO = ((In8 (configTable->MLIDCFG_DBusTag,
         (void *) (configTable->MLIDCFG_IOPort0 + 2))) & 0xfe) << 12;
      configTable->MLIDCFG_MemoryAddress0 = (void *)myMMIO;

      /********************************************************************\
      **    With S-RAM set, get the appropriate length
      \********************************************************************/

      myMMIO = (UINT32) (((UINT8 *)configTable->MLIDCFG_MemoryAddress1)
         + RAM_RELOCATION_REG + 1);

      CMSMReadPhysicalMemory (1, (void *)&i,
         configTable->MLIDCFG_DBusTag, (void *)myMMIO);


      switch (i & SHARED_RAM_MASK)
      {
         case SHARED_RAM_8K:
            configTable->MLIDCFG_MemorySize0 = 0x200;
            break;
         case SHARED_RAM_16K:
            configTable->MLIDCFG_MemorySize0 = 0x400;
            break;
         case SHARED_RAM_32K:
            configTable->MLIDCFG_MemorySize0 = 0x800;
            break;
         case SHARED_RAM_64K:
            configTable->MLIDCFG_MemorySize0 = 0x1000;
            break;
      }


      if ((ccode = CMSMRegisterHardwareOptions (configTable, &driverData)) == REG_TYPE_FAIL)
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }

      /********************************************************************\
      **    check if new frame for existing adapter... if so we're done
      \********************************************************************/

      if (ccode == REG_TYPE_NEW_FRAME)
      {

         /* clear the shutdown bit */
                  
         configTable->MLIDCFG_SharingFlags &= ~MS_SHUTDOWN_BIT;

         /* This is a new frame type for an existing board */
         /* We have already Initialized the hardware. */
         /* Set up to produce NESL MLID Card Insertion Complete event */

         NESL_EPBPtr->EPBDataPtr0   = configTable;

               /* Generate NESL MLID Card Insertion Complete Event */

            CMSMNESLProduceEvent(NESLServiceResumeNECBPtr,
                              NULL,
                               NESL_EPBPtr);

         return (ODISTAT_SUCCESSFUL);
      }

      /********************************************************************\
      **    initialize the ADS now that we have a pointer to it
      \********************************************************************/

      CFixUpStatStrings (driverData);

      driverData->busType = busType;
      driverData->busTag  = configTable->MLIDCFG_DBusTag;

      /********************************************************************\
      **    set resetlevel
      \********************************************************************/

      driverData->interruptResetLevel = RESET_IRQ_PORT;
      busSignature              = microChannelSignature;
   }

   /***********************************************************************\
   **    if bus == ISA or EISA do this stuff
   \***********************************************************************/

   else
   {
      configTable->MLIDCFG_DBusTag = 0;      /* TNL 12/15/95      */

      /********************************************************************\
      **    let the MSM parse the command line
      \********************************************************************/

      if (CMSMParseDriverParameters(&DriverParameterBlock, &IoOption)
         != ODISTAT_SUCCESSFUL)
      {
         CMSMReturnDriverResources(configTable);
         return (ODISTAT_FAIL);
      }

      /********************************************************************\
      **    release adapter reset to prepare to read MMIO area
      \********************************************************************/

      Out8 (configTable->MLIDCFG_DBusTag,
         (void *) (configTable->MLIDCFG_IOPort0 + RELEASE_ADAPTER_RESET), 0);

      /********************************************************************\
      **    get INT and MMIO/BIOS decode info and mask accordingly
      \********************************************************************/

      myINT   = In8 (configTable->MLIDCFG_DBusTag, (void *) configTable->MLIDCFG_IOPort0);
      myMMIO  = (UINT32) myINT;

      /********************************************************************\
      **    decode INT and MMIO/BIOS segment info and save
      \********************************************************************/

      configTable->MLIDCFG_MemoryAddress1 =
         (void *) ((((myMMIO & MMIO_SEGMENT_MASK) << 7) | MMIO_BIT) << 4);
      configTable->MLIDCFG_Interrupt0 = ((myINT & INTERRUPT_MASK)
            | ((myINT & INTERRUPT_MASK) << 1)) | 2;

      /********************************************************************\
      **    if NO S-RAM segment specified, put in a default value
      \********************************************************************/

      if (configTable->MLIDCFG_MemoryAddress0 == 0)
      {
         configTable->MLIDCFG_MemoryAddress0 =
            (void *) ((DEFAULT_RAM_SEGMENT + LOW_PRIMARY_PIO
            - (UINT8) configTable->MLIDCFG_IOPort0) << 12);
      }

      /********************************************************************\
      **    With S-RAM set, get the appropriate length
      \********************************************************************/

      CMSMReadPhysicalMemory (
         1,
         &i,
         configTable->MLIDCFG_DBusTag,
         (void *) (((UINT8 *) configTable->MLIDCFG_MemoryAddress1)
            + RAM_RELOCATION_REG + 1));

/* switch statement to correctly set MemorySize0   */

      switch (i & SHARED_RAM_MASK)
      {
         case SHARED_RAM_8K:
            configTable->MLIDCFG_MemorySize0 = 0x200;
            break;
         case SHARED_RAM_16K:
            configTable->MLIDCFG_MemorySize0 = 0x400;
            break;
         case SHARED_RAM_32K:
            configTable->MLIDCFG_MemorySize0 = 0x800;
            break;
         case SHARED_RAM_64K:
            configTable->MLIDCFG_MemorySize0 = 0x1000;
            break;
      }

         
      /********************************************************************\
      **    register hardware options, check if fail, or new frame
      \********************************************************************/

      ccode = CMSMRegisterHardwareOptions (configTable, &driverData);

      if (ccode == REG_TYPE_FAIL)
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }

      if (ccode == REG_TYPE_NEW_FRAME)
     {

         /* clear the shutdown bit */
                  
         configTable->MLIDCFG_SharingFlags &= ~MS_SHUTDOWN_BIT;

         /********************************************************************\
         *   This is a new frame type for an existing board
         *   We have already Initialized the hardware.
         *   Set up to produce NESL MLID Card Insertion Complete event 
         \********************************************************************/

         NESL_EPBPtr->EPBDataPtr0   = configTable;

         /* Generate NESL MLID Card Insertion Complete Event */

         CMSMNESLProduceEvent(NESLServiceResumeNECBPtr,
                                     NULL,
                              NESL_EPBPtr);

         return (ODISTAT_SUCCESSFUL);
      }

      /********************************************************************\
      **    MUST be new adapter...
      **    initialize the ADS now that we have a pointer to it
      \********************************************************************/

      CFixUpStatStrings (driverData);

      driverData->busType = busType;
      driverData->busTag  = configTable->MLIDCFG_DBusTag;

      /********************************************************************\
      **    set resetlevel
      \********************************************************************/

      if (configTable->MLIDCFG_Interrupt0 == 9)
         driverData->interruptResetLevel = RESET_IRQ_PORT + 2;
      else
         driverData->interruptResetLevel = RESET_IRQ_PORT
            + (UINT32) configTable->MLIDCFG_Interrupt0;

      busSignature = pcSignature;
   }

   driverData->commonIOPort        = configTable->MLIDCFG_IOPort0;
   driverData->absoluteMMIOAddress = (void *) configTable->MLIDCFG_LinearMemory1;

   if ((UINT8) driverData->commonIOPort - LOW_PRIMARY_PIO)
      driverData->boardNumber = 1;

   /***********************************************************************\
   **    compare bus signature with MMIO signature at 0x1F30
   \***********************************************************************/

   for (i = 0; i != SIGNATURE_SIZE; i++)
   {
      signature = Rd8 (configTable->MLIDCFG_DBusTag, NULL,
         (void *) ((UINT8 *) driverData->absoluteMMIOAddress + SIGNATURE_OFFSET
            + (i * 2)));
      if (signature - (*(busSignature + i) & 0xff))
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }
   }

   /***********************************************************************\
   **    verify shared-RAM is on correct boundary
   \***********************************************************************/

   if ((UINT32)((configTable->MLIDCFG_MemorySize0 << 4) - 1) &
       (UINT32)configTable->MLIDCFG_MemoryAddress0)
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   /***********************************************************************\
   **    check for BIOS/MMIO domain and shared-RAM overlap
   \***********************************************************************/

   driverData->commonMemoryDecode0 = configTable->MLIDCFG_MemoryAddress0;
   driverData->commonLinearMemory0 = (void *) configTable->MLIDCFG_LinearMemory0;
   driverData->sharedRAMRelative   = (void *) configTable->MLIDCFG_LinearMemory0;

   if (configTable->MLIDCFG_MemoryAddress0 < configTable->MLIDCFG_MemoryAddress1)
   {
      if (((UINT8 *)configTable->MLIDCFG_MemoryAddress1 -
           (UINT8 *)configTable->MLIDCFG_MemoryAddress0) <
           (configTable->MLIDCFG_MemorySize0 << 4))
      {
         CMSMReturnDriverResources (configTable);
         return (ODISTAT_FAIL);
      }
   }
   else if (((UINT8 *)configTable->MLIDCFG_MemoryAddress0 -
             (UINT8 *)configTable->MLIDCFG_MemoryAddress1) <
              (configTable->MLIDCFG_MemorySize1 << 4))
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   /***********************************************************************\
   **    read node address from adapter unless there was a node override
   \***********************************************************************/

   if ((configTable->MLIDCFG_NodeAddress.nodeAddress [0] == 0xff) &&
       (configTable->MLIDCFG_NodeAddress.nodeAddress [1] == 0xff) &&
       (configTable->MLIDCFG_NodeAddress.nodeAddress [2] == 0xff) &&
       (configTable->MLIDCFG_NodeAddress.nodeAddress [3] == 0xff) &&
       (configTable->MLIDCFG_NodeAddress.nodeAddress [4] == 0xff) &&
       (configTable->MLIDCFG_NodeAddress.nodeAddress [5] == 0xff))
   {
      for (i = 0; i < 6; i ++)
      {
         nodeHI = Rd8 (configTable->MLIDCFG_DBusTag, NULL,
            (void *) ((UINT8 *) driverData->absoluteMMIOAddress
               + NODE_ADDRESS_OFFSET + (i * 4)));
         nodeHI = nodeHI << 4;
         nodeLO  = Rd8 (configTable->MLIDCFG_DBusTag, NULL,
            (void *) ((UINT8 *) driverData->absoluteMMIOAddress
               + NODE_ADDRESS_OFFSET + (i * 4) + 2));
         nodeLO  = (nodeLO & 0x0f) | nodeHI;

         configTable->MLIDCFG_NodeAddress.nodeAddress [i] = nodeLO;
      }
   }

   for (i = 0; i < 6; i++)
      driverData->commonNodeAddress [i] = configTable->MLIDCFG_NodeAddress.nodeAddress [i];

   /***********************************************************************\
   **    initialize DIROpenAdapter structure and MSMTxFreeCount
   \***********************************************************************/

   TxBufferLenValue = (UINT16)TBZOption.Parameter1.Max;   /* TNL 8/25/95   */

   driverData->DIROA.OpenMaxLinkStations = LinkStationsValue;
   driverData->DIROA.OpenMaximumSAPs     = MaxSAPsValue;
   driverData->DIROA.OpenTxBuffers       = TxBuffersValue;
   driverData->DIROA.OpenTxLength        = (TxBufferLenValue << 8)
                                    | (TxBufferLenValue >> 8);

   DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = TxBuffersValue+1;

   /***********************************************************************\
   **    return custom keyword values to defaults in case re-entered
   \***********************************************************************/

   LinkStationsValue = OPEN_LINK_STATIONS;
   MaxSAPsValue      = OPEN_MAX_SAPS;
   TxBuffersValue    = OPEN_TX_BUFFERS;
   TxBufferLenValue  = 0;

   /***********************************************************************\
   **    initialize and OPEN token-ring adapter
   \***********************************************************************/

#ifndef NO_TX_LIMIT

   if (configTable->MLIDCFG_MaxFrameSize > 4202)
      driverData->commonMaximumSize = 4202;
   else
      driverData->commonMaximumSize = configTable->MLIDCFG_MaxFrameSize;

#else

   driverData->commonMaximumSize = configTable->MLIDCFG_MaxFrameSize;

#endif /* NO_TX_LIMIT */

  /********************************************************************\
  **    set up our interrupt procedure and set resetlevel
  \********************************************************************/

    if (CMSMSetHardwareInterrupt (driverData, configTable) != 0)
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   /***********************************************************************\
   **    initialize the hardware
   \***********************************************************************/
/* AYD 04-30-97 */
   if( DriverReset(driverData,
                      configTable,
                      OP_SCOPE_ADAPTER) > ODISTAT_RESPONSE_DELAYED )
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   driverData->AdapterResetCount = 0;

   if (driverData->initStatus & INIT_FAST_PATH)
      DriverParameterBlock.DriverSendPtr = (void (*)()) DriverSendFastPath;
   else
      DriverParameterBlock.DriverSendPtr = (void (*)()) DriverSend;

   /***********************************************************************\
   **   adapter initialization COMPLETE
   \***********************************************************************/

   configTable->MLIDCFG_LineSpeed    = driverData->commonLineSpeed;
   configTable->MLIDCFG_MaxFrameSize = driverData->commonMaximumSize;

   if (CMSMScheduleAES(driverData, &(driverData->DAES)))
   {
      CMSMReturnDriverResources(configTable);
      return ODISTAT_FAIL;
   }

   if (CMSMRegisterMLID (driverData, configTable))
   {
      CMSMReturnDriverResources (configTable);
      return (ODISTAT_FAIL);
   }

   CMSMPrintString (
      configTable,
      MSG_TYPE_INIT_INFO,
      CNTR2000_SIGN_ON_MSG,
      (void *) driverData->boardNumber,
      (void *) configTable->MLIDCFG_LineSpeed);

   CMSMPrintString (
      configTable,
      MSG_TYPE_INIT_INFO,
      driverData->pageSizeMSG, 0, 0);

#ifdef NO_TX_LIMIT

   CMSMPrintString (
      configTable,
      MSG_TYPE_INIT_INFO,
      CNTR2000_PKTSIZE_MSG1,
      (void *) driverData->commonMaximumSize, 0);

#endif /* NO_TX_LIMIT */

   if (driverData->sendMSG)
   {
      CMSMPrintString (
         configTable,
         MSG_TYPE_INIT_INFO,
         driverData->sendMSG, 0, 0);
   }


   TBZOption.Parameter1.Max = 17954;      /* Reset Options for next load   */

   return   ODISTAT_SUCCESSFUL;
}

/**************************************************************************\
**
** PROC NAME:     DriverRemove
**
**                This routine will called when the driver image is
**                to be deleted from memory.
**
** Parameters:    NONE
**
** Return Value:  NONE
**
** See Also:
**
\**************************************************************************/

void
DriverRemove (void)
{

/* Clean up all NESL related stuff   */

   CMSMNESLDeRegisterProducer(NESLServiceResumeNECBPtr);
   CMSMFree(NULL,NESLServiceResumeNECBPtr);
   CMSMFree(NULL,NESL_EPBPtr);

   CMSMDriverRemove (DriverParameterBlock.DriverModuleHandle);
   return;
}

/**************************************************************************\
**
** PROC NAME:     DriverReset
**
**                This routine will called when the driver needs to be
**                reset to its original pristine state.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

ODISTAT
DriverReset (
            DRIVER_DATA       *driverData,
            CONFIG_TABLE      *configTable,
            OPERATION_SCOPE   operationScope)
{
   void     *MMIO;

   UINT8    eCode;
   UINT8    DHBSize;
   UINT8    ramRelocValue;
   UINT8    ramRelocMask;

   UINT16   ramSize;
   UINT16   page;
   UINT16   *txSizeTable;
   UINT16   txTableSize;

   UINT32   address;
   UINT32   txCommonSize;
   UINT32   txSize;
   UINT32   memPattern;
   UINT32   i,j;

   if (operationScope == OP_SCOPE_ADAPTER)
   {
      MMIO = ((DRIVER_DATA *) driverData)->absoluteMMIOAddress;

         if (driverData->inDriverReset)
         return ODISTAT_SUCCESSFUL;

      driverData->inDriverReset++;
      driverData->AdapterResetCount++;
      driverData->initRetryCounter = MAX_INIT_RETRIES;
   
      /***********************************************************************\
      **    start RESET loop by shutting down the driver (& checking retries)
      \***********************************************************************/
   
      do
      {
         do
         {
            do
            {
            DriverShutdown (driverData, configTable, SHUTDOWN_PARTIAL, 
                                OP_SCOPE_ADAPTER);

               driverData->initRetryCounter--;
               if (!driverData->initRetryCounter)
               {
                  driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
                  driverData->inDriverReset   = 0;
                  CMSMPrintString (
                     configTable,
                     MSG_TYPE_INIT_ERROR,
                     CNTR2000_INIT_FAIL_MSG, 0, 0);
                  return (ODISTAT_FAIL);
               }
   
               /**************************************************************\
               **    disable paging for 8k & 64k, enable for 16k & 32k S-RAM
               \**************************************************************/
   
               driverData->pageSizeMask = 0x100 - 1;
               ramRelocValue      = Rd8 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1));
   
               ramRelocMask = ramRelocValue & SHARED_RAM_MASK;
   
               if (ramRelocMask == SHARED_RAM_8K)
               {
                  driverData->pageSizeMSG = CNTR2000_MEMSIZE_8K_MSG;
                  driverData->pageSize8KFlag = 1;
               }
               else if (ramRelocMask == SHARED_RAM_64K)
                  driverData->pageSizeMSG = CNTR2000_MEMSIZE_64K_MSG;
               else
               {
                  Wrt8 (
                     configTable->MLIDCFG_DBusTag,
                     NULL,
                     (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
                     PAGING_ACTIVE_FLAG);
   
                  if (ramRelocMask == SHARED_RAM_32K)
                  {
                     driverData->pageSizeMSG  = CNTR2000_MEMSIZE_32K_MSG;
                     driverData->pageSize     = 0x8000;
                     driverData->pagingMask   = 0x80;
                     driverData->pageSizeMask = 0x80 - 1;
                  }
                  else
                  {
                     driverData->pageSizeMSG  = CNTR2000_MEMSIZE_16K_MSG;
                     driverData->pageSize     = 0x4000;
                     driverData->pagingMask   = 0xc0;
                     driverData->pageSizeMask = 0x40 - 1;
                  }
               }
   
               Wrt8 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG),
                  (UINT8) ((UINT32) driverData->commonMemoryDecode0 >> 12));
   
               ramRelocValue = Rd8 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1));
   
               Wrt8 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1),
                  ramRelocValue & ~PARTIAL_RESET);

                 driverData->MLIDStatusFlag &= ~NIC_INTERRUPTED_BIT;   

               Wrt8 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + OR_OFFSET),
                  INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT);
   
               /**************************************************************\
               **    wait for DIR.Initialize complete interrupt
               \**************************************************************/
   
            }
            while (WaitForEvent (
               driverData,
               configTable->MLIDCFG_DBusTag,
               INIT_TIMEOUT_IN_TICKS,
               NIC_INTERRUPTED_BIT,
               (UINT16 *) &(driverData->MLIDStatusFlag),
               NULL));
   
            /*****************************************************************\
            **    process the DIR.Initialize complete interrupt
            \*****************************************************************/
   
            address = Rd32 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + WRITE_REGION_BASE));
   
            driverData->ivt_SRB.pageValue    = (UINT8) address;
            driverData->ivt_SRB.baseAddress  = (void *)
               ((UINT32)driverData->commonLinearMemory0
               + (UINT32)VALUE_TO_HILO_UINT16(
                  (UINT16)(address & ((UINT32)driverData->pageSizeMask | 0xffffff00))));
   
            Wrt8 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
               (UINT8) address);
         }
         while ((Rd8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + DIR_INIT_COMMAND_CODE))
            != SRB_INIT_COMPLETE));
   
         driverData->initStatus = Rd8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + DIR_INIT_STATUS));
   
         /********************************************************************\
         **    calculate the data rate and the maximum transmit buffer size
         \********************************************************************/
   
         page = Rd16 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *)((UINT8 *)driverData->ivt_SRB.baseAddress + DIR_INIT_ADPTR_PM_ADDR));
   
         driverData->adapterParmsPageValue = (UINT8) page;
         address = (UINT32)VALUE_TO_HILO_UINT16(
            page & ((UINT16)driverData->pageSizeMask | 0xff00));
   
         driverData->adapterParmsAddr = (void *) ((UINT8 *) driverData->sharedRAMRelative
            + address);
   
         if (driverData->initStatus & INIT_16_MBPS)
         {
            txSizeTable = transmitSizeTable16Mb;
            DHBSize     = Rd8 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + ADAPTER_ID_OFFSET + 0x0a + 2));
            driverData->commonLineSpeed = 16;
         }
         else
         {
            txSizeTable = transmitSizeTable4Mb;
            DHBSize     = Rd8 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + ADAPTER_ID_OFFSET + 0x0a));
         }
   
         DHBSize &= 0x0f;
   
         if (DHBSize < 0x0b)
            DHBSize = 0;
         else
            DHBSize -= 0x0b;
   
             DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = 2;
   
         txTableSize  = txSizeTable [DHBSize];
         txCommonSize = driverData->commonMaximumSize + 6;
   
#ifdef NO_TX_LIMIT
   
         if (!(driverData->initStatus & INIT_FAST_PATH))
         {
            if (txCommonSize > (4202 + 6))
               txCommonSize = 4202 + 6;
         }
   
#endif /* NO_TX_LIMIT */
   
         txSize = (UINT32)VALUE_TO_HILO_UINT16(driverData->DIROA.OpenTxLength);

         if (!txSize)
            txSize = txCommonSize;
   
         if (txSize > (UINT32) txTableSize)
            txSize =  (UINT32) txTableSize;
   
         if (txSize > txCommonSize)
            txSize = txCommonSize;
   
         if (((Rd8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1))
               & SHARED_RAM_MASK) - SHARED_RAM_8K)
            == 0)
         {
            driverData->DIROA.OpenTxBuffers = 1;
            DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = 1;
   
            if (txSize > 2048)
               txSize = 2048;
         }
   
         driverData->commonMaximumSize  = txSize - 6;
         driverData->DIROA.OpenTxLength = VALUE_TO_HILO_UINT16((txSize & 0xfffffff8));
   
         eCode  = Rd8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *)((UINT8 *)driverData->ivt_SRB.baseAddress + DIR_INIT_ERROR_CODE +1));
   
         eCode |= Rd8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + DIR_INIT_ERROR_CODE));
      }
      while (eCode);
   
      /***********************************************************************\
      **    perform S-RAM read/write test
      \***********************************************************************/
   
      memPattern = (0x55 << 16) | (0xaa << 8) + 0xff;
   
      for (j = 0; j < 8; j++)
      {
         for (i = 0; i < (sizeof (tDIROpenAdapter) / 4); i++)
         {
            Wrt32 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + (i * 4)),
               memPattern);
         }
   
         for (i = 0; i < (sizeof (tDIROpenAdapter) / 4); i++)
         {
            if (Rd32 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + (i * 4)))
               != memPattern)
            {
               driverData->inDriverReset = 0;
               CMSMPrintString (
                  configTable,
                  MSG_TYPE_INIT_ERROR,
                  CNTR2000_MEM_FAIL_MSG, 0, 0);
               return (ODISTAT_FAIL);
            }
         }
         memPattern = (memPattern >> 4) | (memPattern << 28);
      }
   
      /***********************************************************************\
      ** TNL 6/20/95 Shared RAM works fine. Check for zeroing top 512 bytes
      \***********************************************************************/
   
      if (((Rd8 (
           configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1))
            & SHARED_RAM_MASK) - SHARED_RAM_8K)
         != 0)                              /* Don't do it if 8k Shared RAM   */
      {
         
         j = Rd8 (                  /* Read Shared RAM mode from ID PROM   */
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + ADAPTER_ID_OFFSET + 6));
   
         if (((j & 0x0f) - 0x0b) == 0)   
         {                  /* If 0xb then we must zero out top 512 bytes    */
            for (i = (sizeof (tDIROpenAdapter) / 4);
                 i < ((sizeof (tDIROpenAdapter) + 512) / 4);
                 i++)
            {
               Wrt32 (
                  configTable->MLIDCFG_DBusTag,
                  NULL,
                  (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + (i * 4)),
                  0);
            }
         }
      }
   
      /***********************************************************************\
      **    issue DIR.Open.Adapter
      \***********************************************************************/
   
      Wrt16 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
         0);
   
      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + OR_OFFSET),
         INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT);
   
      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         driverData->ivt_SRB.pageValue);
   
   #ifdef BROUTER
   
      if (driverData->brouterState)
      {
         driverData->initStatus &= ~INIT_FAST_PATH;
      
         Wrt16 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
            0);
   
         Wrt8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + OR_OFFSET),
            INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT);
   
         MovToBus16 (
            driverData->busTag,
            NULL,
            driverData->ivt_SRB.baseAddress,
            driverData->bConfigCommand,
            CONFIG_BRIDGE_SIZE / 2);

         driverData->MLIDStatusFlag = 0;

         Wrt8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + 1),
            COMMAND_IN_SRB);

         driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;

         Wrt8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            0);

         driverData->inDriverReset = 0;
/* AYD 04-30-97 Replaced return code */
/*         return ODISTAT_SUCCESSFUL; */
         return ODISTAT_RESPONSE_DELAYED;

      }

   #endif /* BROUTER */

      if (driverData->initStatus & INIT_FAST_PATH)
      {
         driverData->initStatus &= ~INIT_FAST_PATH;
         if (!driverData->pageSize8KFlag)
         {
            /*****************************************************************\
            **    Fast Path supported
            \*****************************************************************/

            driverData->sendMSG = CNTR2000_FAST_PATH_MSG;

   #ifdef NO_TX_LIMIT

            ramSize = (16 + 512 + ((4096 + 512) * 5)) / 8;
   #else
            ramSize = (16 + 512 + ((4096 + 512) * 4)) / 8;

   #endif /* NO_TX_LIMIT */

            ramSize = VALUE_TO_HILO_UINT16(ramSize);

            driverData->configFastPath [8] = ((UINT8 *)&ramSize)[0];
            driverData->configFastPath [9] = ((UINT8 *)&ramSize)[1];

            MovToBus32 (
               driverData->busTag,
               NULL,
               driverData->ivt_SRB.baseAddress,
               driverData->configFastPath,
               CONFIG_FAST_PATH_SIZE / 4);

              driverData->MLIDStatusFlag &= ~NIC_INTERRUPTED_BIT;

            Wrt8 (
               configTable->MLIDCFG_DBusTag,
               NULL,
               (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + 1),
               COMMAND_IN_SRB);

            if (!WaitForEvent (
               driverData,
               configTable->MLIDCFG_DBusTag,
               INIT_TIMEOUT_IN_TICKS,
               NIC_INTERRUPTED_BIT,
               (UINT16 *) &(driverData->MLIDStatusFlag),
               0))
            {

               if (!Rd8 (configTable->MLIDCFG_DBusTag, NULL,
                  (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + FPR_RET_CODE)))
               {
                  driverData->initStatus |= INIT_FAST_PATH;

#ifdef NO_TX_LIMIT

                  DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount =
                     (4096 * 5) / driverData->commonMaximumSize;
#else
                  DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = 4;

#endif /* NO_TX_LIMIT */

                  page = Rd16 (
                     driverData->busTag,
                     NULL,
                     (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress
                        + FPR_FAST_PATH_XMIT));
                  driverData->ivt_FTX.pageValue   = (UINT8) page;
                  driverData->ivt_FTX.baseAddress =
                     (void *) ((UINT32)driverData->sharedRAMRelative
                     + (UINT32)VALUE_TO_HILO_UINT16(
                        page & ((UINT16)driverData->pageSizeMask | 0xff00)));

                  page = Rd16 (
                     driverData->busTag,
                     NULL,
                     (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress
                        + FPR_SRB_ADDRESS));
                  driverData->ivt_SRB.pageValue   = (UINT8) page;
                  driverData->ivt_SRB.baseAddress =
                     (void *) ((UINT32) driverData->commonLinearMemory0
                     + (UINT32)VALUE_TO_HILO_UINT16(
                        page & ((UINT16)driverData->pageSizeMask | 0xff00)));

                  Wrt8 (
                     driverData->busTag,
                     NULL,
                     (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
                     (UINT8) page);
               }
            }
         }

         /********************************************************************\
         **    NO Fast Path supported
         \********************************************************************/

         else
            driverData->sendMSG = CNTR2000_PKTSIZE_MSG2;
      }
      else
         driverData->sendMSG = 0;

      /**********************************************************************\
      **    Fast Path checked
      \***********************************************************************/

      Wrt16 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
         0);

      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + OR_OFFSET),
         INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT);

      MovToBus32 (
         driverData->busTag,
         NULL,
         driverData->ivt_SRB.baseAddress,
         &driverData->DIROA,
         OPEN_ADAPTER_SIZE / 4);

      /**********************************************************************\
      **    copy node address to DIROpenAdapter Area
      \***********************************************************************/

      MovToBus32 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + SOPEN_NODE_ADDRESS),
         driverData->commonNodeAddress,
         1);

      MovToBus16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + SOPEN_NODE_ADDRESS + 4),
         (void *) ((UINT8 *) &driverData->commonNodeAddress + 4),
         1);

      /**********************************************************************\
      **    clear state flag, issue command, set busy flag, zero out page
      \***********************************************************************/

      driverData->MLIDStatusFlag = 0;

      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + 1),
         COMMAND_IN_SRB);

      driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         0);

      driverData->OpeningAdapter = -1;
      driverData->inDriverReset = 0;
/* AYD 04-30-97 Replaced return code */
      /* return ODISTAT_SUCCESSFUL; */
         return ODISTAT_RESPONSE_DELAYED;
   }
   else
      return ODISTAT_SUCCESSFUL;
}

/**************************************************************************\
**
** PROC NAME:     DriverManagement
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

#ifdef BROUTER

ODISTAT
DriverManagement (
   DRIVER_DATA       *driverData,
   CONFIG_TABLE      *configTable,
   ECB               *ecb)
{
   void     *MMIO;
   UINT8    ramRelocValue;
   UINT32   temp;

   if (!((ecb->ECB_ProtocolID.protocolID [0] == 'B') &&
      (ecb->ECB_ProtocolID.protocolID [1] == 'R')    &&
      (ecb->ECB_ProtocolID.protocolID [2] == 'O')    &&
      (ecb->ECB_ProtocolID.protocolID [3] == 'U')    &&
      (ecb->ECB_ProtocolID.protocolID [4] == 'T')    &&
      (ecb->ECB_ProtocolID.protocolID [5] == 'E')))
   {
      return ODISTAT_NO_SUCH_HANDLER;
   }

   if (((HUB_ECB *) ecb)->HECB_BrouterRequestCode == BROUTER_SUPPORT)
   {
      temp = BROUTER_STATUS;
      ((HUB_BR_ECB *) ecb)->BR_BrouterSupportStatus = (void *) temp;
      return ODISTAT_SUCCESSFUL;
   }

   if (((HUB_ECB *) ecb)->HECB_BrouterRequestCode != SELECT_SR_BRIDGING)
      return ODISTAT_BAD_PARAMETER;

   MMIO = driverData->absoluteMMIOAddress;

   ramRelocValue = Rd8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1));

   ramRelocValue &= SHARED_RAM_MASK;

   if (ramRelocValue == SHARED_RAM_8K)
      return ODISTAT_NO_SUCH_HANDLER;

   driverData->brouterState = (UINT32) (((HUB_SR_ECB *) ecb)->SR_ServiceHandler);
   driverData->bParmsPBits = ((HUB_SR_ECB *) ecb)->SR_PartitionSize;
   driverData->bParmsBNumber = VALUE_TO_HILO_UINT16(
      ((HUB_SR_ECB *)ecb)->SR_BridgeNumber);
   driverData->bParmsSRing = VALUE_TO_HILO_UINT16(
      ((HUB_SR_ECB *)ecb)->SR_RingInNumber);
   driverData->bParmsTRing = VALUE_TO_HILO_UINT16(
      ((HUB_SR_ECB *)ecb)->SR_RingOutNumber);
   driverData->bParmsCopySTE [0] = ((HUB_SR_ECB *) ecb)->SR_FilterSTE ^ 0x01;

   return (DriverReset (driverData, configTable, OP_SCOPE_ADAPTER));
}

#endif /* BROUTER */

/**************************************************************************\
**
** PROC NAME:     DriverMulticastChange
**
**                This routine will save the 32-bit functional address
**                passed, and sets a flag so that the next time the SRB
**                free, the new functional address will be passed to the
**                adapter.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

ODISTAT
DriverMulticastChange (
   DRIVER_DATA         *driverData,
   CONFIG_TABLE      *configTable,
   GROUP_ADDR_LIST_NODE   *mcTable,
   UINT32            numEntries,
   UINT32            functionalTable)
{
   configTable       = configTable;
   mcTable    = mcTable;
   numEntries = numEntries;

   driverData->functionalAddress = functionalTable;
   driverData->MLIDStatusFlag   |= DIR_FUNCTIONAL_BIT;

   CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
   return ODISTAT_SUCCESSFUL;
}

/**************************************************************************\
**
** PROC NAME:     DriverShutdown
**
**                This routine will called when the driver needs to be
**                shudown either temporarily or permanently.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

ODISTAT
DriverShutdown (
            DRIVER_DATA       *driverData,
            MLID_ConfigTable  *configTable,
            UINT32            shutDownType,
            OPERATION_SCOPE   operationScope)
{
   TCB      *nextTCB;
   TCB      *tcb;
   void     *MMIO;
   UINT8    ramRelocValue;
   UINT32   startTime;

#ifdef OUT_CHAR
   CMSMOutMEON ('D', ATTRIB);
#endif /* OUT_CHAR */

   shutDownType = shutDownType;        /* to avoid compiler warnings   */
   operationScope = operationScope;

//JCJ 22-July-1997 SPD #161861 When a shutdown is called with a scope of LOGICAL_BOARD
//              justreturn without doing anything.
   if (operationScope == OP_SCOPE_LOGICAL_BOARD)
         return (ODISTAT_SUCCESSFUL);
//JCJ SPD #161861 End

   driverData->CompletionQHead = 0;

   MMIO = driverData->absoluteMMIOAddress;

   if (MMIO)
   {
      driverData->MLIDStatusFlag = IGNORE_INTERRUPT_BIT;

      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
         255 - INTERRUPT_ENABLE_BIT - NMI_DISABLED_BIT);


      /********************************************************************\
      **    pull the adapter reset line and wait for at least 50 mills.
      \********************************************************************/

      ramRelocValue = Rd8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1));

      ramRelocValue &= ALTERNATE_IPL;
      ramRelocValue |= PARTIAL_RESET;

      driverData->MLIDStatusFlag = ADAPTER_RESET_BIT;
      Out8 (configTable->MLIDCFG_DBusTag, (void *) (configTable->MLIDCFG_IOPort0 + 1),
         ramRelocValue);

      startTime = CMSMGetMicroTimer ();

      do
      {
         CMSMYieldWithDelay();
      }
      while ((CMSMGetMicroTimer () - startTime) < 50000);

      /********************************************************************\
      **    release the adapter reset
      \********************************************************************/


      Out8 (configTable->MLIDCFG_DBusTag, (void *) (configTable->MLIDCFG_IOPort0 + 2),
         ramRelocValue);

      Wrt8 (
         configTable->MLIDCFG_DBusTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_RELOCATION_REG + 1),
         ramRelocValue);
   }

   driverData->MLIDStatusFlag = IGNORE_INTERRUPT_BIT;

   /********************************************************************\
   **    return TCB in process
   \********************************************************************/

   tcb = driverData->tcbInProcess;
   driverData->tcbInProcess = 0;

   if (tcb)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

#ifdef USE_FAST_CALLS
      CTokenTSMFastSendComplete (driverData, tcb, 1);
#else
      CTokenTSMSendComplete (driverData, tcb, 1);
#endif /* USE_FAST_CALLS */

      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      driverData->txStartTime = 0;
   }

   /********************************************************************\
   **    return TCBs in queue
   \********************************************************************/

   tcb = driverData->SendQueueHead;

   while (tcb)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('2', ATTRIB);
#endif /* OUT_CHAR */

      nextTCB = (TCB *) tcb->TCB_DriverWS [TCB_LINK];

      CTokenTSMFastSendComplete (driverData, tcb, 1);
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      driverData->txStartTime = 0;

      tcb = nextTCB;
   }

   /********************************************************************\
   **    return Tx in process
   \********************************************************************/

   tcb = driverData->txInProcessHead;

   while (tcb)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('3', ATTRIB);
#endif /* OUT_CHAR */

      nextTCB = (TCB *) tcb->TCB_DriverWS [TCB_LINK];

      CTokenTSMFastSendComplete (driverData, tcb, 1);
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      driverData->txStartTime = 0;

      tcb = nextTCB;
   }

   driverData->txInProcessHead = 0;
   driverData->SendQueueHead   = 0;

   return (ODISTAT_SUCCESSFUL);
}

/**************************************************************************\
**
** PROC NAME:     DriverSend
**
**                This routine will called when the driver wants to
**                send a packet out onto the media.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DriverSend (
            DRIVER_DATA       *driverData,
            MLID_ConfigTable  *configTable,
            TCB               *tcb,
            UINT32            pktSize,
            void              *physTcb)
{
   void     *MMIO;
   UINT8    oldPage;
   TCB      *oldSendQueueTail;

   configTable    = configTable;
   pktSize = pktSize;
   physTcb = physTcb;

#ifdef OUT_CHAR
   CMSMOutMEON ('S', ATTRIB);
#endif /* OUT_CHAR */

   if (!driverData->startSendFlag)
   {
#ifdef BROUTER

      /********************************************************************\
      **   check if DriverSendBridge
      \********************************************************************/

      if (driverData->brouterState)
      {
         DriverSendBridge (driverData, configTable, tcb, pktSize, physTcb);
         return;
      }

#endif /* BROUTER */

      /********************************************************************\
      **   check if inside of the DriverReset routine
      \********************************************************************/

      if (driverData->inDriverReset || driverData->OpeningAdapter)
      {

#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

         DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
         driverData->txStartTime = 0;
         CTokenTSMFastSendComplete (driverData, tcb, 1);
         return;
      }

      /********************************************************************\
      **   set link to end of queue
      \********************************************************************/

      tcb->TCB_DriverWS [TCB_LINK] = 0;

      /********************************************************************\
      **   check to see if the card is still using the SRB.
      \********************************************************************/

      if (driverData->MLIDStatusFlag & (DIR_READ_LOG_BIT | DIR_FUNCTIONAL_BIT
         | TX_IN_PROCESS_BIT | SRB_IS_BUSY_BIT))
      {
         /*****************************************************************\
         **    SRB is busy, enqueue the send for later processing.
         \*****************************************************************/


#ifdef OUT_CHAR
   CMSMOutMEON ('2', ATTRIB);
#endif /* OUT_CHAR */
   
         oldSendQueueTail = driverData->SendQueueTail;
         driverData->SendQueueTail = tcb;

         if (!driverData->SendQueueHead)
            oldSendQueueTail = (TCB *)((UINT32)&driverData->SendQueueHead - (UINT32)&((TCB *)0)->TCB_DriverWS);

         oldSendQueueTail->TCB_DriverWS[TCB_LINK] = (UINT32)tcb;

         CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
         return;
      }
   }

   /***********************************************************************\
   **   startSend area
   **
   **   looks like the SRB is free to use
   \***********************************************************************/

   driverData->startSendFlag  = 0;

   MMIO    = driverData->absoluteMMIOAddress;
   oldPage = Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG));

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_SRB.pageValue);

   driverData->tcbInProcess    = tcb;
   driverData->MLIDStatusFlag |= TX_IN_PROCESS_BIT;

   MovToBus32 (
      driverData->busTag,
      NULL,
      driverData->ivt_SRB.baseAddress,
      TxDIRFrame,
      SRB_SIZE / 4);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      COMMAND_IN_SRB);

   driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      oldPage);

#ifdef OUT_CHAR
   CMSMOutMEON ('s', ATTRIB);
#endif /* OUT_CHAR */
}

/**************************************************************************\
**
** PROC NAME:     DriverSendFastPath
**
**                This routine will be called when the driver wants to
**                send a packet out onto the media.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DriverSendFastPath (
            DRIVER_DATA       *driverData,
            MLID_ConfigTable  *configTable,
            TCB               *tcb,
            UINT32            pktSize,
            TCB               *physTcb)
{

   FRAGMENTSTRUCT       *fragPtr;

   void     *txBuffer;
   void     *FPBase;
   void     *FPNewBase;
   void     *MMIO;
   void     *copySource;

   UINT32   copyBytes;
   UINT32   fragCount;

   UINT16   qHead;

   configTable = configTable;
   pktSize = pktSize;
   physTcb = physTcb;

#ifdef OUT_CHAR
   CMSMOutMEON ('F', ATTRIB);
#endif /* OUT_CHAR */

#ifdef OUT_CHAR
   CMSMOutUINT32 ((UINT32) tcb, ATTRIB);
#endif /* OUT_CHAR */

#ifdef BROUTER

   if (driverData->brouterState)
   {
      DriverSendBridge (driverData, configTable, tcb, pktSize, physTcb);
      return;
   }

#endif /* BROUTER */

   /***********************************************************************\
   **   if fast path is NOT opened, free up resource and return
   \***********************************************************************/

   if (!driverData->CompletionQHead)
   {
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      driverData->txStartTime = 0;
      CTokenTSMFastSendComplete (driverData, tcb, 1);
      return;
   }

   MMIO = driverData->absoluteMMIOAddress;

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_FTX.pageValue);

   driverData->txLastBuffer = (UINT32) Rd16 (
      driverData->busTag,
        NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + FP_FREE_Q_HEAD));

   /***********************************************************************\
   **   get first transmit buffer
   \***********************************************************************/

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      (UINT8) driverData->txLastBuffer);

   FPBase = (void *) ((UINT32) driverData->sharedRAMRelative
      + (UINT32)VALUE_TO_HILO_UINT16( (UINT16)(driverData->txLastBuffer
         & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

   /***********************************************************************\
   **   fill out necessary information
   \***********************************************************************/

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) FPBase - FP_TX_NEXT_BUFFER + FP_TX_COMMAND),
      SRB_TX_DIR_FRAME);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) FPBase - FP_TX_NEXT_BUFFER + FP_TX_CORRELATOR),
      driverData->TxCorrelator);

   driverData->TxCorrelator = (driverData->TxCorrelator + 1) & 0x7f;

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) FPBase - FP_TX_NEXT_BUFFER + FP_TX_STATION_ID),
      0);

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) FPBase - FP_TX_NEXT_BUFFER + FP_TX_FRAME_LENGTH),
      VALUE_TO_HILO_UINT16((UINT16)tcb->TCB_DataLen));

   driverData->txBufferSpace   = 512 - 22;
   driverData->txCurrentBuffer = FPBase;

   /***********************************************************************\
   **   copy TCB header to first buffer
   \***********************************************************************/

   driverData->txBufferSpace -= tcb->TCB_MediaHeaderLen;
   txBuffer = (void *)((UINT8 *) FPBase - FP_TX_NEXT_BUFFER + FP_TX_FRAME_DATA);

   MovFastToBus (
      driverData->busTag,
      NULL,
      txBuffer,
      &tcb->TCB_MediaHeader,
      tcb->TCB_MediaHeaderLen);

   txBuffer = (void *) ((UINT8 *) txBuffer + tcb->TCB_MediaHeaderLen);

   /***********************************************************************\
   **   copy the rest of the packet
   \***********************************************************************/

   fragPtr    = &tcb->TCB_FragBlockPtr->TCB_Fragment;
   fragCount  = tcb->TCB_FragBlockPtr->TCB_FragmentCount;

   while (fragCount)
   {
      copyBytes  = fragPtr->FragmentLength;
      copySource = fragPtr->FragmentAddress;

      while (copyBytes > driverData->txBufferSpace)
      {
         /**************************************************************\
         **   frag WON'T fit in tx buff, so fill in rest & get new buff
         \**************************************************************/

#ifdef OUT_CHAR
   CMSMOutMEON ('w', ATTRIB);
#endif /* OUT_CHAR */

         copyBytes -= driverData->txBufferSpace;

         MovFastToBus (
            driverData->busTag,
            NULL,
            txBuffer,
            copySource,
            driverData->txBufferSpace);

         Wrt16 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) driverData->txCurrentBuffer - FP_TX_NEXT_BUFFER
               + FP_TX_BUFFER_LENGTH),
            0xea01);       /* 512-22 LO-HI order */

         driverData->txLastBuffer = Rd16 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) driverData->txCurrentBuffer - FP_TX_NEXT_BUFFER
               + FP_TX_NEXT_BUFFER));

         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            (UINT8) driverData->txLastBuffer);

         driverData->txCurrentBuffer = (void *) ((UINT32) driverData->sharedRAMRelative
            + (UINT32)VALUE_TO_HILO_UINT16( (UINT16)(driverData->txLastBuffer
               & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

         txBuffer   = (void *) ((UINT8 *) driverData->txCurrentBuffer
            - FP_TX_NEXT_BUFFER + FP_TX_FRAME_DATA);
         copySource = (void *) ((UINT8 *) copySource + driverData->txBufferSpace);
         driverData->txBufferSpace  = 512 - 22;
      }

      driverData->txBufferSpace -= copyBytes;

#ifdef OUT_CHAR
   CMSMOutMEON ('.', ATTRIB);
#endif /* OUT_CHAR */

      MovFastToBus (
         driverData->busTag,
         NULL,
         txBuffer,
         copySource,
         copyBytes);

      txBuffer = (void *) ((UINT8 *) txBuffer + copyBytes);
      fragPtr++;
      fragCount--;
   }

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) driverData->txCurrentBuffer - FP_TX_NEXT_BUFFER
         + FP_TX_BUFFER_LENGTH),
      VALUE_TO_HILO_UINT16((UINT16)(512 - 22 - driverData->txBufferSpace)));

   qHead = Rd16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) driverData->txCurrentBuffer - FP_TX_NEXT_BUFFER
         + FP_TX_NEXT_BUFFER));

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_FTX.pageValue);

   txBuffer = (void *) Rd16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + FP_FREE_Q_HEAD));

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      (UINT8) txBuffer);

   FPNewBase = (void *) ((UINT32) driverData->sharedRAMRelative
      + (UINT32)VALUE_TO_HILO_UINT16(
         (UINT16)((UINT32)txBuffer
            & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) FPNewBase - FP_TX_NEXT_BUFFER + FP_TX_LAST_BUFFER),
      (UINT16) driverData->txLastBuffer);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_FTX.pageValue);

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + FP_FREE_Q_HEAD),
      qHead);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      BRIDGE_FORWARD);

   driverData->txStartTime = CMSMGetCurrentTime();
   CTokenTSMFastSendComplete (driverData, tcb, 0);

#ifdef OUT_CHAR
   CMSMOutMEON ('f', ATTRIB);
#endif /* OUT_CHAR */

   return;
}

/**************************************************************************\
**
** PROC NAME:     DriverSendBridge
**
**                This routine will called when the driver wants to
**                send a packet out onto the media.
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

#ifdef BROUTER

void
DriverSendBridge (
            DRIVER_DATA       *driverData,
            MLID_ConfigTable  *configTable,
            TCB               *tcb,
            UINT32            pktSize,
            TCB               *physTcb)
{
   FRAGMENTSTRUCT       *fragPtr;

   void     *txBuffer;
   void     *BTBBase;
   void     *MMIO;
   void     *copySource;

   UINT32   copyBytes;
   UINT32   fragCount;
   UINT32   tempBuffer;

   UINT16   qHead;

   UINT8    count;

   pktSize = pktSize;
   physTcb = physTcb;


#ifdef OUT_CHAR
   CMSMOutMEON ('B', ATTRIB);
#endif /* OUT_CHAR */

   MMIO = driverData->absoluteMMIOAddress;

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_FTX.pageValue);

   /***********************************************************************\
   **   check if bridge is open
   \***********************************************************************/

   if (!driverData->ivt_FTX.baseAddress)
   {
      driverData->txStartTime = 0;
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      CTokenTSMFastSendComplete (driverData, tcb, 1);
      return;
   }

   tempBuffer = (UINT32) Rd16 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + BTCA_NEXT_BUFFER));

   if (!tempBuffer)
   {
      driverData->txStartTime = 0;
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      CTokenTSMFastSendComplete (driverData, tcb, 1);
      return;
   }

   /***********************************************************************\
   **   get first transmit buffer
   \***********************************************************************/

   driverData->txLastBuffer = tempBuffer;

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      (UINT8) tempBuffer);

   BTBBase = (void *) ((UINT32) driverData->sharedRAMRelative
      + (UINT32)VALUE_TO_HILO_UINT16(
         (UINT16)(tempBuffer & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

   /***********************************************************************\
   **   fill out necessary information
   \***********************************************************************/

   Wrt16 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_FRAME_LENGTH),
      VALUE_TO_HILO_UINT16((UINT16)tcb->TCB_DataLen));

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_XMIT_CONTROL),
      0);

   driverData->txBufferSpace   = OPEN_RX_LENGTH - 8;
   driverData->txCurrentBuffer = BTBBase;

   /***********************************************************************\
   **   copy TCB header to first buffer
   \***********************************************************************/

   driverData->txBufferSpace -= tcb->TCB_MediaHeaderLen;
   txBuffer = (void *)((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_FRAME_DATA);

   MovFastToBus (
      driverData->busTag,
      NULL,
      txBuffer,
      &tcb->TCB_MediaHeader,
      tcb->TCB_MediaHeaderLen);

   driverData->TxBuffersUsed = 1;
   txBuffer = (void *) ((UINT8 *) txBuffer + tcb->TCB_MediaHeaderLen);

   /***********************************************************************\
   **   copy the rest of the packet
   \***********************************************************************/

   fragPtr    = &tcb->TCB_FragBlockPtr->TCB_Fragment;
   fragCount  = tcb->TCB_FragBlockPtr->TCB_FragmentCount;

   while (fragCount)
   {
      copyBytes  = fragPtr->FragmentLength;
      copySource = fragPtr->FragmentAddress;

      while (copyBytes > driverData->txBufferSpace)
      {
         /**************************************************************\
         **   frag WON'T fit in tx buff, so fill in rest & get new buff
         \**************************************************************/

         copyBytes -= driverData->txBufferSpace;

         MovFastToBus (
            driverData->busTag,
            NULL,
            txBuffer,
            copySource,
            driverData->txBufferSpace);

         Wrt16 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *)((UINT8 *)BTBBase - BTB_BUFFER_POINTER + BTB_BUFFER_LENGTH),
            VALUE_TO_HILO_UINT16((OPEN_RX_LENGTH - 8)));

         Wrt8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *)((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_XMIT_CONTROL),
            0);

         driverData->txLastBuffer = Rd16 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *)((UINT8 *)BTBBase - BTB_BUFFER_POINTER
               + BTB_BUFFER_POINTER));

         Wrt8 (
            configTable->MLIDCFG_DBusTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            (UINT8) driverData->txLastBuffer);

         driverData->txCurrentBuffer = (void *) Rd32 (
            driverData->busTag,
            NULL,
            (void *) ((UINT32) driverData->sharedRAMRelative
               + (UINT32)VALUE_TO_HILO_UINT16( (UINT16)(driverData->txLastBuffer
                  & ((UINT32)driverData->pageSizeMask | 0xffffff00)))));

         txBuffer   = (void *) ((UINT8 *) driverData->txCurrentBuffer
            - BTB_BUFFER_POINTER + BTB_FRAME_DATA);
         copySource = (void *) ((UINT8 *) copySource + driverData->txBufferSpace);
         driverData->txBufferSpace = OPEN_RX_LENGTH - 8;
      }

      driverData->txBufferSpace -= copyBytes;

      MovFastToBus (
         driverData->busTag,
         NULL,
         txBuffer,
         copySource,
         copyBytes);

      txBuffer = (void *) ((UINT8 *) txBuffer + copyBytes);
      fragPtr++;
      fragCount--;
   }

   Wrt16 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_BUFFER_LENGTH),
      VALUE_TO_HILO_UINT16((UINT16)(OPEN_RX_LENGTH - 8 - driverData->txBufferSpace)));

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_XMIT_CONTROL),
      1);

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_FTX.pageValue);

   count = Rd8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + BTCA_INPUT_COUNT));

   count += driverData->TxBuffersUsed;

   qHead = Rd16 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) BTBBase - BTB_BUFFER_POINTER + BTB_BUFFER_POINTER));

   Wrt16 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + BTCA_NEXT_BUFFER),
      qHead);

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + BTCA_INPUT_COUNT),
      count);

   Wrt8 (
      configTable->MLIDCFG_DBusTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      BRIDGE_FORWARD);

   driverData->txStartTime = CMSMGetCurrentTime();
   CTokenTSMFastSendComplete (driverData, tcb, 0);

#ifdef OUT_CHAR
   CMSMOutMEON ('b', ATTRIB);
#endif /* OUT_CHAR */

   return;
}

#endif /* BROUTER */

/**************************************************************************\
**
** PROC NAME:     CFixUpStatStrings
**
**                This routine will called to insert the description
**                strings for each counter.
**
** Parameters:    IN    DRIVER_DATA *ads
**
**                ads   -  Pointer to HSM's AdapterDataSPace
**
** Return Value:  NONE
**
** See Also:
**
\**************************************************************************/

void
CFixUpStatStrings (DRIVER_DATA *driverData)
{
   driverData->BadCorrelatorTable.StatString       = (MEON_STRING *) CNTR2000_BADCORR_STR;
   driverData->UnknownARBTable.StatString          = (MEON_STRING *) CNTR2000_UNKNOWNARB_STR;
   driverData->QDepthEqualTwoTable.StatString      = (MEON_STRING *) CNTR2000_QDEPTHRESET_STR;
   driverData->CardIsDeadTable.StatString          = (MEON_STRING *) CNTR2000_CARDISDEAD_STR;
   driverData->TxFreeCountZeroTable.StatString     = (MEON_STRING *) CNTR2000_TXFREECOUNT_STR;
   driverData->TxFreeCountZeroAndResetTable.StatString  = (MEON_STRING *) CNTR2000_TXFREECOUNTRESET_STR;
}

/**************************************************************************\
**
** PROC NAME:     DriverCallBack
**
**                This routine will ...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DriverCallBack (
            DRIVER_DATA    *driverData,
            CONFIG_TABLE   *configTable)
{
   configTable = configTable;

#ifdef OUT_CHAR
   CMSMOutMEON ('p', ATTRIB);
#endif /* OUT_CHAR */

   if (driverData->inDriverReset || driverData->OpeningAdapter)
   {
#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

      driverData->txStartTime = 0;      /* Set Tx no longer active   */
      return;
   }

   if (driverData->MLIDStatusFlag & RE_INIT_ADAPTER_BIT)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('2', ATTRIB);
#endif /* OUT_CHAR */

      driverData->CardIsDead++;
      DriverReset (driverData, configTable, OP_SCOPE_ADAPTER);
      driverData->txStartTime = 0;      /* Set Tx no longer active   */
      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

   if (driverData->txStartTime)         /* Transmit active ?         */
   {                                    /* Yes, check for timeout   */
      if ((CMSMGetCurrentTime() - driverData->txStartTime) > 90)
      {

#ifdef OUT_CHAR
   CMSMOutMEON ('3', ATTRIB);
#endif /* OUT_CHAR */

         driverData->TxFreeCountZeroAndReset++;
         driverData->CardIsDead++;
           DriverReset (driverData, configTable, OP_SCOPE_ADAPTER);
         driverData->txStartTime = 0;      /* Set Tx no longer active   */
           CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
         return;
      }
   }
   else                                 /* No transmit active,       */
   {                                    /*  check QDepth            */
      if (driverData->QDepth)
      {
#ifdef OUT_CHAR
   CMSMOutMEON ('4', ATTRIB);
#endif /* OUT_CHAR */

         if (driverData->QDepth == 2)
            driverData->QDepthEqualTwo++;

         if (DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount == 0)
            driverData->TxFreeCountZero++;

         driverData->txStartTime = CMSMGetCurrentTime();
      }
   }

   driverData->MLIDStatusFlag  |= DIR_READ_LOG_BIT;
   driverData->CheckAlertTimer--;

   if (driverData->CheckAlertTimer)
   {
#ifdef OUT_CHAR
   CMSMOutMEON ('5', ATTRIB);
#endif /* OUT_CHAR */

      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

   if (!driverData->LastErrorMessage)
   {
#ifdef OUT_CHAR
   CMSMOutMEON ('6', ATTRIB);
#endif /* OUT_CHAR */

      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

   driverData->LastErrorMessage = 0;
   UpdateAlertStats (driverData->absoluteMMIOAddress, driverData);
   CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
   return;
}

/**************************************************************************\
**
** PROC NAME:     DriverISR
**
**                This routine will ...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DriverISR (DRIVER_DATA *driverData)
{
   tINTVector  *vector;
   void        *MMIO;
   UINT8       OldRAMPageRegister;
   UINT16      intMask;

#ifdef OUT_CHAR
   CMSMOutMEON ('I', ATTRIB);
#endif /* OUT_CHAR */

   MMIO    = driverData->absoluteMMIOAddress;
   intMask = Rd16 (driverData->busTag, NULL,
      (void *)((UINT8 *)MMIO + INT_STATUS_TO_PC));

   /***********************************************************************\
   **   we need to find the interrupt reason, the following compare
   **   sequence has been optimized to provide the best performance
   \***********************************************************************/

   if (intMask & ADAPTER_ERROR_BIT)
      vector = &driverData->ivt_AER;
   else if (intMask & (ADAPTER_CHECK_BIT  << 8))
      vector = &driverData->ivt_ACK;
   else if (intMask & (ASB_FREE_BIT       << 8))
      vector = &driverData->ivt_ASB;
   else if (intMask & (SRB_RESPONSE_BIT   << 8))
      vector = &driverData->ivt_SRB;
   else if (intMask & (BRIDGE_FORWARD_BIT << 8))
      vector = &driverData->ivt_FTX;
   else if (intMask & (ARB_COMMAND_BIT    << 8))
      vector = &driverData->ivt_ARB;
   else if (intMask & (SSB_RESPONSE_BIT   << 8))
      vector = &driverData->ivt_SSB;
   else
      vector = &driverData->ivt_RET;

   /***********************************************************************\
   **   interrupt reason FOUND, so disable interrupt and do EOI
   \***********************************************************************/

   /* Done in DriverDisableInterrupt for NT compatability   */

   driverData->MLIDStatusFlag |= NIC_INTERRUPTED_BIT;

   intMask  = ~(vector->mask);

   intMask &= ~((UINT16)(INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT));

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
      intMask);

   /***********************************************************************\
   **    check if we should even look at this interrupt...
   \***********************************************************************/

   if (!(driverData->MLIDStatusFlag & IGNORE_INTERRUPT_BIT))
   {
      OldRAMPageRegister = Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG));

      /********************************************************************\
      **    if page provided, use it
      \********************************************************************/

      if (!vector->pageNotProvided)
      {
         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            vector->pageValue);
      }

      /********************************************************************\
      **    call interrupt vector
      \********************************************************************/

#ifdef BROUTER
      driverData->SRAFlag = 0;
#endif /* BROUTER */

      (*vector->routine) (MMIO, vector->baseAddress, driverData);

      /********************************************************************\
      **    restore old RAM Page register value
      \********************************************************************/

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         OldRAMPageRegister);
   }

#ifdef OUT_CHAR
   else
   {
      CMSMOutMEON ('#', ATTRIB);
   }
#endif /* OUT_CHAR */


   /***********************************************************************\
   **    an OUT to this port will issue a global interrupt enable
   \***********************************************************************/

   Out8 (driverData->busTag, (void *) driverData->interruptResetLevel, 0);

#ifndef USE_FAST_CALLS
   CMSMServiceEvents ();
#endif /* USE_FAST_CALLS */

#ifdef OUT_CHAR
   CMSMOutMEON ('i', ATTRIB);
#endif /* OUT_CHAR */

   return;
}

/**************************************************************************\
**
** PROC NAME:     DriverDisableInterrupt
**
**                This routine will ...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

BOOLEAN
DriverDisableInterrupt (DRIVER_DATA *driverData, BOOLEAN switchVal)
{
   void     *MMIO;
   UINT16   intMask;

#ifdef OUT_CHAR
   CMSMOutMEON ('{', ATTRIB);
#endif /* OUT_CHAR */

   switchVal = switchVal;
   MMIO    = driverData->absoluteMMIOAddress;
   intMask = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC));

   if (driverData->MLIDStatusFlag & ADAPTER_RESET_BIT)
      return (FALSE);

   if (intMask & (0xff00 | PARITY_ERROR_BIT | TIMER_EXPIRED_BIT
         | RAM_VIOLATION_BIT | ADAPTER_ERROR_BIT))
   {
      Wrt16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
         ~(INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT));

      if (driverData->inDriverReset)
      {
         driverData->MLIDStatusFlag |= NIC_INTERRUPTED_BIT;
         Out8 (driverData->busTag, (void *)driverData->interruptResetLevel, (UINT8)intMask);
      }

      return (TRUE);
   }

   Wrt16 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + AND_OFFSET),
      ~(INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT));

   return (FALSE);
}

/**************************************************************************\
**
** PROC NAME:     DriverEnableInterrupt
**
**                This routine will ...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DriverEnableInterrupt (DRIVER_DATA *driverData)
{

   void     *MMIO;

#ifdef OUT_CHAR
   CMSMOutMEON ('}', ATTRIB);
#endif /* OUT_CHAR */


   MMIO    = driverData->absoluteMMIOAddress;

/*18-Sep-97 JCJ SPD# 163281 */
/*   if ((DADSP_TO_CMSMADSP (driverData)->CMSMStatusFlags & SHUTDOWN) ||
       (driverData->MLIDStatusFlag & ADAPTER_RESET_BIT) )
      return;
*/
   Wrt16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC + OR_OFFSET),
         INTERRUPT_ENABLE_BIT | NMI_DISABLED_BIT);
}


/**************************************************************************\
**
** PROC NAME:     IV_AdapterError
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_AdapterError (void *MMIOBase, void *SRAMBase, DRIVER_DATA *driverData)
{
   UINT16   value;
   void     *address;

   SRAMBase = SRAMBase;

#ifdef OUT_CHAR
   CMSMOutMEON ('e', ATTRIB);
#endif /* OUT_CHAR */

   if (WaitForEvent (
         driverData,
         driverData->busTag,
         ADAPTER_CHECK_TIMEOUT,
         (ADAPTER_CHECK_BIT << 8),
         0,
         (void *) ((UINT8 *) MMIOBase + INT_STATUS_TO_PC)))
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

      value = Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) MMIOBase + WRITE_WINDOW_CLOSE_REG));

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIOBase + RAM_PAGE_REG),
         (UINT8) value);

      address = (void *) Rd32 (
         driverData->busTag,
         NULL,
         (void *) ((UINT32) driverData->sharedRAMRelative
            + VALUE_TO_HILO_UINT16(
               (value & ((UINT16)driverData->pageSizeMask | 0xff00)))));

      /********************************************************************\
      **    convert dword to intel format if needed
      \********************************************************************/

      address = (void *)VALUE_TO_HILO_UINT32((UINT32)address);
   }
   else
      address = (void *) 0x8000;

   driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;

   UpdateAlertStats (MMIOBase, driverData);
}


/**************************************************************************\
**
** PROC NAME:     IV_AdapterCheck
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_AdapterCheck (void *MMIOBase, void *SRAMBase, DRIVER_DATA *driverData)
{
   UINT16   value;
   void     *address;

#ifdef OUT_CHAR
   CMSMOutMEON ('c', ATTRIB);
#endif /* OUT_CHAR */

   SRAMBase = SRAMBase;
   value    = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) MMIOBase + WRITE_WINDOW_CLOSE_REG));

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIOBase + RAM_PAGE_REG),
      (UINT8) value);

   address = (void *) Rd32 (
      driverData->busTag,
      NULL,
      (void *) ((UINT32) driverData->sharedRAMRelative
         + VALUE_TO_HILO_UINT16(
            (value & ((UINT16)driverData->pageSizeMask | 0xff00)))));

   /********************************************************************\
   **    convert dword to intel format
   \********************************************************************/

   address = (void *)VALUE_TO_HILO_UINT32((UINT32)address);

   driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;


   UpdateAlertStats (MMIOBase, driverData);
}


/**************************************************************************\
**
** PROC NAME:     IV_ARBRequest
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_ARBRequest (void *MMIO, void *SRAMBase, DRIVER_DATA *driverData)
{
   UINT8    value;

   /***********************************************************************\
   **    save the ARB area
   \***********************************************************************/

#ifdef OUT_CHAR
   CMSMOutMEON ('a', ATTRIB);
#endif /* OUT_CHAR */

/* 18-Sep-97 JCJ SPD# 163281 */
    if (DADSP_TO_CMSMADSP (driverData)->CMSMStatusFlags & SHUTDOWN)
    {
        return;
    }

   value = (Rd8 (driverData->busTag, NULL,
      SRAMBase) & 0x3f);   

   MovFromBus32 (
      driverData->ARBSaveArea,
      driverData->busTag,
      NULL,
      SRAMBase,
      ARB_SIZE / 4);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      ARB_FREE);

   driverData->ARBSaveArea [ASB_RETURN_CODE]  = 0;
   driverData->ARBSaveArea [ASB_COMMAND_CODE] = ARB_RECEIVED_DATA;

#ifdef BROUTER

   if (value > 5)
   {
      ARB_JMP_InvalidARBEntry (MMIO, driverData);
      return;
   }

#else

   if (value >= 5)
   {
      ARB_JMP_InvalidARBEntry (MMIO, driverData);
      return;
   }

#endif /* BROUTER */

   if (!value)
   {
      ARB_JMP_InvalidARBEntry (MMIO, driverData);
      return;
   }

   (ARBJumpTable [value - 1]) (MMIO, driverData);
}

#ifdef BROUTER


/**************************************************************************\
**
** PROC NAME:     ARB_JMP_BReceiveDataRoutine
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_BReceiveDataRoutine (void *MMIO, DRIVER_DATA *driverData)
{
   driverData->SRAFlag = 1;
   ARB_JMP_ReceiveDataRoutine (MMIO, driverData);
   driverData->SRAFlag = 0;
}
#endif /* BROUTER */


/**************************************************************************\
**
** PROC NAME:     ARB_JMP_ReceiveDataRoutine
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_ReceiveDataRoutine (void *MMIO, DRIVER_DATA *driverData)
{
   FRAGMENTSTRUCT *fragPtr;
   RCB            *rcb;
   UINT8            *rxBuffer;
   void           *rxDFragment;
   UINT8            *firstRxBuffer;

   UINT32   rcbSize;
   UINT32   rxBufferSize;
   UINT32   startByte;
   UINT32   numBytes;
   UINT32   rcvStatus = 0;
   UINT32   pktSize;
   UINT32   fragCount;

   UINT16   currentBuffer;

#ifdef OUT_CHAR
   CMSMOutMEON ('R', ATTRIB);
#endif /* OUT_CHAR */

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ARBSaveArea [ARB_RX_FIRST_BUFFER]);

   rxBuffer = (UINT8 *)(GET_HILO_UINT16(&driverData->ARBSaveArea[ARB_RX_FIRST_BUFFER])
       & (((driverData->pageSizeMask) << 8) | 0xff));

   rxBuffer = (UINT8 *)driverData->sharedRAMRelative + (UINT32)rxBuffer;

   firstRxBuffer = rxBuffer + 2;

   rxBuffer += RCB_FRAME_DATA + 2;

   pktSize = (UINT32)(GET_HILO_UINT16(&driverData->ARBSaveArea[ARB_RX_FRAME_LENGTH]));

#ifdef BROUTER

   if (!driverData->brouterState)
   {
      /********************************************************************\
      **    if it came in from SRA, subtract CRC length
      \********************************************************************/

      if (driverData->SRAFlag)
         pktSize -= 4;

      /********************************************************************\
      **    didn't come in from SRA, discard if its an explorer
      \********************************************************************/

      else if (Rd8 (driverData->busTag, NULL,
            (void *) (rxBuffer + TX_SOURCE_NODE_ADDRESS)) & 0x80)
      {
         if (Rd8 (
            driverData->busTag,
            NULL,
            (void *) (rxBuffer + TX_ROUTING_INFO)) & 0x80)
         {
            ARB_JMP_SUB_ReturnASBResponse (MMIO, driverData);
            return;
         }
      }
   }

#endif /* BROUTER */

   /***********************************************************************\
   **    get an RCB
   \***********************************************************************/

   rcb = CTokenTSMGetRCB (
      driverData,
      rxBuffer,
      pktSize,
      rcvStatus,
      &startByte,
      &numBytes);

   if (!rcb)
   {

#ifdef OUT_CHAR
//   CMSMOutMEON ('-', ATTRIB);
#endif /* OUT_CHAR */

      driverData->ARBSaveArea [ASB_RETURN_CODE] = SRB_NO_BUFFERS;
      ARB_JMP_SUB_ReturnASBResponse (MMIO, driverData);
      return;
   }

   driverData->ARBSaveArea [ASB_RETURN_CODE] = 0;

   /***********************************************************************\
   **    ARB 0x81:   Move the first buffer into the ECB
   \***********************************************************************/

   pktSize   = numBytes;
   fragCount = rcb->RCBFragCount;
   fragPtr   = &rcb->RCBFragStruct;


   rxBufferSize = (UINT32) Rd16 (
      driverData->busTag,
      NULL,
      firstRxBuffer + RCB_BUFFER_LENGTH);

   rxBufferSize= (UINT32)VALUE_TO_HILO_UINT16((UINT16)rxBufferSize) - startByte;
   rcbSize     = fragPtr->FragmentLength;
   rxBuffer    = firstRxBuffer + startByte + RCB_FRAME_DATA;

   if (rcbSize > rxBufferSize)
   {
      rxDFragment = fragPtr->FragmentAddress;
      goto RDR_RCBFragmentTooBig;
   }

   rxBufferSize -= rcbSize;

   if (rcbSize > pktSize)
   {
      rxDFragment = fragPtr->FragmentAddress;
      goto RDR_ReadNextFragOverrun;
   }

   pktSize -= rcbSize;

   MovFastFromBus (
      fragPtr->FragmentAddress,
      driverData->busTag,
      NULL,
      rxBuffer,
      rcbSize);

   rxBuffer += rcbSize;
   fragPtr++;
   fragCount--;

   if (fragCount)
      goto RDR_RxGetNextFragment;

RDR_ReturnRCBToMSM:

#ifdef USE_FAST_CALLS
   CTokenTSMFastRcvComplete (driverData, rcb);
#else
   CTokenTSMRcvComplete (driverData, rcb);
#endif /* USE_FAST_CALLS */

#ifdef OUT_CHAR
//   CMSMOutMEON ('r', ATTRIB);
#endif /* OUT_CHAR */

   ARB_JMP_SUB_ReturnASBResponse (MMIO, driverData);
   return;

/**************************************************************************\
**    ARB 0x81:   This is where all the odd-ball spaghetti code goes
**                for cases where the receive packet doesn't fit nicely
**                into a single fragmented RCB.
\**************************************************************************/

RDR_RxGetNextFragment:

#ifdef OUT_CHAR
//   CMSMOutMEON ('f', ATTRIB);
#endif /* OUT_CHAR */

   while (fragCount)
   {
      rxDFragment = fragPtr->FragmentAddress;
      rcbSize     = fragPtr->FragmentLength;

      if (rxBufferSize)
         goto RDR_RxNextCopy;

RDR_RxGetNextRxBuffer:

#ifdef OUT_CHAR
//   CMSMOutMEON ('n', ATTRIB);
#endif /* OUT_CHAR */

      currentBuffer = (UINT32) Rd16 (
         driverData->busTag,
         NULL,
         firstRxBuffer + RCB_NEXT_BUFFER);

      if (!currentBuffer)
         goto RDR_ReturnRCBToMSM;


      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         (UINT8) currentBuffer);

      firstRxBuffer = ((UINT8 *) driverData->sharedRAMRelative
         + (UINT32)VALUE_TO_HILO_UINT16( (UINT16)(currentBuffer
            & ((UINT16)driverData->pageSizeMask | 0xff00))));

      rxBufferSize = (UINT32) Rd16 (
         driverData->busTag,
         NULL,
         firstRxBuffer + RCB_BUFFER_LENGTH);

      rxBufferSize  = (UINT32)VALUE_TO_HILO_UINT16((UINT16)rxBufferSize);
      rxBuffer      = firstRxBuffer + RCB_FRAME_DATA;

RDR_RxNextCopy:

#ifdef OUT_CHAR
//   CMSMOutMEON ('c', ATTRIB);
#endif /* OUT_CHAR */

      if (rcbSize > rxBufferSize)
         goto RDR_RCBFragmentTooBig;

      rxBufferSize -= rcbSize;

      if (rcbSize > pktSize)
         goto RDR_ReadNextFragOverrun;

      MovFastFromBus (
         rxDFragment,
         driverData->busTag,
         NULL,
         rxBuffer,
         rcbSize);

      rxBuffer += rcbSize;
      fragPtr++;
      fragCount--;
   }

   goto RDR_ReturnRCBToMSM;

/**************************************************************************\
**    ARB 0x81:   copy remaining bytes, then we're finished!
\**************************************************************************/

RDR_ReadNextFragOverrun:

#ifdef OUT_CHAR
//   CMSMOutMEON ('o', ATTRIB);
#endif /* OUT_CHAR */

   MovFastFromBus (
      rxDFragment,
      driverData->busTag,
      NULL,
      rxBuffer,
      rxBufferSize);
   rxBuffer += rxBufferSize;

   goto RDR_ReturnRCBToMSM;

/**************************************************************************\
**    ARB 0x81:   ECB Fragment > than Rx Buffer, copy using rx buffer size.
\**************************************************************************/

RDR_RCBFragmentTooBig:

#ifdef OUT_CHAR
//   CMSMOutMEON ('b', ATTRIB);
#endif /* OUT_CHAR */

   rcbSize -= rxBufferSize;

   if (rxBufferSize > pktSize)
      goto RDR_ReadNextFragOverrun;

   pktSize -= rxBufferSize;

   MovFastFromBus (
      rxDFragment,
      driverData->busTag,
      NULL,
      rxBuffer,
      rxBufferSize);

   rxBuffer += rxBufferSize;
   rxDFragment = (void *) ((UINT8 *) rxDFragment + rxBufferSize);
   goto RDR_RxGetNextRxBuffer;
}


/**************************************************************************\
**
** PROC NAME:     ARB_JMP_TransmitDataRequest
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_TransmitDataRequest (void *MMIOBase, DRIVER_DATA *driverData)
{
   FRAGMENTSTRUCT       *fragPtr;

   TCB      *prevTCB;
   TCB      *nextTCB;

   void     *MMIO;
   void     *txBuffer;
   UINT16   *temp;

   UINT32   fragCount;
   UINT16   page;

   /***********************************************************************\
   **    ARB 0x82:  first see if we can set another SRB
   \***********************************************************************/

#ifdef OUT_CHAR
   CMSMOutMEON ('X', ATTRIB);
#endif /* OUT_CHAR */

   driverData->MLIDStatusFlag &= ~TX_IN_PROCESS_BIT;
   CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);

   /***********************************************************************\
   **    ARB 0x82:  search for TCB with matching correlator
   \***********************************************************************/

/* check this next instruction very carefully..................... */

   nextTCB = (TCB *)( (UINT32)&driverData->txInProcessHead
                  - (UINT32)&((TCB*)0)->TCB_DriverWS[TCB_LINK] );

   do
   {
      prevTCB = nextTCB;
      nextTCB = (TCB *) prevTCB->TCB_DriverWS [TCB_LINK];

      /********************************************************************\
      **    check for invalid ARB
      \********************************************************************/

      if (!nextTCB)
      {
#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

         driverData->BadCorrelator++;
         ARB_JMP_SUB_ReturnASBResponse (MMIOBase, driverData);
         return;
      }
   }
   while (driverData->ARBSaveArea [ARB_TX_CORRELATOR]
      != (UINT8) nextTCB->TCB_DriverWS [TCB_CORRELATOR]);

   /***********************************************************************\
   **    ARB 0x82:  unlink from txInProcessHead Queue
   \***********************************************************************/

   driverData->ARBSaveArea [ASB_COMMAND_CODE] = SRB_TX_DIR_FRAME;
   prevTCB->TCB_DriverWS [TCB_LINK]     = nextTCB->TCB_DriverWS [TCB_LINK];

   /***********************************************************************\
   **    ARB 0x82:  prepare to move the data
   \***********************************************************************/

   MMIO = driverData->absoluteMMIOAddress;

/* 950609 MCD */
   page = GET_HILO_UINT16(&driverData->ARBSaveArea [ARB_TX_DHB_ADDRESS]);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      (UINT8)(page >> 8));

   txBuffer = (void *)((UINT32) driverData->sharedRAMRelative
      + (page & ((driverData->pageSizeMask << 8) | 0xFF)));

   /***********************************************************************\
   **    ARB 0x82:  move the header into the shared RAM tx buffer
   \***********************************************************************/


   if (driverData->pageSizeMask != 0xff)
      MoveDataToPagedBuffers (
         &txBuffer,
         &nextTCB->TCB_MediaHeader,
         nextTCB->TCB_MediaHeaderLen,
         driverData);
   else
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('2', ATTRIB);
#endif /* OUT_CHAR */

      MovFastToBus (
         driverData->busTag,
         NULL,
         txBuffer,
         &nextTCB->TCB_MediaHeader,
         nextTCB->TCB_MediaHeaderLen);

         txBuffer = (void *) ((UINT8 *) txBuffer + nextTCB->TCB_MediaHeaderLen);
   }

   /***********************************************************************\
   **    ARB 0x82:  move fragments
   \***********************************************************************/

   fragCount = nextTCB->TCB_FragBlockPtr->TCB_FragmentCount;
   fragPtr   = &nextTCB->TCB_FragBlockPtr->TCB_Fragment;

   while (fragCount)
   {

      if (driverData->pageSizeMask != 0xff)
         MoveDataToPagedBuffers (
            &txBuffer,
            fragPtr->FragmentAddress,
            fragPtr->FragmentLength,
            driverData);

      else
      {

#ifdef OUT_CHAR
   CMSMOutMEON ('3', ATTRIB);
#endif /* OUT_CHAR */

         MovFastToBus (
            driverData->busTag,
            NULL,
            txBuffer,
            fragPtr->FragmentAddress,
            fragPtr->FragmentLength);

         txBuffer = (void *) ((UINT8 *) txBuffer + fragPtr->FragmentLength);
      }

      fragPtr++;
      fragCount--;
   }

   /***********************************************************************\
   **    ARB 0x82:  everything done
   \***********************************************************************/

   temp = (UINT16 *)&driverData->ARBSaveArea [ASB_FRAME_LENGTH];
   *temp  = GET_HILO_UINT16(&nextTCB->TCB_DataLen);

   driverData->txStartTime = CMSMGetCurrentTime();

#ifdef USE_FAST_CALLS
   CTokenTSMFastSendComplete (driverData, nextTCB, 0);
#else
   CTokenTSMSendComplete (driverData, nextTCB, 0);
#endif /* USE_FAST_CALLS */

   DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
   driverData->txStartTime = 0;
   ARB_JMP_SUB_ReturnASBResponse (driverData->absoluteMMIOAddress, driverData);

#ifdef OUT_CHAR
   CMSMOutMEON ('x', ATTRIB);
#endif /* OUT_CHAR */
}


/**************************************************************************\
**
** PROC NAME:     MoveDataToPagedByffers
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* 950608 MCD Changed dest and its references from (void *) to (void **). */

void
MoveDataToPagedBuffers (void **dest, void *source, UINT32 length,
   DRIVER_DATA *driverData)
{
   UINT32   nonPageBytes;

#ifdef OUT_CHAR
   CMSMOutMEON ('m', ATTRIB);
#endif /* OUT_CHAR */

   do
   {
      /********************************************************************\
      **    paging is active, check for page overflow...
      \********************************************************************/

      if (driverData->pagingMask & (UINT8)(((UINT32) *dest + (UINT32) length
         - (UINT32) driverData->sharedRAMRelative) >> 8))
      {
         nonPageBytes = (UINT32) *dest - (UINT32) driverData->sharedRAMRelative;

         MovFastToBus (
            driverData->busTag,
            NULL,
            *dest,
            source,
            driverData->pageSize - nonPageBytes);


         /*****************************************************************\
         **    adjust destination and length to fill next page.
         \*****************************************************************/

         *dest   = (void *) ((UINT8 *) *dest - nonPageBytes);
         length = length - (driverData->pageSize - nonPageBytes);
      }

      else
      {

         MovFastToBus (
            driverData->busTag,
            NULL,
            *dest,
            source,
            length);

         *dest = (void *) ((UINT8 *) *dest + length);
         return;
      }
   }
   while (length);
}



/**************************************************************************\
**
** PROC NAME:     ARB_JMP_InvalidARBEntry
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_InvalidARBEntry (void *MMIOBase, DRIVER_DATA *driverData)
{
#ifdef OUT_CHAR
   CMSMOutMEON ('v', ATTRIB);
#endif /* OUT_CHAR */

   driverData->UnknownARB++;
   ARB_JMP_SUB_ReturnASBResponse (MMIOBase, driverData);
}



/**************************************************************************\
**
** PROC NAME:     ARB_JMP_RingStatusRoutine
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_RingStatusRoutine (void *MMIOBase, DRIVER_DATA *driverData)
{
   UINT16      beaconType;
   UINT16      oldPage;
   MEON_STRING *alertMSG;
   CONFIG_TABLE   *configTable;

#ifdef OUT_CHAR
   CMSMOutMEON ('G', ATTRIB);
#endif /* OUT_CHAR */

   configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
   driverData->LastRingStatus  = (UINT32) GET_HILO_UINT16(&driverData->ARBSaveArea [RING_NEW_STATUS0]);

   /***********************************************************************\
   **    check to generate RING alert
   \***********************************************************************/

   if (driverData->ARBSaveArea [RING_NEW_STATUS0] &
      (RING_HARD_ERROR | RING_TX_BEACON | RING_LOBE_WIRE_FAULT
         | RING_AUTO_REMOVE | RING_REMOVE_RECEIVED))
   {
      if (driverData->ARBSaveArea [RING_NEW_STATUS0] & RING_LOBE_WIRE_FAULT)
      {
         alertMSG = CNTR2000_IMDISCONN1_MSG;
         driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
      }

      else if (driverData->ARBSaveArea [RING_NEW_STATUS0] & RING_REMOVE_RECEIVED)
      {
         alertMSG = CNTR2000_IMZAPPED1_MSG;
         driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
      }

      else if (driverData->ARBSaveArea [RING_NEW_STATUS0] & RING_AUTO_REMOVE)
      {
         alertMSG = CNTR2000_IMREMOVED_MSG;
         driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
      }

      else if (driverData->ARBSaveArea [RING_NEW_STATUS0] & RING_TX_BEACON)
      {
         alertMSG = CNTR2000_IMBEACONING_MSG;
      }

      else if ((UINT8) driverData->LastRingStatus &  RING_RECOVERY / 256)
      {
         alertMSG = CNTR2000_IMBEACONING_MSG;

         oldPage  = Rd8 (driverData->busTag, NULL,
            (void *) ((UINT8 *) MMIOBase + RAM_PAGE_REG));

         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIOBase + RAM_PAGE_REG),
            driverData->adapterParmsPageValue);

         beaconType = Rd16 (driverData->busTag, NULL,
            (void *)((UINT8 *) driverData->adapterParmsAddr + PARMS_BEACON_TRANSMIT));

         if (beaconType == 0x0200)
            driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;

/* the old driver doesn't actually reset this but I think it should be done???!!???!!?? */

         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIOBase + RAM_PAGE_REG),
            oldPage);
      }

      else
      {
         alertMSG = CNTR2000_IMDISCONN2_MSG;
         driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
      }

      if (driverData->LastErrorMessage == alertMSG)
         return;

      driverData->LastErrorMessage = alertMSG;
      driverData->CheckAlertTimer  = 8;

      UpdateAlertStats (MMIOBase, driverData);
      CMSMPrintString (configTable, MSG_TYPE_RUNTIME_WARNING, alertMSG, 0, 0); 
      return;
   }

   /***********************************************************************\
   **    check if single station status
   \***********************************************************************/

   if ((UINT8) driverData->LastRingStatus &  RING_SINGLE_STATION / 256)
      return;

   /***********************************************************************\
   **    check if previous alert has been cleared
   \***********************************************************************/

   if (!driverData->LastErrorMessage)
      return;

   /***********************************************************************\
   **    update stats and post alert
   \***********************************************************************/

   alertMSG = CNTR2000_ALERT_CORRECT_MSG;
   driverData->LastErrorMessage = 0;
   UpdateAlertStats (driverData->absoluteMMIOAddress, driverData);
   CMSMPrintString (configTable, MSG_TYPE_RUNTIME_WARNING, alertMSG, 0, 0); 
}



/**************************************************************************\
**
** PROC NAME:     ARB_JMP_SUB_ReturnASBResponse
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
ARB_JMP_SUB_ReturnASBResponse (void *MMIO, DRIVER_DATA *driverData)
{
   void     *asbBase;
   UINT16   status;
   UINT8    rcode;

#ifdef OUT_CHAR
   CMSMOutMEON ('P', ATTRIB);
#endif /* OUT_CHAR */

   do
   {
      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         driverData->ivt_ASB.pageValue);

      asbBase = driverData->ivt_ASB.baseAddress;
      status  = Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_PC));

      if (status & ((ADAPTER_CHECK_BIT << 8) | (ADAPTER_ERROR_BIT)))
         return;

      rcode = Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) asbBase + ASB_RETURN_CODE));

   }
   while (rcode != SRB_IN_PROCESS);

   MovToBus32 (
      driverData->busTag,
      NULL,
      asbBase,
      driverData->ARBSaveArea,
      3);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      RESPONSE_IN_ASB);
}



/**************************************************************************\
**
** PROC NAME:     IV_ARBReturn
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_ARBReturn (void *MMIOBase, void *SRAMBase, DRIVER_DATA *driverData)
{

#ifdef OUT_CHAR
   CMSMOutMEON ('&', ATTRIB);
#endif /* OUT_CHAR */

   driverData     = driverData;
   MMIOBase = MMIOBase;
   SRAMBase = SRAMBase;
}


/**************************************************************************\
**
** PROC NAME:     IV_FastTxComplete
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_FastTxComplete (void *MMIO, void *SRAMBase, DRIVER_DATA *driverData)
{
   void     *tail;
   void     *head;
   void     *newBase;

#ifdef BROUTER

   UINT8    numBuffs;
   UINT8    outputCnt;
   UINT8    returnCnt;

#endif /* BROUTER */

#ifdef OUT_CHAR
   CMSMOutMEON ('T', ATTRIB);
#endif /* OUT_CHAR */

   do
   {

#ifdef BROUTER

      if (driverData->brouterState)
      {
         outputCnt = Rd8 (driverData->busTag, NULL,
            (void *) ((UINT8 *) SRAMBase + BTCA_OUTPUT_COUNT));
         returnCnt = Rd8 (driverData->busTag, NULL,
            (void *) ((UINT8 *) SRAMBase + BTCA_RETURN_COUNT));

         if (outputCnt != returnCnt)
         {
            newBase = (void *) Rd16 (driverData->busTag, NULL,
               (void *) ((UINT8 *) SRAMBase + BTCA_OLD_BUFFER));

            do
            {
               Wrt8 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
                  (UINT8) newBase);

               newBase = (void *) Rd16 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) driverData->sharedRAMRelative
                     + BTB_BUFFER_POINTER + BTB_LAST_BUFFER
                     + VALUE_TO_HILO_UINT16((UINT16)((UINT32)newBase
                        & ((UINT32)driverData->pageSizeMask | 0xffffff00)))));

               Wrt8 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
                  (UINT8) newBase);

               DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
               driverData->txStartTime = 0;

               newBase = (void *) ((UINT8 *) driverData->sharedRAMRelative
                  + VALUE_TO_HILO_UINT16((UINT16)((UINT32)newBase
                     & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

               numBuffs = Rd8 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) newBase + BTB_BUFFER_POINTER
                     + BTB_NUMBER_BUFFERS));

               newBase = (void *) Rd16 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) newBase + BTB_BUFFER_POINTER
                     + BTB_BUFFER_POINTER));

               Wrt8 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
                  driverData->ivt_FTX.pageValue);

               returnCnt = Rd8 (driverData->busTag, NULL,
                  (void *) ((UINT8 *) SRAMBase + BTCA_RETURN_COUNT));

               Wrt8 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) SRAMBase + BTCA_RETURN_COUNT),
                  returnCnt + numBuffs);

               Wrt16 (
                  driverData->busTag,
                  NULL,
                  (void *) ((UINT8 *) SRAMBase + BTCA_OLD_BUFFER),
                  (UINT16) newBase);

               outputCnt = Rd8 (driverData->busTag, NULL,
                  (void *) ((UINT8 *) SRAMBase + BTCA_OUTPUT_COUNT));
            }
            while (outputCnt != (returnCnt + numBuffs));
         }

return;
      }

#endif /* BROUTER */

      tail = (void *) Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + FP_COMPLETION_Q_TAIL));
   }
   while (tail != (void *) Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + FP_COMPLETION_Q_TAIL)));

   for (;;)
   {
      head = driverData->CompletionQHead;
      if (head == tail)
      {
         return;
      }

#ifdef OUT_CHAR
   CMSMOutMEON ('+', ATTRIB);
#endif /* OUT_CHAR */

      driverData->txStartTime = 0;
      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         (UINT8) head);

      newBase = (void *) ((UINT8 *) driverData->sharedRAMRelative
         + VALUE_TO_HILO_UINT16( (UINT16)
            ((UINT32)head & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

      newBase = (void *) Rd16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) newBase - FP_TX_NEXT_BUFFER + FP_TX_NEXT_BUFFER));

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         (UINT8) newBase);

      newBase = (void *) ((UINT8 *) driverData->sharedRAMRelative
         + VALUE_TO_HILO_UINT16( (UINT16)
            ((UINT32)newBase & ((UINT32)driverData->pageSizeMask | 0xffffff00))));

      newBase = (void *) Rd16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT32) newBase - FP_TX_NEXT_BUFFER + FP_TX_LAST_BUFFER));

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         driverData->ivt_FTX.pageValue);

      Wrt16 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) SRAMBase + FP_FREE_Q_TAIL),
         (UINT16) newBase);

      driverData->CompletionQHead = newBase;
   }
}



/**************************************************************************\
**
** PROC NAME:     IV_InvalidASB
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_InvalidASB (void *MMIOBase, void *SRAMBase, DRIVER_DATA *driverData)
{

#ifdef OUT_CHAR
   CMSMOutMEON ('!', ATTRIB);
#endif /* OUT_CHAR */

   driverData     = driverData;
   MMIOBase = MMIOBase;

   /* We need to set ASB Retcode to SRB_INVALID here   */

   Wrt8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + ASB_RETURN_CODE), SRB_INVALID);
}

/**************************************************************************\
**
** PROC NAME:     IV_SRBResponse
**
**                This routine will ...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/


/* align 16 */

void
IV_SRBResponse (void *MMIO, void *SRAMBase, DRIVER_DATA *driverData)
{
   UINT16   value;
   TCB      *tcb;
   CONFIG_TABLE   *configTable;

#ifdef BROUTER
   UINT16         txOffset;
   UINT16         srbAddress;
   UINT8          rcode;
   MEON_STRING    *message;
#endif /* BROUTER */

#ifdef OUT_CHAR
   CMSMOutMEON ('Z', ATTRIB);
#endif /* OUT_CHAR */

   if (driverData->tcbInProcess)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

      tcb = driverData->tcbInProcess;
      driverData->tcbInProcess = 0;

#ifdef USE_FAST_CALLS
      CTokenTSMFastSendComplete (driverData, tcb, 1);
#else
      CTokenTSMSendComplete (driverData, tcb, 1);
#endif /* USE_FAST_CALLS */

      DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
      driverData->txStartTime = 0;
   }

   driverData->MLIDStatusFlag &= ~SRB_IS_BUSY_BIT;

   /********************************************************************\
   **    check for SRB = 0x08 DIRReadLog
   \********************************************************************/

   if ((Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + SRB_COMMAND))) == SRB_DIR_READ_LOG)
   {
      driverData->LineError             += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 0));
      driverData->InternalError         += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 1));
      driverData->BurstError            += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 2));
      driverData->ACError               += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 3));
      driverData->AbortDelimiter        += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 4));
      driverData->LostFrame             += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 6));
      driverData->PacketRxOverflowCount += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 7));
      driverData->FrameCopiedError      += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 8));
      driverData->FrequencyError        += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 9));
      driverData->TokenError            += (UINT32) Rd8 (driverData->busTag, NULL,
                                    (void *) ((UINT8 *) SRAMBase + 6 + 10));

      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

#ifdef BROUTER

   if ((Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + SRB_COMMAND))) != SRB_OPEN_ADAPTER)
   {
      /********************************************************************\
      **    Check Configure Bridge
      \********************************************************************/

      if ((Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + SRB_COMMAND))) != SRB_SET_BRIDGE)
      {
         if ((Rd8 (driverData->busTag, NULL,
            (void *)((UINT8 *)SRAMBase + SRB_COMMAND))) != SRB_CONFIGURE_BRIDGE)
         {
            CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
            return;
         }
      }

      rcode = Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + BSRB_RETURN_CODE));

      if ((Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + SRB_COMMAND))) == SRB_SET_BRIDGE)
      {
         if (!rcode)
         {
            CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
            return;
         }

         message = BRDGERR1;
      }
      else
         message = BRDGERR2;

      if (rcode)
      {
         /*****************************************************************\
         **    DIROpenReInitAdapter
         \*****************************************************************/

         driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;

         /*****************************************************************\
         **    DIROpenSendAlert
         \*****************************************************************/

         if (driverData->LastErrorMessage == message)
         {
            CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
            return;
         }

         driverData->LastErrorMessage = message;
         driverData->CheckAlertTimer  = 8;

         UpdateAlertStats (MMIO, driverData);
         CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
         return;
      }

      txOffset   = Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + BSRB_TX_OFFSET));

      driverData->ivt_FTX.pageValue   = (UINT8) txOffset;
      driverData->ivt_FTX.baseAddress =
         (void *) ((UINT32) driverData->commonLinearMemory0
         + VALUE_TO_HILO_UINT16(
            txOffset & ((UINT16)driverData->pageSizeMask | 0xff00)));

      srbAddress = Rd16 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRAMBase + BSRB_SRB_ADDRESS));

      driverData->ivt_SRB.pageValue   = (UINT8) srbAddress;
      driverData->ivt_SRB.baseAddress =
         (void *) ((UINT32) driverData->commonLinearMemory0 +
         + VALUE_TO_HILO_UINT16(
            srbAddress & ((UINT16)driverData->pageSizeMask | 0xff00)));

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         (UINT8) srbAddress);

      MovToBus32 (
         driverData->busTag,
         NULL,
         driverData->ivt_SRB.baseAddress,
         &driverData->DIROA,
         OPEN_ADAPTER_SIZE / 4);

      MovToBus32 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) driverData->ivt_SRB.baseAddress + SOPEN_NODE_ADDRESS),
         driverData->commonNodeAddress,
         1);

      MovToBus16 (
         driverData->busTag,
         NULL,
         (void *)((UINT8 *) driverData->ivt_SRB.baseAddress + SOPEN_NODE_ADDRESS + 4),
         (void *) ((UINT8 *) &driverData->commonNodeAddress + 4),
         1);

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + 1),
         COMMAND_IN_SRB);

      driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;
      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

#else

   if ((Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + SRB_COMMAND))) != SRB_OPEN_ADAPTER)
   {
      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

#endif /* BROUTER */

   /********************************************************************\
   **    SRB = 0x03 DIROpenAdapter
   \********************************************************************/

   driverData->OpeningAdapter = 0;

   if ((Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + OPEN_SRB_RETURN_CODE))) != 0)
   {
      DIROpenAdapterError (MMIO, driverData, SRAMBase, (UINT8) ((Rd16 (driverData->busTag,
         NULL, (void *) ((UINT8 *) SRAMBase + OPEN_SRB_ERROR_CODE))) >> 8));
      return;
   }

   value = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + OPEN_ASB_ADDRESS));
   driverData->ivt_ASB.pageValue   = (UINT8) value;
   driverData->ivt_ASB.baseAddress = (void *) ((UINT32) driverData->sharedRAMRelative
      + VALUE_TO_HILO_UINT16(value & ((UINT16)driverData->pageSizeMask | 0xff00)));

   value = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + OPEN_SRB_ADDRESS));
   driverData->ivt_SRB.pageValue   = (UINT8) value;
   driverData->ivt_SRB.baseAddress = (void *) ((UINT32) driverData->sharedRAMRelative
      + VALUE_TO_HILO_UINT16(value & ((UINT16)driverData->pageSizeMask | 0xff00)));

   value = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + OPEN_ARB_ADDRESS));
   driverData->ivt_ARB.pageValue   = (UINT8) value;
   driverData->ivt_ARB.baseAddress = (void *) ((UINT32) driverData->sharedRAMRelative
      + VALUE_TO_HILO_UINT16(value & ((UINT16)driverData->pageSizeMask | 0xff00)));

   value = Rd16 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRAMBase + OPEN_SSB_ADDRESS));
   driverData->ivt_SSB.pageValue   = (UINT8) value;
   driverData->ivt_SSB.baseAddress = (void *) ((UINT32) driverData->sharedRAMRelative
      + VALUE_TO_HILO_UINT16(value & ((UINT16)driverData->pageSizeMask | 0xff00)));


   /* clear the shutdown bit */
                  
   configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;

   configTable->MLIDCFG_SharingFlags &= ~MS_SHUTDOWN_BIT;

   /* Now that open adapter is done, generate NESL MLID Card Insertion Complete Event   */

/*   NESL_EPBPtr->EPBDataPtr0 = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;*/

/* AYD 04-30-97 addded CMSMControlComplete */
   
   CMSMControlComplete(driverData, CHSM_COMPLETE_RESET, ODISTAT_SUCCESSFUL);

   NESL_EPBPtr->EPBDataPtr0 = configTable;

   CMSMNESLProduceEvent(NESLServiceResumeNECBPtr,
                     NULL,
                     NESL_EPBPtr);

#ifdef BROUTER

   if (driverData->brouterState)
   {
      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         driverData->ivt_SRB.pageValue);

      MovFromBus8 (
         driverData->bParmsCommand,
         driverData->busTag,
         NULL,
         driverData->ivt_SRB.baseAddress,
         15);

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + 1),
         COMMAND_IN_SRB);

      driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;

      /********************************************************************\
      **    set functional
      \********************************************************************/

      CTokenTSMUpdateMulticast (driverData);
      UpdateAlertStats (MMIO, driverData);

      if (driverData->LastErrorMessage == 0)
      {
         CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
         return;
      }

      driverData->LastErrorMessage = 0;

         CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

#endif /* BROUTER */

   /********************************************************************\
   **    check for Fast-Path Transmission
   \********************************************************************/

   if (driverData->initStatus & INIT_FAST_PATH)
   {
      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         driverData->ivt_FTX.pageValue);

      driverData->CompletionQHead = (void *) Rd32 (driverData->busTag, NULL,
         (void *) ((UINT8 *) driverData->ivt_FTX.baseAddress + FP_COMPLETION_Q_TAIL));
      driverData->TxCorrelator    = 0;
   }

   /********************************************************************\
   **    set functional
   \********************************************************************/

   CTokenTSMUpdateMulticast (driverData);
   UpdateAlertStats (MMIO, driverData);

   if (driverData->LastErrorMessage == 0)
   {
      CheckNextSRBCommand (MMIO, driverData);
      return;
   }

   driverData->LastErrorMessage = 0;

   CheckNextSRBCommand (MMIO, driverData);
}



/**************************************************************************\
**
** PROC NAME:     DIROpenAdapter
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
DIROpenAdapterError (void *MMIOBase, DRIVER_DATA *driverData, void *SRB,
   UINT8 errorCode)
{
   UINT32         saveErrorCode;
   MEON_STRING    *message;
   CONFIG_TABLE   *configTable;

   configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
   saveErrorCode = errorCode;

   if ((Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) SRB + SRB_RETURN_CODE))) != SRB_COMMAND_CANCELLED)
      message = CNTR2000_DIROPENERR1_MSG;
   else
   {
      errorCode &= 0x0f;

      message = CNTR2000_DUPERR_MSG;
      if (errorCode != OPEN_ERROR_NODE)
      {
         if ((errorCode == OPEN_ERROR_REMOVED)
            || (errorCode == OPEN_ERROR_FUNCTION))
         {
            if (errorCode == OPEN_ERROR_REMOVED)
               message = CNTR2000_IMZAPPED2_MSG;
            else
               message = CNTR2000_IMDICONN3_MSG;

            /**************************************************************\
            **    DIROpenReInitAdapter
            \**************************************************************/

            driverData->MLIDStatusFlag |= RE_INIT_ADAPTER_BIT;
         }
         else if (errorCode == OPEN_ERROR_BEACONING)
            message = CNTR2000_BEACON1_MSG;
         else
            message = CNTR2000_DIROPENERR1_MSG;
      }
   }

   /***********************************************************************\
   **    DIROpenSendAlert
   \***********************************************************************/

   if (driverData->LastErrorMessage == message)
   {
      CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
      return;
   }

   driverData->LastErrorMessage = message;
   driverData->CheckAlertTimer  = 8;

   UpdateAlertStats (MMIOBase, driverData);
   CMSMPrintString (configTable, MSG_TYPE_RUNTIME_WARNING, message, (void *)saveErrorCode, 0); 
   CheckNextSRBCommand (driverData->absoluteMMIOAddress, driverData);
}



/**************************************************************************\
**
** PROC NAME:     UpdateAlertStats
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
UpdateAlertStats (void *MMIOBase, DRIVER_DATA *driverData)
{
   UINT8    OldPage;
   void     *MMIO;

   MMIOBase = MMIOBase;

   MMIO    = driverData->absoluteMMIOAddress;
   OldPage = Rd8 (driverData->busTag, NULL,
   (void *) ((UINT8 *) MMIO + RAM_PAGE_REG));

   Wrt8 (driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->adapterParmsPageValue);

   driverData->LastRingID      = Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) driverData->adapterParmsAddr + PARMS_LOCAL_RING));

   driverData->LastBeaconType   = Rd8 (driverData->busTag, NULL,
      (void *) ((UINT8 *) driverData->adapterParmsAddr + PARMS_BEACON_TYPE));

   Wrt8 (driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      OldPage);
}



/**************************************************************************\
**
** PROC NAME:     IV_SSBResponse
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

/* align 16 */

void
IV_SSBResponse (void *MMIOBase, void *SRAMBase, DRIVER_DATA *driverData)
{

#ifdef OUT_CHAR
   CMSMOutMEON ('@', ATTRIB);
#endif /* OUT_CHAR */

   SRAMBase = SRAMBase;

   Wrt16 (driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIOBase + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      SSB_FREE);
}




/**************************************************************************\
**
** PROC NAME:     CheckNextSRBCommand
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/



void
CheckNextSRBCommand (void *MMIO, DRIVER_DATA *driverData)
{
   void     *SRBBase;
   TCB      *txTail;
   TCB      *txNext;
   TCB      *tcb;
   UINT8    ramPage;

#ifdef OUT_CHAR
   CMSMOutMEON ('N', ATTRIB);
#endif /* OUT_CHAR */

   ramPage = Rd8 (driverData->busTag, NULL, (void *) ((UINT8 *) MMIO + RAM_PAGE_REG));

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      driverData->ivt_SRB.pageValue);

   SRBBase = driverData->ivt_SRB.baseAddress;

   /***********************************************************************\
   **    exit IMMEDIATELY if there is nothing to do
   \***********************************************************************/

   if (driverData->MLIDStatusFlag & (SRB_IS_BUSY_BIT | DIR_FUNCTIONAL_BIT
      | DIR_READ_LOG_BIT))
   {
      /********************************************************************\
      **
      **    SERVICE THE SRB
      **
      **    one of 3 conditions are present...
      **
      **    1) SRB is busy.
      **    2) DIRSetFunctionAddress has been requested.
      **       (setup SRB if it is free and exit)
      **    3) DIRReadLog has been requested.
      **       (setup SRB if it is free and exit)
      **
      \********************************************************************/

      if (!(driverData->MLIDStatusFlag & SRB_IS_BUSY_BIT))
      {
         CheckFunctionalAddressFlag (SRBBase, MMIO, driverData, ramPage);
         return;
      }

      else if ((Rd8 (driverData->busTag, NULL,
         (void *) ((UINT8 *) SRBBase + SRB_RETURN_CODE))) == SRB_IN_PROCESS)
      {
         if (driverData->tcbInProcess)
         {

            tcb = driverData->tcbInProcess;
            driverData->tcbInProcess = 0;

#ifdef OUT_CHAR
   CMSMOutMEON ('2', ATTRIB);
#endif /* OUT_CHAR */


            txTail = (TCB *)( (UINT32)&driverData->txInProcessHead
                        - (UINT32)&((TCB*)0)->TCB_DriverWS[TCB_LINK] );
            txNext = driverData->txInProcessHead;

            while (txNext)
            {
               txTail = txNext;
               txNext = (TCB *) txNext->TCB_DriverWS [TCB_LINK];
            }

            txTail->TCB_DriverWS [TCB_LINK] = (UINT32) tcb;
            tcb->TCB_DriverWS [TCB_LINK] = NULL;


            tcb->TCB_DriverWS [TCB_CORRELATOR] =
               (UINT32) Rd8 (driverData->busTag, NULL,
               (void *) ((UINT8 *) SRBBase + SRB_CMD_CORRELATE));

            driverData->MLIDStatusFlag &= ~SRB_IS_BUSY_BIT;
         }

         CheckFunctionalAddressFlag (SRBBase, MMIO, driverData, ramPage);
         return;
      }
   }

   else if (!(driverData->MLIDStatusFlag & TX_IN_PROCESS_BIT))
   {
      /********************************************************************\
      **    restore page
      \********************************************************************/

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
         ramPage);

#ifdef OUT_CHAR
   CMSMOutMEON ('3', ATTRIB);
#endif /* OUT_CHAR */


      CheckForAnotherSend (driverData);
      return;
   }

   /***********************************************************************\
   **    restore page
   \***********************************************************************/

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      ramPage);
}



/**************************************************************************\
**
** PROC NAME:     CheckFunctionalAddressFlag
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
CheckFunctionalAddressFlag (void *SRBBase, void *MMIO, DRIVER_DATA *driverData,
   UINT8 ramPage)
{
   if (!(driverData->MLIDStatusFlag & (DIR_FUNCTIONAL_BIT | DIR_READ_LOG_BIT)))
   {
      if (!(driverData->MLIDStatusFlag & TX_IN_PROCESS_BIT))
      {
         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            ramPage);

         CheckForAnotherSend (driverData);
         return;
      }

      else
      {
         /*****************************************************************\
         **    restore page
         \*****************************************************************/

         Wrt8 (
            driverData->busTag,
            NULL,
            (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
            ramPage);

         return;
      }
   }

   if (driverData->MLIDStatusFlag & DIR_FUNCTIONAL_BIT)
   {
      /********************************************************************\
      **    set DIR.Set.Functional.Address Function
      \********************************************************************/

      driverData->MLIDStatusFlag &= ~DIR_FUNCTIONAL_BIT;

      Wrt32 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) SRBBase + SRB_FUNCTIONAL_ADDRESS),
         driverData->functionalAddress | OPEN_FUNCTIONAL_ADDR);

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) SRBBase + SRB_COMMAND),
         SRB_DIR_SET_FUNC_ADDR);
   }

   else
   {
      /********************************************************************\
      **    set DIR.Read.Log Function
      \********************************************************************/

      driverData->MLIDStatusFlag &= ~DIR_READ_LOG_BIT;

      Wrt8 (
         driverData->busTag,
         NULL,
         (void *) ((UINT8 *) SRBBase + SRB_COMMAND),
         SRB_DIR_READ_LOG);
   }

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) SRBBase + SRB_RETURN_CODE),
      SRB_NOT_PROCESSED);

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + INT_STATUS_TO_ADAPTER + OR_OFFSET + 1),
      COMMAND_IN_SRB);

   driverData->MLIDStatusFlag |= SRB_IS_BUSY_BIT;

   /*****************************************************************\
   **    restore page
   \*****************************************************************/

   Wrt8 (
      driverData->busTag,
      NULL,
      (void *) ((UINT8 *) MMIO + RAM_PAGE_REG),
      ramPage);

   return;
}



/**************************************************************************\
**
** PROC NAME:     CheckForAnotherSend
**
**                This routine will called when...
**
** Parameters:
**
** Return Value:
**
** See Also:
**
\**************************************************************************/

void
CheckForAnotherSend (DRIVER_DATA *driverData)
{
   TCB      *txHead, *tempTCB;
   TCB      *physTCB = 0;

/* dummy variables for calling DriverSend */

   UINT32         pktSize = 0; 
   CONFIG_TABLE   *configTable   = 0;

   /********************************************************************\
   **    check for INIT_FAST_PATH
   \********************************************************************/

   if (driverData->initStatus & INIT_FAST_PATH)
      return;

#ifdef OUT_CHAR
   CMSMOutMEON ('K', ATTRIB);
#endif /* OUT_CHAR */


   /********************************************************************\
   **    check wait queue for more SRB commands
   \********************************************************************/

   txHead = driverData->SendQueueHead;
   if (txHead)
   {

#ifdef OUT_CHAR
   CMSMOutMEON ('1', ATTRIB);
#endif /* OUT_CHAR */

      tempTCB = (TCB *) txHead->TCB_DriverWS [TCB_LINK];
      txHead->TCB_DriverWS [TCB_LINK] = 0;   /* Unlink it   */
      driverData->SendQueueHead = tempTCB;
      driverData->startSendFlag = 1;
      DriverSend (driverData, configTable, txHead, pktSize, physTCB);
   }

}