// Sample code file: cneamd.c

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

/***********************************************************************\
* $name: CNEAMD.C
 * $version: 8
 * $date_modified: 12181998 
 * $description: C version of the ne2100, PCnetISA, PCnetISA+, PCnetPCI, 
 *               PCnetPCI_II, PCnet-Fast (100 MBps) family driver.  
 * $owner:  ODI LAN Driver Manager
 * Copyright (c) 1996, 1997, 1998 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.
************************************************************************/

/***********************************************************************\
*                                                                       *
*
*   Name:
*         cneamd.c
*
*   Description:
*
*         C version of the ne2100, PCnetISA, PCnetISA+, PCnetPCI, PCnetPCI_II
*         PCnet-Fast (100 MBps) family driver.
*
*  Notes:
*
*  Origin:
*
*         Derived from cne15_21.c
*
*  Created by:
*                     AYD 1995-96
*
*                     AYD 11-15-96, 11-18-96, 14-12-96
*                     Added Style 3 descriptors, burst Read and Write. Added
*                     new structures PCI_32_RX_DESC, PCI_32_TX_DESC to support
*                     Style 2 descriptors for older revs. of PCnetPCI. Added
*                     a new flag PCNETPCI_II which indicate PCnetPCI_II or/and
*                     PCnetFast NICs. Changed scatter/gather count in case of
*                     PCnetISA, PCnetPCI/II/Fast to 16.
*
*                      AYD 02-12-97
*                     Added code to detect dynamically a link speed, currently
*                     running and put the value in MLID config table.
*
*                     AYD 02-14-97
*                      Added a new call in DriverInit CMSMParseSingleParameter for
*                     preliminary parsing.
*
*                     AYD 02-21-97
*                     Added an API CMSMInitParser in DriverInit
*
*                     AYD 07-01-97
*                     Added code in DriverISRs to prevent receive if shutdown
*                     bit is set and in DriverShutdown check if shutdown for the
*                     whole adapter (OP_SCOPE_ADAPTER).
*
*                     AYD 08-29-97
*                     Commented out SPARE_ECB_STATUS checks.
*
*                     AYD 11-10-97
*                     Changed CommonMaximumSize to 2048 to receive jabber 
*                     packets. Removed unnecessary code from DriverISRPCI and
*                      DriverISRPCI_II. Removed Line Speed check from DriverCallBack.
*                     Added CMSMUpdateConfigTables call in DriverReset to update
*                     a Line Speed value in config table.
*                     
*                     AYD 01-23-98 
*                     Because the CMSMTCBPhysToLogFrags API has changed the DriverSendLANCE procedure has
*                     changed. The return value for CMSMTCBPhysToLogFrags has changed in the spec and code. 
*                     CMSMTCBPhysToLogFrags now returns an ECB pointer where it use to return a pointer 
*                     to the ECB_FragmentCount field in the ECB. The cneamd.lan expected the return of 
*                     the ECB_FragmentCount pointer.
************************************************************************/

#include <portable.h>
#include <odi.h>
#include <odi_nbi.h>
#include <odi_nesl.h>
#include <nesl_str.h>
#include <parser.h>
#include <cmsm.h>
#include <cneamd.txt>
#include <debug.txt>


/* AYD  include to use a debug function NiosBreak and NiosDprintf */
#ifdef DEBUG
#include <nios.h>
#include <nstdlib.h>
#endif

/***********************************************************************\
*                                                                       *
* cneamd Definitions.                                                 *
*                                                                       *
************************************************************************/

/*    7990, PCnetISA, PCnetPCI Control/Status Register Offsets and Bit Values.   */

#define   CSR0      0      /* Offset of CSR 0   Status and Control         */
#define   CSR1      1      /* Offset of CSR 1   Lower IADR                  */
#define   CSR2      2      /* Offset of CSR 2   Upper IADR                  */
#define   CSR3      3      /* Offset of CSR 3   Int mask, Config            */
#define   CSR4      4      /* Offset of CSR 4   Int mask, Config & status   */
#define   CSR80      80      /* Offset of CSR 80  FIFO threshold               */
#define   CSR82      82      /* Offset of CSR 82  Bus timer                  */
#define   CSR88      88      /* Offset of CSR 88  Chip ID.                     */
#define   CSR89      89      /* Offset of CSR 89  Chip ID.                     */
#define   CSR124   124   /* Offset of CSR 124 Test Register               */

#define   BCR9      9      /* Offset of BCR 9  Full-Duplex Control         */
#define   BCR18      18      /* Offset of BCR 18 Burst and Bus Control Reg.   */
#define   BCR19      19      /* Offset of BCR 19 EEPROM Control and Status   */
#define   BCR20      20    /* Offset of BCR 20 Software Stile                */
#define   BCR33      33      /* Offset of BCR 33 MII Address Register         */
#define   BCR34      34      /* Offset of BCR 34 MII Management Data Register */



/*      CSR0 bits.            */

#define   ERR      0x8000       /* Bit 15 - BABL, CERR, MISS OR MERR.     */
#define   BABL      0x4000      /* Bit 14 - Tx Babbled error.               */
#define   CERR      0x2000      /* Bit 13 - Tx Collision error.            */
#define   MISS      0x1000      /* Bit 12 - Rx missed error.               */
#define   MERR      0x0800      /* Bit 11 - Memory access error.            */
#define   RINT      0x0400      /* Bit 10 - Rx interrupt.                  */
#define   TINT      0x0200      /* Bit 09 - Tx interrupt.                  */
#define   IDON      0x0100      /* Bit 08 - Init done.                     */

#define   INTR      0x0080       /* Bit 07 - Interrupt occurred.            */
#define   INEA      0x0040      /* Bit 06 - Interrupt enable.               */
#define   RXON      0x0020      /* Bit 05 - Receiver on.                  */
#define   TXON      0x0010      /* Bit 04 - Transmitter on.               */
#define   TDMD      0x0008      /* Bit 03 - Transmit demand.               */
#define   STOP      0x0004      /* Bit 02 - Stop Lance.                     */
#define   STRT      0x0002      /* Bit 01 - Start Lance.                  */
#define   INIT      0x0001      /* Bit 00 - Initialize Lance.               */

#define IMASK      0x0300      /* PCNetISA Interrupt MASK */

/*      Transmit Message Descriptor 1 bits.      */

#define   T_OWN      0x80
#define   T_ERR      0x40
#define   T_RES      0x20
#define   T_MORE   0x10
#define   T_ONE      0x08
#define   T_DEF      0x04
#define   T_STP      0x02
#define   T_ENP      0x01

#define   T_BUF      0x8000
#define   T_UFL      0x4000
#define   T_LAT      0x1000
#define   T_CAR      0x0800
#define   T_COL      0x0400

/*      Receive Message Descriptor 1 bits.      */

#define   R_OWN      0x80
#define   R_ERR      0x40
#define   R_FRM      0x20
#define   R_OFL      0x10
#define   R_CRC      0x08
#define   R_BUF      0x04
#define   R_STP      0x02
#define   R_ENP      0x01

/*      Transmit Message Descriptor for SWSTYLE = 3      */

#define   T_OWN_32      0x8000   /* Bit 31 - Descriptor owned by HOST OWN = 0 */
#define   T_ERR_32      0x4000   /* Bit 30 */
#define   T_RES_32      0x2000   /* Bit 29 */
#define   T_MORE_32   0x1000   /* Bit 28 */
#define   T_ONE_32      0x0800   /* Bit 27 */
#define   T_DEF_32      0x0400   /* Bit 26 */
#define   T_STP_32      0x0200   /* Bit 25 - Start of the Packet                */
#define   T_ENP_32      0x0100   /* Bit 24 - End of the Packet                */

/*      Receive Message Descriptor for SWSTYLE = 3      */

#define   R_OWN_32      0x8000   /* Bit 31 - Descriptor owned by HOST OWN = 0 */
#define   R_ERR_32      0x4000   /* Bit 30 */
#define   R_FRM_32      0x2000   /* Bit 29 */
#define   R_OFL_32      0x1000   /* Bit 28 */
#define   R_CRC_32      0x0800   /* Bit 27 */
#define   R_BUF_32      0x0400   /* Bit 26 */
#define   R_STP_32      0x0200   /* Bit 25 - Start of the Packet                */
#define   R_ENP_32      0x0100   /* Bit 24 - End of the Packet                */


#define   MASK_ENP_STP   0xFCFF
#define   MASK_ENP      0xFEFF


/*      Tx & Rx Buffer equates.                  */

#define   TX_BUFFERS         2            /* 2, 4, 8, 16, 32, 64 or 128.   */
/* AYD 12-04-96 */
#define TX_BUFFERS_FRAG      64               /* PCnetISA - 32, 64, 128         */
#define RX_BUFFERS         32             /* 2, 4, 8, 16, 32, 64 or 128.  */
#define BUFFER_SIZE        (1518+2)    /* Keep on dword boundary.      */

/* PCnetISA configuration init values   */

#define   RCVFW_INIT      0x1000         /* 32 bytes.                     */
#define   XMTSP_INIT      0x0800         /* 64 bytes.                     */
#define   XMTFW_INIT      0x0000         /* 8 cycles.                     */
#define   DMAPLUS_INIT   0x0000         /* DMAPLUS disabled.               */
#define   ENTST         0x8000         /* Enable Runt Packet Accept see CSR124*/
#define   LEVEL_INIT      0x0000         /* Level disabled.               */
#define   FASTISA_INIT   0x0000         /* Fast ISA disabled.            */
#define   BNC_INIT      0x0000         /* Not BNC.                        */

/* NIC types */

#define   LANCE              0
#define   PCNETISA         1
#define   PCNETPCI       2
#define   PCNETPCI_II      3

/***********************************************************************\
*                                                                       *
* CNEAMD Structure definitions.                                          *
*                                                                       *
************************************************************************/

typedef struct _ATTR_   {
   UINT16            LAddr;
   UINT8               HAddr;
   UINT8               Attr;
} ATTR;

typedef struct _TX_DESC_ {
   union               {
                     UINT32      TxAddr;
                     ATTR         TxAttr;
                     }TxDescAddr;
   UINT16            TxDescSize;
   UINT16            TxDescStatus;
} TX_DESC;

typedef struct _RX_DESC_   {
   union               {
                     UINT32      RxAddr;
                     ATTR         RxAttr;
                     }RxDescAddr;
   UINT16            RxDescBufferCount;
   UINT16            RxDescMessageCount;
} RX_DESC;

/***********************************************************************\
*                                                                       *
* Full 32 bit mode structure definitions. SWSTYLE = 1 or 2              *
*                                                                       *
************************************************************************/
typedef struct _PCI_INIT   {
  UINT16        Mode;                      /* Mode - Use defaults      */
  UINT16          PCI_Len;
  UINT8         PCI_PhysicalAddress[6];   /* Adapter Physical address */
  UINT16          PCI_Unused;
  UINT8         PCI_LogicalAddressFilter[8];/* Multicast hash table     */
  void          *PCI_RxDescriptorRingPtr; /*  -> Rx Ring            */
  void          *PCI_TxDescriptorRingPtr; /* -> Tx Ring           */
} PCI_INIT;

typedef struct _PCI_TX_DESC_ {
   UINT32      TxAddr_32;           /* TMD0 */
   UINT16      BufferByteCnt;         /* TMD1 */
   UINT16      TxDescStatus_32;
   UINT16      TxRetryCount;        /* TMD2 */
   UINT16      TxError;
   UINT32      Reserved;            /* TMD3 */
} PCI_TX_DESC;

typedef struct _PCI_RX_DESC_   {
   UINT32      RxAddr_32;            /* RMD0 */
   UINT16      BufferByteCnt;         /* RMD1 */
   UINT16      RxDescStatus_32;
   UINT16      MessageByteCnt;      /* RMD2 */
   UINT16      RxStats;
   UINT32      Reserved;            /* RMD3 */
} PCI_RX_DESC;

/* AYD 11-15-96 These two structures used only if SWSTYLE = 3*/
/* SWSTYLE = 3 supported in PCnetPCI II and PCnetFast */
typedef struct _PCI_II_TX_DESC_ {
   UINT16      TxRetryCount_II;        /* TMD0 */
   UINT16      TxError_II;
   UINT16      BufferByteCnt_II;         /* TMD1 */
   UINT16      TxDescStatus_32_II;
   UINT32      TxAddr_32_II;           /* TMD2 */
   UINT32      Reserved;               /* TMD3 */
} PCI_II_TX_DESC;

typedef struct _PCI_II_RX_DESC_   {
   UINT16      MessageByteCnt_II;      /* RMD0 */
   UINT16      RxStats_II;
   UINT16      BufferByteCnt_II;         /* RMD1 */
   UINT16      RxDescStatus_32_II;
   UINT32      RxAddr_32_II;            /* RMD2 */
   UINT32      Reserved;               /* RMD3 */
} PCI_II_RX_DESC;

typedef struct _PCI_32_TX_DESC_   {
   union   {
            PCI_TX_DESC ST2;                /* Style 2 */
            PCI_II_TX_DESC ST3;             /* Style 3 */
         } U;
} PCI_32_TX_DESC;

typedef struct _PCI_32_RX_DESC_   {
   union   {
            PCI_RX_DESC ST2;                /* Style 2 */
            PCI_II_RX_DESC ST3;             /* Style 3 */
         } U;
} PCI_32_RX_DESC;

typedef struct _DRIVER_DATA_ {
  void          *TxBuffers;

  UINT16        InitializationBlock;       /* Mode - Use defaults      */
  UINT8         PhysicalAddress[6];         /* Adapter Physical address */
  UINT8         LogicalAddressFilter[8];   /* Multicast hash table     */
  void          *RxDescriptorRingPtr;       /*  -> Rx Ring            */
  void          *TxDescriptorRingPtr;       /* -> Tx Ring           */

/* Message Descriptors must be at QWORD boundary.
 The following 2 Tables could float backwards by one dword.   */

  UINT32        Reserved0QwordAlign;    /* Reserve for QWORD align    */
  UINT32          Reserved1QwordAlign;

  RX_DESC       RxDescriptorTable[RX_BUFFERS];
  TX_DESC       TxDescriptorTable[TX_BUFFERS_FRAG];   /* PCnetISA   */

  RX_DESC       *RxDescriptorTablePtr;  /* Points to RxDescriptorTable*/
  TX_DESC       *TxDescriptorTablePtr;  /* Points to TxDescriptorTable*/

  UINT32        RDP;
  UINT32        RAP;
  UINT32        Reset;
  UINT32        IDP_BDP;
 /* AYD */
  UINT32        TxNextToReturn;
  UINT32        TxNextToSend;
  void          *TxBufferTable[TX_BUFFERS];
  struct _TCB_  *TCBTable[TX_BUFFERS_FRAG];
  UINT32        TxStartTime[TX_BUFFERS_FRAG];
  UINT32        PaddedValue;   /* AYD */
  UINT32        TxLastDesc[TX_BUFFERS_FRAG];
  UINT32        TxBufferIndex;

  UINT32        RxNextToReturn;
  UINT32        RxNextToAllocate;
  struct _RCB_  *RCBTable[RX_BUFFERS];
  UINT32        NeedRCBCount;
  UINT32        CheckRxCount;
  UINT32        LastTotalRxPacketCount;
  /* UINT8          TempBuffer[2000];     */   /* AYD 04-08-96 */
  /* UINT8          RxDescrTempBuffer[8*16]; */

  UINT32        PCnetFlag;
  UINT32        CommonMaximumSize;
  UINT32        BusType;
  void          *BusTag;
  UINT8         ResetFlag;
  UINT8          BNCFlag;
  UINT32          uniqueID;
  UINT32          FullDuplex;

  UINT32        ReservedForDWordAlign;            /* Reserve for DWORD align */
  PCI_INIT      PCI_InitializationBlock;          /* PCI Init block  */
  PCI_INIT      *PCI_InitializationBlockPtr;    /* Pointer to init block  */

/* Message Descriptors must be at QWORD boundary.
 The following 2 Tables could float backwards by one dword.   */

  UINT32        PCI_Reserved0QwordAlign;    /* Reserve for 16 byte align    */
  UINT32          PCI_Reserved1QwordAlign;
  UINT32        PCI_Reserved2QwordAlign;
  UINT32          PCI_Reserved3QwordAlign;
  PCI_32_RX_DESC   PCI_RxDescriptorTable[RX_BUFFERS];
  PCI_32_TX_DESC   PCI_TxDescriptorTable[TX_BUFFERS_FRAG];

  PCI_32_RX_DESC   *PCI_RxDescriptorTablePtr;  /* Points to RxDescriptorTable*/
  PCI_32_TX_DESC   *PCI_TxDescriptorTablePtr;  /* Points to TxDescriptorTable*/

  MLID_AES_ECB  DAES;

  MLID_StatsTable StatsTable;

  StatTableEntry    TotalTxPacketTable;
  StatTableEntry    TotalRxPacketTable;
  StatTableEntry    NoECBAvailableTable;
  StatTableEntry    PacketTxTooBigTable;
  StatTableEntry    PacketTxTooSmallTable;
  StatTableEntry    PacketRxOverflowTable;
  StatTableEntry    PacketRxTooBigTable;
  StatTableEntry    PacketRxTooSmallTable;
  StatTableEntry    PacketTxMiscErrorTable;
  StatTableEntry    PacketRxMiscErrorTable;
  StatTableEntry    RetryTxTable;
  StatTableEntry    ChecksumErrorTable;
  StatTableEntry    HardwareRxMismatchTable;
  StatTableEntry    TotalTxOKByteTable;
  StatTableEntry    TotalRxOKByteTable;
  StatTableEntry    TotalGroupAddrTxTable;
  StatTableEntry    TotalGroupAddrRxTable;
  StatTableEntry    AdapterResetTable;
  StatTableEntry    AdapterOprTimeStampTable;
  StatTableEntry    QDepthTable;

  StatTableEntry    TxOKSingleCollisionTable;
  StatTableEntry    TxOKMultipleCollisionsTable;
  StatTableEntry    TxOKButDeferredTable;
  StatTableEntry    TxAbortLateCollisionTable;
  StatTableEntry    TxAbortExcessCollisionsTable;
  StatTableEntry    TxAbortCarrierSenseTable;
  StatTableEntry    TxAbortExDeferralTable;
  StatTableEntry    RxAbortFrameAlignmentTable;

  StatTableEntry    HeartbeatErrorTable;
  StatTableEntry    MemoryErrorTable;
  StatTableEntry    TxOverflowTable;
  StatTableEntry    TxUnderflowTable;
  StatTableEntry    TxBufferErrorTable;
  StatTableEntry    ECBsOver16MegTable;
  StatTableEntry    TxECBsOver16MegTable;
  StatTableEntry    ECBOverflowTable;

  UINT32        TotalTxPacketCount;
  UINT32        TotalRxPacketCount;
  UINT32        NoECBAvailableCount;
  UINT32        PacketTxTooBigCount;
  UINT32        PacketTxTooSmallCount;
  UINT32        PacketRxOverflowCount;
  UINT32        PacketRxTooBigCount;
  UINT32        PacketRxTooSmallCount;
  UINT32        PacketTxMiscErrorCount;
  UINT32        PacketRxMiscErrorCount;
  UINT32        RetryTxCount;
  UINT32        ChecksumErrorCount;
  UINT32        HardwareRxMismatchCount;
  UINT64        TotalTxOKByteCount;
  UINT64        TotalRxOKByteCount;
  UINT32        TotalGroupAddrTxCount;
  UINT32        TotalGroupAddrRxCount;
  UINT32        AdapterResetCount;
  UINT32        AdapterOprTimeStamp;
  UINT32        QDepth;

  UINT32        TxOKSingleCollision;
  UINT32        TxOKMultipleCollisions;
  UINT32        TxOKButDeferred;
  UINT32        TxAbortLateCollision;
  UINT32        TxAbortExcessCollisions;
  UINT32        TxAbortCarrierSense;
  UINT32        TxAbortExDeferral;
  UINT32        RxAbortFrameAlignment;

  UINT32        HeartbeatError;
  UINT32        MemoryError;
  UINT32        TxOverflow;
  UINT32        TxUnderflow;
  UINT32        TxBufferError;
  UINT32        ECBsOver16Meg;
  UINT32        TxECBsOver16Meg;
  UINT32        ECBOverflowCount;


} DRIVER_DATA;

#include <ethertsm.h>

/***********************************************************************\
*                                                                       *
* CNEAMD function prototypes.                                            *
*                                                                       *
************************************************************************/
void       CFixUpStatStrings(
            DRIVER_DATA       *DriverData);

void      DriverEnableInterrupt(
            DRIVER_DATA         *DriverData);

void       DriverCallBack(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable);

BOOLEAN   DriverDisableInterrupt(
            DRIVER_DATA         *DriverData,
            BOOLEAN Flag);

void      DriverISRISA(
            DRIVER_DATA         *DriverData);

void      DriverISRPCI(
            DRIVER_DATA         *DriverData);

void      DriverISRPCI_II(
            DRIVER_DATA         *DriverData);

UINT32   DriverISRErrorHandler(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            UINT32            InterruptStatus);

UINT32   DriverISRTxErrorHandler(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable);

ODISTAT   DriverMulticastChange(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            GROUP_ADDR_LIST_NODE   *mcTable,
            UINT32            NumEntries,
            UINT32            functionalTable);

void      DriverPromiscuousChange(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            UINT32            promiscuousMode);

void      DriverSendLANCE(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            TCB               *tcb,
            UINT32            packetSize,
            void               *physTcb);

void      DriverSendISA(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            TCB               *tcb,
            UINT32            packetSize,
            void               *physTcb);

void      DriverSendPCI(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            TCB               *tcb,
            UINT32            packetSize,
            void               *physTcb);

void      DriverSendPCI_II(
            DRIVER_DATA         *DriverData,
            CONFIG_TABLE      *configTable,
            TCB               *tcb,
            UINT32            packetSize,
            void               *physTcb);

ODISTAT   DriverShutdown(
            DRIVER_DATA       *DriverData,
            CONFIG_TABLE      *configTable,
            UINT32            shutdownType,
            OPERATION_SCOPE   operationScope);

ODISTAT   DriverReset(
            DRIVER_DATA       *DriverData,
            CONFIG_TABLE      *configTable,
            OPERATION_SCOPE   operationScope);

void      SetMulticast(
            DRIVER_DATA         *DriverData,
            GROUP_ADDR_LIST_NODE   *mcTable);

ODISTAT   DriverInitISA(   UINT32 *PCnetFlagISA,
                        CONFIG_TABLE  *configTable);


MEON_STRING CHSMSPEC[] = {CNEAMD_SPECVER_TXTMSG};

/* TNL 12/06/95 Data pointers needed for NESL event production   */

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


/* DriverMessages will be filled in by MSM(<TSM>RegisterHSM) to point      */
/* to message enabled messages.                                             */

MEON   **DriverMessages = NULL;

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

/* AYD 03-09-95 */
#define NUMBER_OF_GENERICS  &((DRIVER_DATA *)0)->QDepth - \
  &((DRIVER_DATA *)0)->TotalTxPacketCount - 1

#define NUMBER_OF_MEDIAS    &((DRIVER_DATA *)0)->RxAbortFrameAlignment - \
  &((DRIVER_DATA *)0)->TxOKSingleCollision +1

#define NUMBER_OF_CUSTOMS   &((DRIVER_DATA *)0)->ECBOverflowCount - \
  &((DRIVER_DATA *)0)->HeartbeatError +1

/* AYD */
/*#define NUMBER_OF_GENERICS  20L
#define NUMBER_OF_MEDIAS     8L
#define NUMBER_OF_CUSTOMS    8L  */

/* AYD used to align for test
UINT8    DriverDataSignature[] = {'D','D','T','S'}; */

static DRIVER_DATA DriverDataTemplate = {
  NULL,                 /* TxBuffers              */

  0,                    /* InitializationBlock    */
  {0,0,0,0,0,0},        /* PhysicalAddress        */
  {0,0,0,0,0,0,0,0},    /* LogicalAddressFilter   */
  NULL,                 /* *RxDescriptorRingPtr   */
  NULL,                 /* *TxDescriptorRingPtr   */


  0,                    /* Reserved0QwordAlign    */
  0,                    /* Reserved1QwordAlign    */


  {0},                  /* RxDescriptorTable      */
  {0},                  /* TxDescriptorTable      */

  NULL,                 /* *RxDescriptorTablePtr  */
  NULL,                 /* *TxDescriptorTablePtr  */

  0,                    /* RDP                    */
  0,                    /* RAP                    */
  0,                    /* Reset                  */
  0,                    /* IDP_BDP                    */

  0,                    /* TxNextToReturn         */
  0,                    /* TxNextToSend           */
  {NULL},               /* TxBufferTable          */
  {NULL},               /* TCBTable               */
  {0},                  /* TxStartTime            */
  0,                    /* AYD PaddedValue        */
  {0},                  /* TxLastDesc             */
  0,                    /* TxBufferIndex          */

  0,                    /* RxNextToReturn         */
  0,                    /* RxNextToAllocate       */
  {NULL},               /* RCBTable               */
  RX_BUFFERS,           /* NeedRCBCount           */
  16,                   /* CheckRxCount           */
  0,                    /* LastTotalRxPacketCount */
  /*{0},   */                  /* AYD 04-08-96*/
  /*{0}, */

  0,                    /* PCnetFlag           */
  0,                    /* CommonMaximumSize      */
  0,                    /* BusType                */
  NULL,                 /* *BusTag                */
  0,                    /* ResetFlag              */
  0,                     /* BNCFlag                 */
  0,                     /* uniqueID                  */
  0,                     /* FullDuplex               */

  0,                      /* ReservedForDWordAlign   */
  {0},                    /* PCI_InitializationBlock */
  NULL,                   /* PCI_InitializationBlockPtr */

  0,                       /* PCI_Reserved0QwordAlign   */
  0,                      /* PCI_Reserved1QwordAlign */
  0,                    /* PCI_Reserved2QwordAlign */
  0,                     /* PCI_Reserved3QwordAlign */

  {0},                  /* PCI_RxDescriptorTable[RX_BUFFERS] */
  {0},                  /* PCI_TxDescriptorTable[TX_BUFFERS_FRAG] */
  NULL,                   /* *PCI_RxDescriptorTablePtr   */
  NULL,                   /* *PCI_TxDescriptorTablePtr  */

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

  {4,                   /* StatsTable->MStatTableMajorVer     */
  00,                   /* StatsTable->MStatTableMinorVer     */
  NUMBER_OF_GENERICS,   /* StatsTable->MNumGenericCounters      */
   &DriverDataTemplate.TotalTxPacketTable,
                        /* StatsTable->MGenericCountsPtr        */
  NUMBER_OF_MEDIAS,     /* StatsTable->MNumMediaCounters        */
   &DriverDataTemplate.TxOKSingleCollisionTable,
                        /* StatsTable->MMediaCountersPtr        */
  NUMBER_OF_CUSTOMS,    /* StatsTable->MNumCustomCounters     */
   &DriverDataTemplate.HeartbeatErrorTable},
                        /* StatsTable->MCustomCountersPtr     */

  {ODI_STAT_UINT32,     /* TotalTxPacketTable->StatUseFlag      */
   &DriverDataTemplate.TotalTxPacketCount,         /* ->StatCounter         */
  NULL},                /* ->StatString     */

  {ODI_STAT_UINT32,     /* TotalRxPacketTable->StatUseFlag      */
   &DriverDataTemplate.TotalRxPacketCount,         /* ->StatCounter         */
  NULL},                /*  ->StatString      */

   {ODI_STAT_UINT32,               /* NoECBAvailableTable->StatUseFlag         */
   &DriverDataTemplate.NoECBAvailableCount,         /*  ->StatCounter         */
   NULL},                                          /*  ->StatString         */

   {ODI_STAT_UINT32,               /* PacketTxTooBigTable->StatUseFlag         */
   &DriverDataTemplate.PacketTxTooBigCount,         /*  ->StatCounter         */
   NULL},                                          /*  ->StatString         */

   {ODI_STAT_UINT32,               /* PacketTxTooSmallTable->StatUseFlag      */
   &DriverDataTemplate.PacketTxTooSmallCount,         /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,               /* PacketRxOverflowTable->StatUseFlag      */
   &DriverDataTemplate.PacketRxOverflowCount,         /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,               /* PacketRxTooBigTable->StatUseFlag         */
   &DriverDataTemplate.PacketRxTooBigCount,         /*  ->StatCounter         */
   NULL},                                          /*  ->StatString         */

   {ODI_STAT_UINT32,               /* PacketRxTooSmallTable->StatUseFlag      */
   &DriverDataTemplate.PacketRxTooSmallCount,         /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,               /* PacketTxMiscErrorTable->StatUseFlag      */
   &DriverDataTemplate.PacketTxMiscErrorCount,         /*  ->StatCounter      */
   NULL},                                             /*  ->StatString      */

   {ODI_STAT_UINT32,               /* PacketRxMiscErrorTable->StatUseFlag      */
   &DriverDataTemplate.PacketRxMiscErrorCount,         /*  ->StatCounter      */
   NULL},                                             /*  ->StatString      */

   {ODI_STAT_UINT32,                        /* RetryTxTable->StatUseFlag      */
   &DriverDataTemplate.RetryTxCount,                  /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,                  /* ChecksumErrorTable->StatUseFlag      */
   &DriverDataTemplate.ChecksumErrorCount,            /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,               /* HardwareRxMismatchTable->StatUseFlag   */
   &DriverDataTemplate.HardwareRxMismatchCount,         /*   ->StatCounter   */
   NULL},                                             /*   ->StatString      */

   {ODI_STAT_UINT64,                  /* TotalTxOKByteTable->StatUseFlag      */
   &DriverDataTemplate.TotalTxOKByteCount,            /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT64,                  /* TotalRxOKByteTable->StatUseFlag      */
   &DriverDataTemplate.TotalRxOKByteCount,            /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,                  /* TotalGroupAddrTxTable->StatUseFlag   */
   &DriverDataTemplate.TotalGroupAddrTxCount,            /* ->StatCounter   */
   NULL},                                                /* ->StatString   */

   {ODI_STAT_UINT32,                  /* TotalGroupAddrRxTable->StatUseFlag   */
   &DriverDataTemplate.TotalGroupAddrRxCount,            /* ->StatCounter   */
   NULL},                                                /* ->StatString   */

   {ODI_STAT_UINT32,                  /* AdapterResetTable->StatUseFlag      */
   &DriverDataTemplate.AdapterResetCount,               /*->StatCounter      */
   NULL},                                             /*->StatString         */

   {ODI_STAT_UINT32,               /* AdapterOprTimeStampTable->StatUseFlag   */
   &DriverDataTemplate.AdapterOprTimeStamp,               /* ->StatCounter   */
   NULL},                                                /* ->StatString   */

   {ODI_STAT_UINT32,                           /* QDepthTable->StatUseFlag   */
   &DriverDataTemplate.QDepth,                           /*->StatCounter   */
   NULL},                                                /*->StatString      */

   {ODI_STAT_UINT32,            /* TxOKSingleCollisionTable->StatUseFlag      */
   &DriverDataTemplate.TxOKSingleCollision,            /* ->StatCounter      */
   NULL},                                             /* ->StatString      */

   {ODI_STAT_UINT32,            /* TxOKMultipleCollisionsTable->StatUseFlag   */
   &DriverDataTemplate.TxOKMultipleCollisions,         /*    ->StatCounter   */
   NULL},                                             /*    ->StatString   */

   {ODI_STAT_UINT32,                  /* TxOKButDeferredTable->StatUseFlag   */
   &DriverDataTemplate.TxOKButDeferred,               /*   ->StatCounter   */
   NULL},                                             /*   ->StatString      */

   {ODI_STAT_UINT32,               /* TxAbortLateCollisionTable->StatUseFlag   */
   &DriverDataTemplate.TxAbortLateCollision,               /*  ->StatCounter   */
   NULL},                                                /*  ->StatString   */

   {ODI_STAT_UINT32,            /* TxAbortExcessCollisionTable->StatUseFlag   */
   &DriverDataTemplate.TxAbortExcessCollisions,            /* ->StatCounter   */
   NULL},                                                /* ->StatString   */

   {ODI_STAT_UINT32,               /* TxAbortCarrierSenseTable->StatUseFlag   */
   &DriverDataTemplate.TxAbortCarrierSense,               /* ->StatCounter   */
   NULL},                                                /* ->StatString   */

   {ODI_STAT_UINT32,               /* TxAbortExDeferralTable->StatUseFlag      */
   &DriverDataTemplate.TxAbortExDeferral,               /*  ->StatCounter      */
   NULL},                                             /*  ->StatString      */

   {ODI_STAT_UINT32,            /* RxAbortFrameAlignmentTable->StatUseFlag   */
   &DriverDataTemplate.RxAbortFrameAlignment,         /*   ->StatCounter   */
   NULL},                                             /*   ->StatString      */

   {ODI_STAT_UINT32,                     /* HeartbeatErrorTable->StatUseFlag   */
   &DriverDataTemplate.HeartbeatError,                     /*  ->StatCounter   */
   NULL},                                                /*  ->StatString   */
   {ODI_STAT_UINT32,                     /* MemoryErrorTable->StatUseFlag      */
   &DriverDataTemplate.MemoryError,                     /*  ->StatCounter      */
   NULL},                                             /*  ->StatString      */
   {ODI_STAT_UINT32,                     /* TxOverflowTable->StatUseFlag      */
   &DriverDataTemplate.TxOverflow,                     /* ->StatCounter      */
   NULL},                                             /* ->StatString      */
   {ODI_STAT_UINT32,                     /* TxUnderflowTable->StatUseFlag      */
   &DriverDataTemplate.TxUnderflow,                     /*  ->StatCounter      */
   NULL},                                             /*  ->StatString      */
   {ODI_STAT_UINT32,                  /* TxBufferErrorTable->StatUseFlag      */
   &DriverDataTemplate.TxBufferError,                  /* ->StatCounter      */
   NULL},                                             /* ->StatString      */
   {ODI_STAT_UINT32,                  /* ECBsOver16MegTable->StatUseFlag      */
   &DriverDataTemplate.ECBsOver16Meg,                  /* ->StatCounter      */
   NULL},                                             /* ->StatString      */
   {ODI_STAT_UINT32,                  /* TxECBsOver16MegTable->StatUseFlag   */
   &DriverDataTemplate.TxECBsOver16Meg,               /*   ->StatCounter   */
   NULL},                                             /*   ->StatString      */
   {ODI_STAT_UINT32,               /* ECBOverflowCountTable->StatUseFlag      */
   &DriverDataTemplate.ECBOverflowCount,               /* ->StatCounter      */
   NULL},                                             /* ->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,                    /* TxOKSingleCollision              */
  0,                    /* TxOKMultipleCollsions            */
  0,                    /* TxOKButDeferred                  */
  0,                    /* TxAbortLateCollision             */
  0,                    /* TxAbortExcessCollisions          */
  0,                    /* TxAbortCarrierSense              */
  0,                    /* TxAbortExDeferral                */
  0,                    /* RxAbortFrameAlignment            */

  0,                    /* HeartbeatError                   */
  0,                    /* MemoryError                      */
  0,                    /* TxOverflow                       */
  0,                    /* TxUnderflow                      */
  0,                    /* TxBufferError                    */
  0,                    /* ECBsOver16Meg                    */
  0,                    /* TxECBsOver16Meg                  */
  0                     /* ECBOverflowCount                 */
};   /* End DriverDataTemplate */

/* Configuration Table Template. <TSM>RegisterHSM will initialize the      */
/* configuration table in each frame data space will be initialized with   */
/* values in this template.                                                */

/* AYD 07-05-95 */
#define ModeFlags      MM_MULTICAST_BIT \
                     | MM_C_HSM_BIT \
                     | MM_PROMISCUOUS_BIT \
                     | MM_PREFILLED_ECB_BIT \
                | MM_FRAGS_PHYS_BIT
#define   MFlags         0
#define   SharingFlags   0

MEON_STRING NICShortName[] =  {CNEAMD_SHORTNAME_TXTMSG};

/* AYD used to align for test
UINT8    DriverConfigSignature[] = {'D','C','T','S','0','0','0','0'}; */

static CONFIG_TABLE DriverConfigTemplate = {
  CNEAMD_CONFIGSIG_TXTMSG,                /* MLIDCFG_Signature        */
  01,                                       /* MLIDCFG_MajorVersion     */
  21,                                       /* MLIDCFG_MinorVersion     */
  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},     /* MLIDCFG_NodeAddress      */
  ModeFlags,                                /* MLIDCFG_ModeFlags        */
  0x0000,                                   /* MLIDCFG_BoardNumber      */
  0x0000,                                   /* MLIDCFG_BoardInstance    */
  0x000005F0,                               /* MLIDCFG_MaxFrameSize     */
  0x000005E2,                               /* MLIDCFG_BestDataSize     */
  0x000005E2,                               /* MLIDCFG_WorstDataSize    */
  NULL,                                     /* MLIDCFG_CardName         */
  NICShortName,                             /* MLIDCFG_ShortName        */
  NULL,                                     /* MLIDCFG_FrameTypeString  */
  0x0000,                                   /* MLIDCFG_Reserved0        */
  0x0000,                                   /* MLIDCFG_FrameID          */
  0x0001,                                   /* MLIDCFG_TransportTime    */
  NULL,                                     /* MLIDCFG_SourceRouting    */
  10,                                       /* MLIDCFG_LineSpeed        */
  0x0000,                                   /* MLIDCFG_LookAheadSize    */
  2,                                        /* MLIDCFG_SGCount          */
  0,                                        /* MLIDCFG_Reserved1        */
  0,                                        /* MLIDCFG_PrioritySup      */
  NULL,                                     /* MLIDCFG_Reserved2        */
  0x00,                                     /* MLIDCFG_DriverMajorVer   */
  0,                                          /* MLIDCFG_DriverMinorVer   */
  MFlags,                                   /* MLIDCFG_Flags            */
  10,                                       /* MLIDCFG_SendRetries      */
  NULL,                                     /* MLIDCFG_DriverLink       */
  SharingFlags,                             /* MLIDCFG_SharingFlags     */
  -1,                                        /* MLIDCFG_Slot             */
  0x0300,                                   /* MLIDCFG_IOPort0          */
  32,                                       /* MLIDCFG_IORange0         */
  0x0000,                                   /* MLIDCFG_IOPort1          */
  0,                                        /* MLIDCFG_IORange1         */
  NULL,                                     /* MLIDCFG_MemoryAddress0   */
  0x0000,                                   /* MLIDCFG_MemorySize0      */
  NULL,                                     /* MLIDCFG_MemoryAddress1   */
  0x0000,                                   /* MLIDCFG_MemorySize1      */

  0x03,                                     /* MLIDCFG_Interrupt0       */
  0xff,                                     /* MLIDCFG_Interrupt1       */
  0x05,                                     /* MLIDCFG_DMALine0         */
  0xff,                                     /* MLIDCFG_DMALine1         */

  NULL,                                     /* MLIDCFG_ResourceTag      */
  NULL,                                     /* MLIDCFG_Config           */
  NULL,                                     /* MLIDCFG_CommandString    */
  {0,0,0,0,0,0,
   0,0,0,0,0,0,
   0,0,0,0,0,0},                            /* MLIDCFG_LogicalName      */

  0x00000000,                               /* MLIDCFG_LinearMemory0    */
  0x00000000,                               /* MLIDCFG_LinearMemory1    */
  0x0000,                                   /* MLIDCFG_ChannelNumber    */
  NULL,                                     /* MLIDCFG_DBusTag          */
  0x01,                                     /* MLIDCFG_DIOConfigMajorVer */
  0x00,                                     /* MLIDCFG_DIOConfigMinorVer */
};   /* End DriverConfigTemplate */

/* Driver Parameter Block. This information gives the MSM/TSM the            */
/* information it needs to manage this HSM.                                 */

/* AYD used to align for test
UINT8 DriverParameterBlockSignature[] = {'D','P','B','S','0','0'}; */

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


/* Parameter Option Description Structures */

/* PCI */
struct
{
   UINT32   OptionCount;
   UINT32   Slot[8];
} SlotsWithMyBoard = {0,{0,0,0,0, 0,0,0,0}};

DRIVER_OPTION SlotOption =
         { NULL, NULL, (PARAMETER_OPTIONS *)&SlotsWithMyBoard, 0, 0, SLOTPARAM,
               REQUIREDPARAM | ENUMPARAM, };
DRIVER_OPTION FullDuplexOption =
         { NULL, CNEAMD_FullDuplex, NULL, 0, 0, CUSTOMPARAM, KEYWORDPARAM };

/* LANCE, PCnetISA */

struct
{
   UINT32   OptionCount;
   UINT32   UNumOptVal[12];
} IoOptionList = {12, {0x300,0x320,0x340,0x360,0x200,0x220,0x240,0x260,0x280,0x2A0,0x2C0,0x2E0}};

struct
{
   UINT32   OptionCount;
   UINT32   UNumOptVal[8];
} IntOptionList = {8, {3, 4, 5, 9, 10, 11, 12, 15}};

struct
{
   UINT32   OptionCount;
   UINT32   UNumOptVal[4];
} DMAOptionList = {4, {5, 6, 7, 3}};

DRIVER_OPTION IoOption =
         { NULL, NULL, (PARAMETER_OPTIONS *)&IoOptionList, 0, 0x300, PORTPARAM,
            REQUIREDPARAM | DEFAULTPRESENT | ENUMPARAM, };
DRIVER_OPTION IntOption =
         { &IoOption, NULL, (PARAMETER_OPTIONS *)&IntOptionList, 0, 0x3, INTPARAM,
            REQUIREDPARAM | DEFAULTPRESENT | ENUMPARAM, };
DRIVER_OPTION DMAOption =
         { &IntOption, NULL, (PARAMETER_OPTIONS *)&DMAOptionList, 0, 0x5, DMAPARAM,
               REQUIREDPARAM | DEFAULTPRESENT | ENUMPARAM, };
DRIVER_OPTION ISAOption =
         { NULL, CNEAMD_ISA, NULL, 0, 0,   CUSTOMPARAM, KEYWORDPARAM };

static   UINT8   BroadcastAddress[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverMulticastChange(
*                                 DRIVER_DATA         *driverData,
*                                 PONFIG_TABLE      configTable,
*                                 GROUP_ADDR_LIST_NODE   *mcTable,
*                                 UINT32            numEntries,
*                                 UINT32            functionalTable)
*
*   Description:
*
*      This function passes a copy of the current multicast table
*      so that the HSM can update the adapters multicast hash table.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's Default Configuration Table.
*      mcTable -         Pointer to multicast table.
*      numEntries -      Number of valid entries in multicast table.
*      functionalTable -   Functional Address(not used).
*
*   Values returned:
*
*                                                                       *
************************************************************************/

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

   functionalTable = functionalTable;

   /* Clear hash table */
  /* AYD 08-01-95 to zero all 8 bytes */

   /* AYD 11-15-96 */
   if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
   {
        *(UINT32 *)&(driverData->PCI_InitializationBlockPtr->PCI_LogicalAddressFilter[0]) = 0;
        *(UINT32 *)&(driverData->PCI_InitializationBlockPtr->PCI_LogicalAddressFilter[4]) = 0;
   }
   else
   {
        *(UINT32 *)&(driverData->LogicalAddressFilter[0]) = 0;
        *(UINT32 *)&(driverData->LogicalAddressFilter[4]) = 0;
   }

   /* Calculate hash bit for each multicast address */
   while(numEntries) {
      SetMulticast(driverData, mcTable);
      mcTable++;
      numEntries--;
      }

   /* Reset adapter so that it can accept new hash table */
   DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
   driverData->AdapterResetCount--;
   return ODISTAT_SUCCESSFUL;
}

/***********************************************************************
*
*
*   Name:
*      void   SetMulticast(
*                        DRIVER_DATA         *driverData,
*                        GROUP_ADDR_LIST_NODE   *mcTableEntry)
*
*   Description:
*
*      This function sets the adapter hash table according to the
*      multicast address passed in. The bit set in the hash table
*      is calculated the same way the hardware calculates it using
*      a CRC algorithm.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      mcTableEntry -      Pointer to multicast address.
*
*   Values returned:
*
*
************************************************************************/

#define   POLYNOMIAL      0x4C11DB6

void   SetMulticast(
            DRIVER_DATA         *driverData,
        GROUP_ADDR_LIST_NODE *mcTableEntry)
{

   UINT32      CRC = 0xffffffff;                  /* CRC accumulator */
   UINT32      NodeAddr, CRC31;
   int       WordCount, BitCount;
   UINT32      HashIndex;
   UINT8         CRCLow, CRCHigh;

  for(WordCount = 0; WordCount < 6; WordCount += 2)
  {
      NodeAddr = GET_UINT16(&mcTableEntry->GRP_ADDR.nodeAddress[WordCount]);
    for(BitCount = 16; BitCount; BitCount--)
    {
      CRC31 = ((CRC >> 31) ^ NodeAddr) & 1;   /* Get Control bit */
         CRC = CRC << 1;
         if (CRC31)
            CRC = CRC ^ POLYNOMIAL;            /* XOR if Control bit == 1 */
         CRC = CRC | CRC31;                  /* Put control bit in CRC0 */
         NodeAddr = NodeAddr >> 1;            /* Rotate word address right */
    }
  }

  CRCLow = (UINT8)CRC;
  CRC >>= 8;
  CRCHigh = (UINT8)CRC;

   /* Formation of CRC complete, CRCLow contains the reversed hash code.   */
   /* Reverse the order of the bits in bits 0-7 of CRC accumulator into      */
   /* bits 8-15.                                                             */

  for(BitCount = 10; BitCount; BitCount--)
  {
      CRCHigh >>= 1;
      CRCHigh |= (CRCLow & 0x80);
      CRCLow <<= 1;
  }

   /* CRCHigh now contains the hash code */

   HashIndex = CRCHigh >> 3;                  /* Hash Index = Hash Code / 8 */
   CRCLow = 1 << ((UINT8)CRCHigh & 0x07);      /* CRC bit = 1 << Hash Code */

   /* Set Hash Filter */

   /* AYD 11-15-96 */
   if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
      driverData->PCI_InitializationBlockPtr->PCI_LogicalAddressFilter[HashIndex] |= CRCLow;
   else
      driverData->LogicalAddressFilter[HashIndex] |= CRCLow;

   return;
}

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverPromiscuousChange(
*                                 DRIVER_DATA         *driverData,
*                                 CONFIG_TABLE      *configTable,
*                                 UINT32            promiscuousMode) {
*
*   Description:
*
*      This function enables/disables the adapters promiscuous mode.
*      If promiscuous mode is enabled, we will also pass bad packets
*      up to the TSM.
*
*   Parameters in:
*
*   driverData -      Pointer to HSM's Adapter Data Space.
*   configTable -     Pointer to HSM's Default Configuration Table.
*      promsicuousMode -   PROM_STATE_OFF to disable promiscuous mode.
*                     PROM_STATE_ON  to enable  promiscuous mode.
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void   DriverPromiscuousChange(
               DRIVER_DATA         *driverData,
               CONFIG_TABLE      *configTable,
          UINT32          promiscuousMode)
{
   /* AYD 11-15-96 */
   if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
   {
      if (promiscuousMode)
         PUT_UINT16(&driverData->PCI_InitializationBlockPtr->Mode, 0x8000);
      else
         PUT_UINT16(&driverData->PCI_InitializationBlockPtr->Mode, 0x0000);
   }
   else
   {
      if (promiscuousMode)
         PUT_UINT16(&driverData->InitializationBlock, 0x8000);
      else
         PUT_UINT16(&driverData->InitializationBlock, 0x0000);
   }
   /* Reset Adapter to enable/disable promiscuous mode */
   DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
   driverData->AdapterResetCount--;
   return;

}

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverSend(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable,
*               TCB             *tcb,
*               UINT32          packetSize,
*               void            *physTcb) {
*
*   Description:
*
*      This function sends a packet described in the TCB to the
*      Am7990 LANCE adapter.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's Default Configuration Table.
*      tcb -               Pointer to the Transmit Control Block.
*      packetSize -      Padded, evenized size of packet.
*                        (The size the adapter must put on the wire)
*      physTcb -         Physical pointer to TCB(not used).
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void   DriverSendLANCE(
               DRIVER_DATA      *driverData,
               CONFIG_TABLE   *configTable,
          TCB           *tcb,
          UINT32        packetSize,
          void          *physTcb)
{

  int              i;
  void             *txBuffer;
  int              fragCount;
  FRAGMENTSTRUCT      *fragStruct;
  ECB                     *originalECBPtr;

  physTcb = physTcb;

  i = driverData->TxNextToSend;
  driverData->TCBTable[i] = tcb;

    /* Set up transmit descriptor size field */
  PUT_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize,
                                                -(UINT16)packetSize);

  /* Copy TCB Media Header to the transmit buffer */
  txBuffer = (void *)driverData->TxBufferTable[i];
  /* AYD */
  MovFastToBus(0, 0, txBuffer, &tcb->TCB_MediaHeader, tcb->TCB_MediaHeaderLen);
  txBuffer = (void *)((UINT8 *)txBuffer + tcb->TCB_MediaHeaderLen);

   /* Copy ECB fragments to the transmit buffer */
   /* AYD 10-11-95 To use the linear addresses to move a data*/
   /* AYD 01-23-98 Because the CMSMTCBPhysToLogFrags API changed the following 3 lines changed */

   originalECBPtr = CMSMTCBPhysToLogFrags(tcb);
   fragCount  = originalECBPtr->ECB_FragmentCount;
   fragStruct = originalECBPtr->ECB_Fragment;

   while (fragCount)
     {
       MovFastToBus(0, 0, (UINT8 *)txBuffer,
                  (UINT8 *)fragStruct->FragmentAddress,
                  fragStruct->FragmentLength);
      txBuffer = (void *)((UINT8 *)txBuffer + fragStruct->FragmentLength);
      fragStruct++;
      fragCount--;
   }

   /* Setting T_OWN bit will flag adapter to transmit this packet */
   driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr |= T_OWN;

   /* Send TDMD command so that adapter reads transmit descriptor */
   Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, TDMD | INEA);

   /* Stamp descriptor for timeout detection */
   driverData->TxStartTime[i] = CMSMGetCurrentTime();
   i= (i+1) & (TX_BUFFERS - 1);
   driverData->TxNextToSend = i;
  CEtherTSMFastSendComplete(driverData, tcb, 0);

}   /* End DriverSendLANCE */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverSend ISA or PCI(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable,
*               TCB             *tcb,
*               UINT32          packetSize,
*               void            *physTcb) {
*
*   Description:
*
*      This function sends a packet to the Am79C960 PCnetISA adapter.
*      The TCB is guaranteed to have physically addressed buffers
*      below 16 megabytes. The HSM uses this function instead of
*      DriverSend since the Am79C960 PCnetISA, PCnetPCI chip can
*      accept transmit descriptors of any size, allowing us to let the adapter
*      gather the fragments, thus preventing a double copy.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's Default Configuration Table.
*      tcb -               Pointer to the Transmit Control Block.
*      packetSize -      Padded, evenized size of packet.
*                        (The size the adapter must put on the wire)
*      physTcb -         Physical pointer to TCB(not used).
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void   DriverSendISA(
            DRIVER_DATA      *driverData,
            CONFIG_TABLE   *configTable,
            TCB           *tcb,
            UINT32        packetSize,
            void          *physTcb)
{
   int               i, firstIndex;
   UINT32            fragCount;
   FRAGMENTSTRUCT      *fragStruct;
   UINT16            paddedValue, lastSize;

   configTable = configTable;
   physTcb = physTcb;
   packetSize = packetSize;

   /* Update Tx Over ECB statistic counter */
   driverData->TxECBsOver16Meg += tcb->TCB_DriverWS[1];

   /* paddedValue will be added to the last descriptor if the TSM has
      evenized the packet */
   paddedValue = 0;
   if ( (packetSize != 60) && (packetSize != tcb->TCB_DataLen) )
      paddedValue = 1;

   i = firstIndex = driverData->TxNextToSend;
   driverData->TCBTable[i] = tcb;
   fragCount = tcb->TCB_FragBlockPtr->TCB_FragmentCount;
   fragStruct = &tcb->TCB_FragBlockPtr->TCB_Fragment;

/*#ifdef DEBUG
       NiosDprintf(FRAGMENT_COUNT, fragCount);
#endif */

   if (tcb->TCB_MediaHeaderLen)
   {
         /* Point first descriptor to TCB media header */
     PUT_UINT32(&driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAddr,
                tcb->TCB_DriverWS[2]);
     PUT_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize,
                        -(UINT16)(tcb->TCB_MediaHeaderLen));
      driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr &= 0xFC;
   }
   else
   {
         /* No TCB media header. Point first descriptor to first fragment */
     PUT_UINT32(&driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAddr,
                        (UINT32)fragStruct->FragmentAddress);
     PUT_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr &= 0xFC;
      fragStruct++;
      fragCount--;
   }

   /* Point next desriptors to the rest of the fragments */
   while(fragCount)
   {
    if (fragStruct->FragmentLength)
    {
      i = (i + 1) & (TX_BUFFERS_FRAG - 1);
        PUT_UINT32(&driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAddr,
                        (UINT32)fragStruct->FragmentAddress);
        PUT_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr &= 0xFC;

    }
    fragStruct++;
    fragCount--;
   }

   /* Add possible evenization padding, set last descriptor to T_ENP and
      first descriptor T_STP.         */
   /* AYD 02-14-96 */
   lastSize = GET_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize);

   lastSize -= paddedValue;

   PUT_UINT16(&driverData->TxDescriptorTablePtr[i].TxDescSize, lastSize);

   driverData->TxDescriptorTablePtr[driverData->TxNextToSend].TxDescAddr.TxAttr.Attr &= 0xFE;
   driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr |= T_ENP;
   driverData->TxDescriptorTablePtr[driverData->TxNextToSend].TxDescAddr.TxAttr.Attr |= T_STP;
   driverData->TxLastDesc[driverData->TxNextToSend] = i;
   i = (i+1) & (TX_BUFFERS_FRAG - 1);
   driverData->TxNextToSend = i;

   /* Set adapter ownership bit(T_OWN) starting with the last descriptor
      since setting the bit on the first descriptor will start
      transmission. */
   do
   {
      i = (i - 1) & (TX_BUFFERS_FRAG - 1);
      /* AYD 02-14-96 */
      driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr |= T_OWN;
   }
   while(i != firstIndex);

   Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, TDMD | INEA);
   driverData->TxStartTime[i] = CMSMGetCurrentTime();
   return;

}   /* End DriverSendISA */

void   DriverSendPCI(
            DRIVER_DATA      *driverData,
            CONFIG_TABLE   *configTable,
            TCB           *tcb,
            UINT32        packetSize,
            void          *physTcb)
{
   int               i, firstIndex;
   UINT32            fragCount;
   FRAGMENTSTRUCT      *fragStruct;
   UINT16            paddedValue, lastSize;

   configTable = configTable;
   physTcb = physTcb;
   packetSize = packetSize;


   /* paddedValue will be added to the last descriptor if the TSM has
      evenized the packet */
   paddedValue = 0;
   if ( (packetSize != 60) && (packetSize != tcb->TCB_DataLen) )
      paddedValue = 1;

   i = firstIndex = driverData->TxNextToSend;
   driverData->TCBTable[i] = tcb;
   fragCount = tcb->TCB_FragBlockPtr->TCB_FragmentCount;
   fragStruct = &tcb->TCB_FragBlockPtr->TCB_Fragment;

/* #ifdef DEBUG
       NiosDprintf(FRAGMENT_COUNT, fragCount);
#endif*/
/*   if(fragCount == 4)
      NiosBreak(); */

   if (tcb->TCB_MediaHeaderLen)
   {
         /* Point first descriptor to TCB media header */
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxAddr_32,
                tcb->TCB_DriverWS[2]);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
                        -(UINT16)(tcb->TCB_MediaHeaderLen));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32 &= MASK_ENP_STP;
   }
   else
   {
         /* No TCB media header. Point first descriptor to first fragment */
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxAddr_32,
                        (UINT32)fragStruct->FragmentAddress);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32 &= MASK_ENP_STP;
      fragStruct++;
      fragCount--;
   }

   /* Point next desriptors to the rest of the fragments */
   while(fragCount)
   {
    if (fragStruct->FragmentLength)
    {
      i = (i + 1) & (TX_BUFFERS_FRAG - 1);
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxAddr_32,
                        (UINT32)fragStruct->FragmentAddress);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32 &= MASK_ENP_STP;

    }
    fragStruct++;
    fragCount--;
   }

   /* Add possible evenization padding, set last descriptor to T_ENP and
      first descriptor T_STP.         */
   /* AYD 02-14-96 */
   lastSize = GET_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.BufferByteCnt);

   lastSize -= paddedValue;

   PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST2.BufferByteCnt, lastSize);


   driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToSend].U.ST2.TxDescStatus_32 &= MASK_ENP;
   driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32 |= T_ENP_32;
   driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToSend].U.ST2.TxDescStatus_32 |= T_STP_32;

   driverData->TxLastDesc[driverData->TxNextToSend] = i;
   i = (i+1) & (TX_BUFFERS_FRAG - 1);
   driverData->TxNextToSend = i;

   /* Set adapter ownership bit(T_OWN) starting with the last descriptor
      since setting the bit on the first descriptor will start
      transmission. */
   do
   {
      i = (i - 1) & (TX_BUFFERS_FRAG - 1);
      /* AYD 02-14-96 */
      driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32 |= T_OWN_32;
   }
   while(i != firstIndex);

   Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, TDMD | INEA);
   driverData->TxStartTime[i] = CMSMGetCurrentTime();
   return;

}   /* End DriverSendPCI */

void   DriverSendPCI_II(
            DRIVER_DATA      *driverData,
            CONFIG_TABLE   *configTable,
            TCB           *tcb,
            UINT32        packetSize,
            void          *physTcb)
{
   int               i, firstIndex;
   UINT32            fragCount;
   FRAGMENTSTRUCT      *fragStruct;
   UINT16            paddedValue, lastSize;

   configTable = configTable;
   physTcb = physTcb;
   packetSize = packetSize;

   /* paddedValue will be added to the last descriptor if the TSM has
      evenized the packet */

   paddedValue = 0;
   if ( (packetSize != 60) && (packetSize != tcb->TCB_DataLen) )
      paddedValue = 1;

   i = firstIndex = driverData->TxNextToSend;
   driverData->TCBTable[i] = tcb;
   fragCount = tcb->TCB_FragBlockPtr->TCB_FragmentCount;
   fragStruct = &tcb->TCB_FragBlockPtr->TCB_Fragment;

/* #ifdef DEBUG
       NiosDprintf(FRAGMENT_COUNT, fragCount);
#endif */


   if (tcb->TCB_MediaHeaderLen)
   {
         /* Point first descriptor to TCB media header */
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxAddr_32_II,
                tcb->TCB_DriverWS[2]);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II,
                        -(UINT16)(tcb->TCB_MediaHeaderLen));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II &= MASK_ENP_STP;
   }
   else
   {
         /* No TCB media header. Point first descriptor to first fragment */
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxAddr_32_II,
                        (UINT32)fragStruct->FragmentAddress);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II &= MASK_ENP_STP;
      fragStruct++;
      fragCount--;
   }

   /* Point next desriptors to the rest of the fragments */
   while(fragCount)
   {
    if (fragStruct->FragmentLength)
    {
      i = (i + 1) & (TX_BUFFERS_FRAG - 1);
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxAddr_32_II,
                        (UINT32)fragStruct->FragmentAddress);
      PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II,
                        -(UINT16)(fragStruct->FragmentLength));
      driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II &= MASK_ENP_STP;

    }
    fragStruct++;
    fragCount--;
   }

   /* Add possible evenization padding, set last descriptor to T_ENP_32 and
      first descriptor T_STP_32.         */
   /* AYD 02-14-96 */
   lastSize = GET_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II);

   lastSize -= paddedValue;

   PUT_UINT16(&driverData->PCI_TxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II, lastSize);


   driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToSend].U.ST3.TxDescStatus_32_II &= MASK_ENP;
   driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II |= T_ENP_32;
   driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToSend].U.ST3.TxDescStatus_32_II |= T_STP_32;

   driverData->TxLastDesc[driverData->TxNextToSend] = i;
   i = (i+1) & (TX_BUFFERS_FRAG - 1);
   driverData->TxNextToSend = i;

   /* Set adapter ownership bit(T_OWN_32) starting with the last descriptor
      since setting the bit on the first descriptor will start
      transmission. */
   do
   {
      i = (i - 1) & (TX_BUFFERS_FRAG - 1);
      /* AYD 02-14-96 */
      driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II |= T_OWN_32;
   }
   while(i != firstIndex);

   Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, TDMD | INEA);
   driverData->TxStartTime[i] = CMSMGetCurrentTime();
   return;

}   /* End DriverSendPCI_II */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverISR(
*                        DRIVER_DATA         *driverData)
*
*   Description:
*
*      This function handles packet reception, transmit complete and
*      error handling.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void   DriverISRISA(DRIVER_DATA   *driverData) {

  CONFIG_TABLE         *configTable;
  UINT16            interruptStatus;
  int               i;
  /* UINT8               *TempRCB; */
  /* , bufferCount; */
  UINT8             txStatus;
  UINT8             rxDescStatus;
  UINT32            receiveStatus=0;
  RCB               *rcb;
  UINT32            RxPacketSize;

  configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;

  interruptStatus = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
  Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, interruptStatus);


   /* Reset flag set by timer. Reset adapter and get out */
  if (driverData->ResetFlag)
  {
      driverData->ResetFlag = 0;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return;
  }

   /* Error Interrupt Handler */
  if (interruptStatus & ERR)
      if ( DriverISRErrorHandler(driverData, configTable, interruptStatus) )
         return;

   /* Receive Interrupt Handler */
  if (interruptStatus & RINT)
  {
     /* If Shutdown bit set just exit */
     if( DADSP_TO_CMSMADSP(driverData)->CMSMStatusFlags & SHUTDOWN )
         return;

    while (driverData->NeedRCBCount != RX_BUFFERS)  /*AYD != */
    {
      i = driverData->RxNextToReturn;
      rxDescStatus = driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAttr.Attr;
      if (rxDescStatus & R_OWN)
               break;

      /* If MISS set, reset adapter to prevent reading garbage */
      /* AYD 09-17-96 */
      /* if ( In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP) & MISS)
      {
            driverData->PacketRxOverflowCount++;
            driverData->PacketRxMiscErrorCount++;
            DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
            return;
      }                 */
      rcb = driverData->RCBTable[i];

      /* AYD 04-02-96 */
      /* if( ((UINT32)rcb->RCBFragStruct.FragmentAddress & 0x00FFFFFF)
         != (driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAddr & 0x00FFFFFF) )
         EnterDebugger(); */

      if (rxDescStatus & R_STP)
      {
        /* This is the start of the packet  */
        if ( (rxDescStatus & R_ENP) == 0)
        {
          rxDescStatus |= (R_ERR|R_CRC);
         /* AYD 03-18-96 Changed this code to handel correctly large packets */
/*
          End of packet bit not set. Search thru descriptors for it
          bufferCount = RX_BUFFERS;
          while (bufferCount--)
          {
           i++;
           i &= (RX_BUFFERS - 1);

              rxDescStatus =
               driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAttr.Attr;
              if (rxDescStatus & R_ENP)
                break;
          }
          if (bufferCount == 0)
          {
            Never found end of packet descriptor. Reset time.
            NiosDprintf(NEVER_FOUND_END_OF_PACKET);
            DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
            return;
          }
 */
        }

        /* Found last descriptor. Check its error status */
        if (rxDescStatus & R_ERR)
        {
          /* Receive Error Handler */
          receiveStatus = 0;
          if (rxDescStatus & R_FRM)
          {
            driverData->RxAbortFrameAlignment++;
            driverData->PacketRxMiscErrorCount++;
            receiveStatus |= 2;
          }
          if (rxDescStatus & R_OFL)
            driverData->PacketRxOverflowCount++;
          if (rxDescStatus & R_CRC)
          {
            driverData->ChecksumErrorCount++;
            receiveStatus |= 1;
          }
          if (rxDescStatus & R_BUF)
            driverData->PacketRxOverflowCount++;
        }
        if ( ( (rxDescStatus & R_ERR) &&
           ( (GET_UINT16(&driverData->InitializationBlock) & 0x8000) ) )
         || ((rxDescStatus & R_ERR) == 0) )
        {
          /* Either good packet or bad packet with promiscuous mode enabled */
          driverData->NeedRCBCount++;
          RxPacketSize = (UINT32)GET_UINT16(&driverData->RxDescriptorTablePtr[i].RxDescMessageCount);

          RxPacketSize -= 4;     /* Do not include CRC 4 bytes */

          /* AYD 04-08-96 */
          driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAddr = 0;

          /* TempRCB = (UINT8 *)((RX_DESC *)driverData->RxDescriptorTablePtr);
          for( j=0; j < 8*16; j++, TempRCB++ )
             driverData->RxDescrTempBuffer[j] = *TempRCB; */

          /* TempRCB = (UINT8 *)((RCB *)rcb);
          for( j=0; j < 1590; j++, TempRCB++ )
             driverData->TempBuffer[j] = *TempRCB; */

          rcb = CEtherTSMFastProcessGetRCB(driverData,
                                           rcb,
                                           RxPacketSize,
                                           receiveStatus,
                                           driverData->CommonMaximumSize);
          if (rcb)
          {
            /* TSM gave us an RCB back. */
            driverData->NeedRCBCount--;
            /* AYD 08-29-97 */
            /*if ( ((ECB *)rcb)->ECB_Status == SPARE_ECB_STATUS )
              driverData->ECBsOver16Meg++;*/
          }
        }
      }
      else
      {
        /* Start bit not set. */
        if ( (rxDescStatus & R_ENP) == 0 )
        {
          /* Neither start nor stop bit set. This should never happen */
          /* NiosDprintf(NO_START_NO_STOP_BIT); */
          DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
          return;
        }
        driverData->ECBOverflowCount++;
      }

      /* Finish receive by placing new(or old) RCB back into list */
      /* AYD 03-28-95*/
      i = driverData->RxNextToReturn;
      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToReturn = i;

      if (rcb)
      {
          /* AYD 04-09-96 */
         /* for( j=0; j < 16; j++ )
            if( ((UINT32)rcb->RCBFragStruct.FragmentAddress & 0x00FFFFFF)
               == (driverData->RxDescriptorTablePtr[j].RxDescAddr.RxAddr & 0x00FFFFFF) )
                  EnterDebugger(); */

        i = driverData->RxNextToAllocate;
        driverData->RCBTable[i] = rcb;
         PUT_UINT32(&driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAddr,
          (UINT32)rcb->RCBFragStruct.FragmentAddress | (R_OWN << 24) );

         PUT_UINT16(&driverData->RxDescriptorTablePtr[i].RxDescBufferCount,
               -((UINT16)driverData->CommonMaximumSize));

        i++;
        i &= (RX_BUFFERS - 1);
        driverData->RxNextToAllocate = i;
      }

      if (driverData->NeedRCBCount != RX_BUFFERS) /* AYD != */
      {
        interruptStatus |= In16(configTable->MLIDCFG_DBusTag,
                        (void *)driverData->RDP);
        Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
            interruptStatus);
        if (interruptStatus & ERR)
          if ( DriverISRErrorHandler(driverData, configTable,
                            interruptStatus) )
            return;
      }

    } /* while NeedRCBCount */

  } /* interruptStatus & RINT */

   /* Attempt to allocate RCBs if we need some */

  while (driverData->NeedRCBCount)
  {
      rcb = CMSMAllocateRCB(driverData, driverData->CommonMaximumSize, NULL);
      if (rcb == NULL)
         break;

      driverData->NeedRCBCount--;
      /*if ( ((ECB *)rcb)->ECB_Status == SPARE_ECB_STATUS )
         driverData->ECBsOver16Meg++;*/

      /* AYD 04-09-96 */
      /* for( j=0; j < 16; j++ )
            if( ((UINT32)rcb->RCBFragStruct.FragmentAddress & 0x00FFFFFF)
               == (driverData->RxDescriptorTablePtr[j].RxDescAddr.RxAddr & 0x00FFFFFF) )
                  EnterDebugger(); */

      i = driverData->RxNextToAllocate;
      driverData->RCBTable[i] = rcb;
       PUT_UINT32(&driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAddr,
                  (UINT32)rcb->RCBFragStruct.FragmentAddress | (R_OWN << 24));

       PUT_UINT16(&driverData->RxDescriptorTablePtr[i].RxDescBufferCount,
               -((UINT16)driverData->CommonMaximumSize));

      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToAllocate = i;
  }
   /* AYD 09-25-95 Changed TX_BUFFERS to TX_BUFFERS_FRAG/16 for PCnet */
   /* Transmit Interrupt Handler */
  if (interruptStatus & TINT)
   if (driverData->PCnetFlag)
   {
      i = driverData->TxLastDesc[driverData->TxNextToReturn];
      txStatus = driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr;
      while ( (DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount != TX_BUFFERS_FRAG/16)
              && ( (txStatus & T_OWN) == 0))
      {
        /* AYD 03-29-96 Check if this is an end of the TCB list */
        if( driverData->TCBTable[driverData->TxNextToReturn] == NULL )
              break;

        if ((txStatus & T_ERR) == 0)
        {
              if (txStatus & T_DEF)
                 driverData->TxOKButDeferred++;
        }
        else
        {
            if (DriverISRTxErrorHandler(driverData, configTable))
               return;
        }

        driverData->TxStartTime[driverData->TxNextToReturn] = 0;
        DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount++;
        CEtherTSMFastSendComplete(driverData,
                    driverData->TCBTable[driverData->TxNextToReturn], 0);
        i = (i+1) & (TX_BUFFERS_FRAG - 1); /* AYD 03-31-95*/
        driverData->TxNextToReturn = i;
        i = driverData->TxLastDesc[i];
        txStatus = driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr;

      }
   }
   else      /* Am7990 LANCE chipset */
   {
         i = driverData->TxNextToReturn;
         txStatus = driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr;
         while ( (DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount != TX_BUFFERS)
              && ( (txStatus & T_OWN) == 0))
         {
      /* AYD 09-17-96 */
            if ((txStatus & T_ERR) == 0)
            {
               if (txStatus & T_DEF)
                  driverData->TxOKButDeferred++;
            }
            else
            {
               if (DriverISRTxErrorHandler(driverData, configTable))
                  return;
            }

            driverData->TxStartTime[i] = 0;
            DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount++;
            i = (i+1) & (TX_BUFFERS - 1);
            driverData->TxNextToReturn = i;
            txStatus = driverData->TxDescriptorTablePtr[i].TxDescAddr.TxAttr.Attr;
         }
   }
   return;

}   /* End DriverISRISA */

void   DriverISRPCI(DRIVER_DATA   *driverData) {

  CONFIG_TABLE         *configTable;
  UINT16            interruptStatus;
  int               i;
  UINT16            rxDescStatus_32, txDescStatus_32;
  UINT32            receiveStatus=0;
  RCB               *rcb;
  UINT32            RxPacketSize;

  configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;

  interruptStatus = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
  Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, interruptStatus);


   /* Reset flag set by timer. Reset adapter and get out */
  if (driverData->ResetFlag)
  {
      driverData->ResetFlag = 0;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return;
  }

   /* Error Interrupt Handler */
  if (interruptStatus & ERR)
      if ( DriverISRErrorHandler(driverData, configTable, interruptStatus) )
         return;

   /* Receive Interrupt Handler */
  if (interruptStatus & RINT)
  {
     /* If Shutdown bit set just exit */
     if( DADSP_TO_CMSMADSP(driverData)->CMSMStatusFlags & SHUTDOWN )
         return;

    while (driverData->NeedRCBCount != RX_BUFFERS)  /*AYD != */
    {
     i = driverData->RxNextToReturn;
     rxDescStatus_32 = driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxDescStatus_32;

     if (rxDescStatus_32 & R_OWN_32)
        break;

/* #ifdef DEBUG
            NiosDprintf(RX_DESCR_STATUS, rxDescStatus);
#endif */

      rcb = driverData->RCBTable[i];

      if (rxDescStatus_32 & R_STP_32)
      {
        /* This is the start of the packet  */
        if ( (rxDescStatus_32 & R_ENP_32) == 0)
        {
          rxDescStatus_32 |= (R_ERR_32|R_CRC_32);

          /* AYD 03-18-96 Changed this code to handel correctly large packets */
        }

        /* Found last descriptor. Check its error status */
        if (rxDescStatus_32 & R_ERR_32)
        {
          /* Receive Error Handler */
          receiveStatus = 0;
          if (rxDescStatus_32 & R_FRM_32)
          {
            driverData->RxAbortFrameAlignment++;
            driverData->PacketRxMiscErrorCount++;
            receiveStatus |= 2;
          }

          if (rxDescStatus_32 & R_OFL_32)
            driverData->PacketRxOverflowCount++;

          if (rxDescStatus_32 & R_CRC_32)
          {
            driverData->ChecksumErrorCount++;
            receiveStatus |= 1;
          }

          if (rxDescStatus_32 & R_BUF_32)
            driverData->PacketRxOverflowCount++;
        }
        /* AYD 02-14-96 */
        if ( ( (rxDescStatus_32 & R_ERR_32) &&
           ( (GET_UINT16(&driverData->PCI_InitializationBlockPtr->Mode) & 0x8000) ) )
          || ((rxDescStatus_32 & R_ERR_32) == 0) )
        {
          /* Either good packet or bad packet with promiscuous mode enabled */
          driverData->NeedRCBCount++;
          RxPacketSize = (UINT32)GET_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.MessageByteCnt);
          RxPacketSize -= 4;     /* Do not include CRC 4 bytes */

          /* AYD 04-08-96 */
          driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxAddr_32 = 0;
          rcb = CEtherTSMFastProcessGetRCB(driverData,
                                           rcb,
                                           RxPacketSize,
                                           receiveStatus,
                                           driverData->CommonMaximumSize);
          if (rcb)
          {
            /* TSM gave us an RCB back. */
            driverData->NeedRCBCount--;
          }
        }
      }
      else
      {
        /* Start bit not set. */
        if ( (rxDescStatus_32 & R_ENP_32) == 0 )
        {
          /* Neither start nor stop bit set. This should never happen */
/* #ifdef DEBUG
          NiosDprintf(NO_START_NO_STOP_BIT);
#endif */
          DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
          return;
        }
        driverData->ECBOverflowCount++;
      }

      /* Finish receive by placing new(or old) RCB back into list */
      /* AYD 03-28-95*/
      i = driverData->RxNextToReturn;
      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToReturn = i;
      if (rcb)
      {
        i = driverData->RxNextToAllocate;
        driverData->RCBTable[i] = rcb;
        PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxAddr_32,
          (UINT32)rcb->RCBFragStruct.FragmentAddress);

      PUT_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
               -((UINT16)driverData->CommonMaximumSize));

      driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxDescStatus_32 |= R_OWN_32;

        i++;
        i &= (RX_BUFFERS - 1);
        driverData->RxNextToAllocate = i;
      }
      if (driverData->NeedRCBCount != RX_BUFFERS) /* AYD != */
      {
        interruptStatus |= In16(configTable->MLIDCFG_DBusTag,
                        (void *)driverData->RDP);
        Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
            interruptStatus);
        if (interruptStatus & ERR)
           if ( DriverISRErrorHandler(driverData, configTable, interruptStatus) )
               return;
      }

    } /* while NeedRCBCount */

  } /* interruptStatus & RINT */

   /* Attempt to allocate RCBs if we need some */

  while (driverData->NeedRCBCount)
  {
      rcb = CMSMAllocateRCB(driverData, driverData->CommonMaximumSize, NULL);
      if (rcb == NULL)
         break;

      driverData->NeedRCBCount--;

      i = driverData->RxNextToAllocate;
      driverData->RCBTable[i] = rcb;
      PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxAddr_32,
               (UINT32)rcb->RCBFragStruct.FragmentAddress);
      
      PUT_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
            -((UINT16)driverData->CommonMaximumSize));

      driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxDescStatus_32 |= R_OWN_32;

      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToAllocate = i;
  }
   /* AYD 09-25-95 Changed TX_BUFFERS to TX_BUFFERS_FRAG/16 for PCnet */
   /* Transmit Interrupt Handler */
  if (interruptStatus & TINT)
  {
      i = driverData->TxLastDesc[driverData->TxNextToReturn];
      txDescStatus_32 = driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32;

      while ( (DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount != TX_BUFFERS_FRAG/16)
              && ( (txDescStatus_32 & T_OWN_32) == 0))
      {

        /* AYD 03-29-96 Check if this is an end of the TCB list */
        if( driverData->TCBTable[driverData->TxNextToReturn] == NULL )
              break;

      /* AYD 09-17-96 */
        if ((txDescStatus_32 & T_ERR_32) == 0)
        {
              if (txDescStatus_32 & T_DEF_32)
                 driverData->TxOKButDeferred++;
        }
        else
        {
            if (DriverISRTxErrorHandler(driverData, configTable))
               return;
        }

        driverData->TxStartTime[driverData->TxNextToReturn] = 0;
        DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount++;

        CEtherTSMFastSendComplete(driverData,
                    driverData->TCBTable[driverData->TxNextToReturn], 0);
        i = (i+1) & (TX_BUFFERS_FRAG - 1); /* AYD 03-31-95*/
        driverData->TxNextToReturn = i;
        i = driverData->TxLastDesc[i];
        txDescStatus_32 = driverData->PCI_TxDescriptorTablePtr[i].U.ST2.TxDescStatus_32;
      }
  }
  return;

}   /* End DriverISRPCI */

void   DriverISRPCI_II(DRIVER_DATA   *driverData) {

  CONFIG_TABLE         *configTable;
  UINT16            interruptStatus;
  int               i;
  UINT16            rxDescStatus_32, txDescStatus_32;
  UINT32            receiveStatus=0;
  RCB               *rcb;
  UINT32            RxPacketSize;

  configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;

  interruptStatus = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
  Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, interruptStatus);

/*#ifdef DEBUG
            NiosDprintf(ISR, driverData->RDP );
#endif*/

  /* Reset flag set by timer. Reset adapter and get out */
  if (driverData->ResetFlag)
  {
      driverData->ResetFlag = 0;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return;
  }

  /* Error Interrupt Handler */
  if (interruptStatus & ERR)
      if ( DriverISRErrorHandler(driverData, configTable, interruptStatus) )
         return;

  /* Receive Interrupt Handler */
  if (interruptStatus & RINT)
  {
     /* If Shutdown bit set just exit */
     if( DADSP_TO_CMSMADSP(driverData)->CMSMStatusFlags & SHUTDOWN )
         return;

    while (driverData->NeedRCBCount != RX_BUFFERS)  /*AYD != */
    {
      i = driverData->RxNextToReturn;
      rxDescStatus_32 = driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxDescStatus_32_II;

      if (rxDescStatus_32 & R_OWN_32)
            break;

      rcb = driverData->RCBTable[i];

/* #ifdef DEBUG
            NiosDprintf(RX_DESCR_STATUS);
#endif */

/*#ifdef DEBUG
            NiosDprintf(RCB_COUNT,driverData->NeedRCBCount);
#endif*/

      if (rxDescStatus_32 & R_STP_32)
      {
        /* This is the start of the packet  */
        if ( (rxDescStatus_32 & R_ENP_32) == 0)
        {
          rxDescStatus_32 |= (R_ERR_32|R_CRC_32);

          /* AYD 03-18-96 Changed this code to handel correctly large packets */
        }

        /* Found last descriptor. Check its error status */
        if (rxDescStatus_32 & R_ERR_32)
        {
          /* Receive Error Handler */
          receiveStatus = 0;
          if (rxDescStatus_32 & R_FRM_32)
          {
            driverData->RxAbortFrameAlignment++;
            driverData->PacketRxMiscErrorCount++;
            receiveStatus |= 2;
          }

          if (rxDescStatus_32 & R_OFL_32)
            driverData->PacketRxOverflowCount++;

          if (rxDescStatus_32 & R_CRC_32)
          {
            driverData->ChecksumErrorCount++;
            receiveStatus |= 1;
          }

          if (rxDescStatus_32 & R_BUF_32)
            driverData->PacketRxOverflowCount++;
        }
        /* AYD 02-14-96 */
        if ( ( (rxDescStatus_32 & R_ERR_32) &&
           ( (GET_UINT16(&driverData->PCI_InitializationBlockPtr->Mode) & 0x8000) ) )
          || ((rxDescStatus_32 & R_ERR_32) == 0) )
        {
          /* Either good packet or bad packet with promiscuous mode enabled */
          driverData->NeedRCBCount++;
          RxPacketSize = (UINT32)GET_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST3.MessageByteCnt_II);
          RxPacketSize -= 4;     /* Do not include CRC 4 bytes */

          /* AYD 04-08-96 */
          driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxAddr_32_II = 0;
          rcb = CEtherTSMFastProcessGetRCB(driverData,
                                           rcb,
                                           RxPacketSize,
                                           receiveStatus,
                                           driverData->CommonMaximumSize);
          if (rcb)
          {
            /* TSM gave us an RCB back. */
            driverData->NeedRCBCount--;
          }
        }
      }
      else
      {
        /* Start bit not set. */
        if ( (rxDescStatus_32 & R_ENP_32) == 0 )
        {
          /* Neither start nor stop bit set. This should never happen */
/* #ifdef DEBUG
          NiosDprintf(NO_START_NO_STOP_BIT);
#endif */
          DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
          return;
        }
        driverData->ECBOverflowCount++;
      }

      /* Finish receive by placing new(or old) RCB back into list */
      /* AYD 03-28-95*/
      i = driverData->RxNextToReturn;
      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToReturn = i;

      if (rcb)
      {
        i = driverData->RxNextToAllocate;
        driverData->RCBTable[i] = rcb;
        PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxAddr_32_II,
          (UINT32)rcb->RCBFragStruct.FragmentAddress);

        driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxDescStatus_32_II |= R_OWN_32;

        i++;
        i &= (RX_BUFFERS - 1);
        driverData->RxNextToAllocate = i;
      }

      if (driverData->NeedRCBCount != RX_BUFFERS) /* AYD != */
      {
        interruptStatus |= In16(configTable->MLIDCFG_DBusTag,
                        (void *)driverData->RDP);
        Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
            interruptStatus);
        if (interruptStatus & ERR)
          if ( DriverISRErrorHandler(driverData, configTable,
                            interruptStatus) )
            return;
      }

    } /* while NeedRCBCount */

  } /* interruptStatus & RINT */

  /* Attempt to allocate RCBs if we need some */

  while (driverData->NeedRCBCount)
  {
      rcb = CMSMAllocateRCB(driverData, driverData->CommonMaximumSize, NULL);
      if (rcb == NULL)
         break;

/* #ifdef DEBUG
            NiosDprintf(ALLOC);
#endif */

      driverData->NeedRCBCount--;

      i = driverData->RxNextToAllocate;
      driverData->RCBTable[i] = rcb;

      PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxAddr_32_II,
               (UINT32)rcb->RCBFragStruct.FragmentAddress);

      driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxDescStatus_32_II |= R_OWN_32;

      i++;
      i &= (RX_BUFFERS - 1);
      driverData->RxNextToAllocate = i;
  }

   /* AYD 09-25-95 Changed TX_BUFFERS to TX_BUFFERS_FRAG/16 for PCnet */
   /* Transmit Interrupt Handler */
  if (interruptStatus & TINT)
  {
      i = driverData->TxLastDesc[driverData->TxNextToReturn];
      txDescStatus_32 = driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II;

      while ( (DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount != TX_BUFFERS_FRAG/16)
              && ( (txDescStatus_32 & T_OWN_32) == 0))
      {

        /* AYD 03-29-96 Check if this is an end of the TCB list */
        if( driverData->TCBTable[driverData->TxNextToReturn] == NULL )
              break;

      /* AYD 09-17-96 */
        if ((txDescStatus_32 & T_ERR_32) == 0)
        {
              if (txDescStatus_32 & T_DEF_32)
                 driverData->TxOKButDeferred++;
        }
        else
        {
            if (DriverISRTxErrorHandler(driverData, configTable))
               return;
        }

/*#ifdef DEBUG
        NiosDprintf(TRANSMIT_COMPLETE);
#endif*/

        driverData->TxStartTime[driverData->TxNextToReturn] = 0;
        DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount++;

        CEtherTSMFastSendComplete(driverData,
                    driverData->TCBTable[driverData->TxNextToReturn], 0);
        i = (i+1) & (TX_BUFFERS_FRAG - 1); /* AYD 03-31-95*/
        driverData->TxNextToReturn = i;
        i = driverData->TxLastDesc[i];
        txDescStatus_32 = driverData->PCI_TxDescriptorTablePtr[i].U.ST3.TxDescStatus_32_II;
      }
  }


  return;

}   /* End DriverISRPCI_II */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      UINT32   DriverISRErrorHandler(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable,
*               UINT32          interruptStatus)
*
*   Description:
*
*      This function determines the error type, increments the
*      appropriate statistic counters, and resets the adapter
*      on fatal errors.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's Default Configuration Table.
*      interruptStatus -   Adapters interrupt status.
*
*   Values returned:
*      0 -   If non-fatal error(caller can continue normal execution)
*      1 -   If fatal error(DriverReset has been called)
*
*                                                                       *
************************************************************************/

UINT32   DriverISRErrorHandler(
                              DRIVER_DATA         *driverData,
                              CONFIG_TABLE      *configTable,
                    UINT32          interruptStatus)
{

  if (interruptStatus & MISS)
  {
      driverData->PacketRxOverflowCount++;
      driverData->PacketRxMiscErrorCount++;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return   1;
  }
  if (interruptStatus & CERR)
  {
      driverData->HeartbeatError++;
      driverData->PacketRxMiscErrorCount++;
   }
  if (interruptStatus & BABL)
  {
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return   1;
  }
  if (interruptStatus & MERR)
  {
      if (driverData->PCnetFlag)
         return   0;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return 1;
  }
   return   0;

}

/***********************************************************************\
*                                                                       *
*
*   Name:
*      UINT32   DriverISRTxErrorHandler(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable)
*
*   Description:
*
*      This function determines the transmit error type, increments the
*      appropriate statistic counters, and resets the adapter
*      on fatal errors.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's Default Configuration Table.
*
*   Values returned:
*      0 -   If non-fatal error(caller can continue normal execution)
*      1 -   If fatal error(DriverReset has been called)
*
*                                                                       *
************************************************************************/

UINT32   DriverISRTxErrorHandler(
                                 DRIVER_DATA         *driverData,
                      CONFIG_TABLE    *configTable)
{

   UINT16   txError;

   /* AYD 11-18-96 Added switch statement */
   switch ( driverData->PCnetFlag )
   {
      case PCNETPCI:
          txError = GET_UINT16(
            &driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToReturn].U.ST2.TxError);
         break;

      case PCNETPCI_II:
          txError = GET_UINT16(
            &driverData->PCI_TxDescriptorTablePtr[driverData->TxNextToReturn].U.ST3.TxError_II);
         break;

      default:
          txError = GET_UINT16(
            &driverData->TxDescriptorTablePtr[driverData->TxNextToReturn].TxDescStatus);
         break;
   }

  if (txError & T_BUF)
  {
      driverData->TxBufferError++;
      driverData->PacketTxMiscErrorCount++;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return(1);
  }
  if (txError & T_UFL)
  {
      driverData->TxUnderflow++;
      driverData->PacketTxMiscErrorCount++;
      DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
      return(1);
  }
  if (txError & T_LAT)
  {
      driverData->TxAbortLateCollision++;
      driverData->PacketTxMiscErrorCount++;
  }
  if (txError & T_CAR)
  {
      driverData->TxAbortCarrierSense++;
      driverData->PacketTxMiscErrorCount++;
  }
   return   0;
}

/***********************************************************************\
*                                                                       *
*
*   Name:
*      BOOLEAN   DriverDisableInterrupt(
*                        DRIVER_DATA         *driverData
*                        BOOLEAN   Flag )
*
*   Description:
*
*      This function disables the adapter from interrupting the system.
*      It is called before DriverISR or DriverSend is called. We will
*      always return a zero since the MSM interrupt handler will use it
*      to determine if it needs to EOI the PIC and call DriverISR.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*
*   Values returned:
*      0 -   Our adapter initiated the interrupt.
*
*                                                                       *
************************************************************************/

BOOLEAN DriverDisableInterrupt(DRIVER_DATA  *driverData,
                               BOOLEAN Flag)
{
  UINT16   interruptStatus;

  /* NiosBreak(); */

  if( Flag == FALSE)
  {
      Out16(DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard->MLIDCFG_DBusTag,
      (void *)driverData->RDP,
      0);
        /* NiosDprintf(ID); */
      return   TRUE;
  }
  else
  {
   interruptStatus = In16(DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard->MLIDCFG_DBusTag,
                     (void *)driverData->RDP);
   if( interruptStatus & INTR )
   {
        Out16(DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard->MLIDCFG_DBusTag,
      (void *)driverData->RDP,
      0);
        /* NiosDprintf(ID); */
      return   TRUE;
   }
   else
      return FALSE;
  }
}   /* End DriverDisableInterrupt */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverEnableInterrupt(
*                        DRIVER_DATA         *driverData)
*
*   Description:
*
*      This function enables the adapter to interrupt the system.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void  DriverEnableInterrupt(DRIVER_DATA *driverData)
{

   Out16(DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard->MLIDCFG_DBusTag,
      (void *)driverData->RDP,
      INEA);
   /* NiosDprintf(IE); */
   return;
}   /* End DriverEnableInterrupt */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   DriverCallBack(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable)
*
*   Description:
*
*      This function is called by the MSM due to DriverInit calling
*      CMSMScheduleAES. It is called continuously at the
*      interval specified during DriverInit. It is being used to detect
*      transmit timeouts and receive timeouts(on Am7990 only). If transmit
*      timeout, make sure adapter isn't trying to interrupt system. If it
*      isn't, reset the adapter.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's default Configuration Table.
*
*   Values returned:
*
*   Things To Do:
*      1) Should CMSMGetCurrentTime return int?
*
*                                                                       *
************************************************************************/

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

   UINT32    startTime;
   UINT16    Status;
//   UINT16    ioValue;

//   if(driverData->PCnetFlag == PCNETPCI_II)
//   {
//    /* Update link speed value in Config Table */
//    /* Read BCR33, bit #10 should indicate link speed. 0 - 10, 1 - 100 MBPS*/
//    Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, BCR33);
//    ioValue = In16( configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP);
//
//    if (ioValue & 0x0400)
//        configTable->MLIDCFG_LineSpeed = 100;
//    else
//        configTable->MLIDCFG_LineSpeed = 10;
//
//   /* Restore address of CSR0 in RAP */
//   Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR0);
//   }


   startTime = driverData->TxStartTime[driverData->TxNextToReturn];
   if ( startTime )
     {
    if ( (CMSMGetCurrentTime() - startTime) > 36 )
    {
      /* Transmit Timeout */
      /* Send Alert if driverData->BNCFlag == 0 */
       if( driverData->BNCFlag == 0)
         {
            CMSMPrintString(configTable, MSG_TYPE_RUNTIME_WARNING,
                  CNEAMD_CABLEDISC_MSG,
                  NULL ,NULL);
            driverData->BNCFlag++;
         }

     DriverDisableInterrupt(driverData, FALSE);
      /* AYD */
      Status = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
      Out16( configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, Status );

      if ( Status & (ERR | BABL | CERR | MISS | MERR | RINT | TINT | INTR) )
      {
            /* Adapter is interrupting system. Set reset flag and let
               DriverISR reset the adapter. */
            driverData->ResetFlag++;
            DriverEnableInterrupt(driverData);
            return;
      }
    }
    else    /* Transmit in progress, hasn't timed out yet */
        return;
   }
   else
   {
    if (driverData->PCnetFlag)
    /* Am79C960 PCnetISA chip doesn't have receiver lock bug */
    {
       return;
    }
    if (--driverData->CheckRxCount)
       return;
    driverData->CheckRxCount = 16;
    /* Return if TotalRxPacketCount has changed */
    if (driverData->TotalRxPacketCount != driverData->LastTotalRxPacketCount)
    {
      driverData->LastTotalRxPacketCount = driverData->TotalRxPacketCount;
      return;
    }
    else
      driverData->LastTotalRxPacketCount = driverData->TotalRxPacketCount;
   }

   /* Either transmit or receive timeout. Reset adapter. */
   DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);

}   /* End DriverCallBack */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      ODISTAT   DriverReset(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable,
*                        OPERATION_SCOPE   operationScope)
*
*   Description:
*
*      This function resets the adapter.
*
*   Parameters in:
*
*      driverData       -    Pointer to HSM's Adapter Data Space.
*      configTable    -    Pointer to HSM's default Configuration Table.
*      operationScope -   OP_SCOPE_ADAPTER or OP_SCOPE_LOGICAL_BOARD.
*
*   Values returned:
*      ODISTAT_SUCCESSFUL   Adapter Reset successfully
*      ODISTAT_FAIL         Unable to reset adapter(hardware failure)
*
*                                                                       *
************************************************************************/

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

   RCB     *rcb;
   UINT32   rxFragmentPtr;
   UINT32   bufferCount, bufferLength;
   UINT16   ioValue, ioRPA;
   void      *initPtr, *descPtr;
   UINT32   startTime, currentTime;
   int     i;
   void           *bufferPtr;
   TX_DESC        *txDescPtr;
   UINT32         *txBufferPtr;


   if (operationScope == OP_SCOPE_ADAPTER)
   {
      /* AYD 11-15-96 */
      if( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II ) )
      {
       initPtr = &driverData->PCI_InitializationBlock;
         initPtr = (void *)((UINT32)initPtr & 0xfffffffc);  /* Force to DWORD */
         PUT_UINT32(&driverData->PCI_InitializationBlockPtr, initPtr);
      }
      else
       initPtr = &driverData->InitializationBlock;

      initPtr = CMSMGetPhysical(initPtr);
      initPtr = (void *)GET_UINT32(&initPtr);

      /* AYD 11-15-96 */
      if( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II ) )
      {
         COPY_ADDR(&driverData->PCI_InitializationBlockPtr->PCI_PhysicalAddress,&configTable->MLIDCFG_NodeAddress);

      /* Set up Receive Descriptor Table Ptr.                              */
         descPtr = &driverData->PCI_RxDescriptorTable;
         descPtr = (void *)((UINT32)descPtr & 0xfffffff0); /* Force to 16 bytes */
         PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr, descPtr);

         descPtr = CMSMGetPhysical(descPtr);

      PUT_UINT32(&driverData->PCI_InitializationBlockPtr->PCI_RxDescriptorRingPtr, (void *)(UINT32)descPtr);

      bufferLength = 0xffffffff;
      bufferCount = RX_BUFFERS;
         while(bufferCount != 0)
         {
            bufferLength++;
            bufferCount >>= 1;
         }
      bufferLength <<= 4;
      PUT_UINT16(&driverData->PCI_InitializationBlockPtr->PCI_Len, (UINT16)bufferLength);

      /* Set up Transmit Descriptor Table Ptr.                              */
      descPtr = &driverData->PCI_TxDescriptorTable;
      descPtr = (void *)((UINT32)descPtr & 0xfffffff0);   /* Force to 16 bytes */
      PUT_UINT32(&driverData->PCI_TxDescriptorTablePtr, descPtr);

      descPtr = CMSMGetPhysical(descPtr);

      PUT_UINT32(&driverData->PCI_InitializationBlockPtr->PCI_TxDescriptorRingPtr, (void *)(UINT32)descPtr);

      bufferLength = 0xffffffff;
      bufferCount = TX_BUFFERS_FRAG;
         while(bufferCount != 0)
         {
            bufferLength++;
            bufferCount >>= 1;
         }
      bufferLength <<= 12;
      ioValue = GET_UINT16(&driverData->PCI_InitializationBlockPtr->PCI_Len);
      ioValue &= 0x0fff;
      ioValue |= (UINT16)bufferLength;
      PUT_UINT16(&driverData->PCI_InitializationBlockPtr->PCI_Len, ioValue);
      }
      else
      {
         COPY_ADDR(&driverData->PhysicalAddress,&configTable->MLIDCFG_NodeAddress);
/* AYD 03-03-97 Set aligment to 32 byte boundary to use beter cache lines on
Pentium CPU*/
         /* Set up Receive Descriptor Table Ptr.                              */
         descPtr = &driverData->RxDescriptorTable;
         descPtr = (void *)((UINT32)descPtr & 0xfffffff8); /* Force to QWORD */
         PUT_UINT32(&driverData->RxDescriptorTablePtr, descPtr);

         descPtr = CMSMGetPhysical(descPtr);

         bufferLength = 0xffffffff;
         bufferCount = RX_BUFFERS;
         while(bufferCount != 0)
         {
            bufferLength++;
            bufferCount >>= 1;
         }
         bufferLength <<= 29;
         PUT_UINT32(&driverData->RxDescriptorRingPtr,
                     (void *)((UINT32)descPtr | bufferLength));

         /* Set up Transmit Descriptor Table Ptr.                              */

         descPtr = &driverData->TxDescriptorTable;
         descPtr = (void *)((UINT32)descPtr & 0xfffffff8);   /* Force to QWORD */
         PUT_UINT32(&driverData->TxDescriptorTablePtr, descPtr);

         descPtr = CMSMGetPhysical(descPtr);

         bufferLength = 0xffffffff;
         if (driverData->PCnetFlag == LANCE)
            bufferCount = TX_BUFFERS;
         else
            bufferCount = TX_BUFFERS_FRAG;

         while(bufferCount != 0)
         {
            bufferLength++;
            bufferCount >>= 1;
         }
         bufferLength <<= 29;
         PUT_UINT32(&driverData->TxDescriptorRingPtr,
                  (void *)((UINT32)descPtr | bufferLength));

         if (driverData->PCnetFlag == LANCE)
         {
            /* Setp up Transmit Descriptors.                  */
            for(bufferCount = 0, bufferPtr=driverData->TxBuffers,
               txDescPtr = (TX_DESC *)GET_UINT32(&driverData->TxDescriptorTablePtr),
               txBufferPtr = (UINT32 *)&driverData->TxBufferTable;
               bufferCount < TX_BUFFERS;
               bufferCount++,
                  txDescPtr++,
              txBufferPtr++)
            {
               PUT_UINT32(txBufferPtr, (UINT32)bufferPtr);
               PUT_UINT32(&txDescPtr->TxDescAddr.TxAddr,
                  ((UINT32)CMSMGetPhysical(bufferPtr) | 0x03000000)); /* STP & ENP */
               bufferPtr = (void *)((UINT8 *)bufferPtr + BUFFER_SIZE);
            }
         }
      }

      DriverDisableInterrupt(driverData, FALSE);
      DriverShutdown(driverData, configTable, SHUTDOWN_PARTIAL, OP_SCOPE_ADAPTER);
      driverData->AdapterResetCount++;

      /* Allocate as many RCBs as possible.   */

      while (driverData->NeedRCBCount)
      {
         rcb = CMSMAllocateRCB(driverData, driverData->CommonMaximumSize, NULL);
         if (rcb == NULL)
            break;

         /* AYD 08-29-97 */
         /*if ( ((ECB *)rcb)->ECB_Status == SPARE_ECB_STATUS)
            driverData->ECBsOver16Meg++;*/

         i = driverData->RxNextToAllocate;
         driverData->RCBTable[i] = rcb;
         rxFragmentPtr = (UINT32)GET_UINT32(&rcb->RCBFragStruct.FragmentAddress);

         /* AYD 11-18-96 Added switch */
         switch ( driverData->PCnetFlag )
         {
          case PCNETPCI:
             PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxAddr_32,
                  rxFragmentPtr);
             PUT_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST2.BufferByteCnt,
                  -((UINT16)driverData->CommonMaximumSize));
            
            driverData->PCI_RxDescriptorTablePtr[i].U.ST2.RxDescStatus_32 |= R_OWN_32;

            break;

          case PCNETPCI_II:
             PUT_UINT32(&driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxAddr_32_II,
                  rxFragmentPtr);
             PUT_UINT16(&driverData->PCI_RxDescriptorTablePtr[i].U.ST3.BufferByteCnt_II,
                  -((UINT16)driverData->CommonMaximumSize));
            
            driverData->PCI_RxDescriptorTablePtr[i].U.ST3.RxDescStatus_32_II |= R_OWN_32;

            break;

         default:
             rxFragmentPtr |= (R_OWN << 24);
             PUT_UINT32(&driverData->RxDescriptorTablePtr[i].RxDescAddr.RxAddr,
                  rxFragmentPtr);
             PUT_UINT16(&driverData->RxDescriptorTablePtr[i].RxDescBufferCount,
                  -((UINT16)driverData->CommonMaximumSize));
             break;
         }

         i = (i+1) & (RX_BUFFERS - 1);
         driverData->RxNextToAllocate = i;
         driverData->NeedRCBCount--;
      }

      /* AYD 06-11-96 Moved DMAStart in to DriverReset */
      /* Set up DMA channel */
      if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
         DMAStart( (void *)driverData->BusTag, 0, 0,
              (void *)driverData->BusTag, 0, 0,
              0, (UINT32)configTable->MLIDCFG_DMALine0, 0xc0, 0);

      /* Reset the NIC */

      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR0);
      /* Pulse hardware reset line */
      In16(configTable->MLIDCFG_DBusTag, (void *)driverData->Reset);
      Slow();
      DriverEnableInterrupt(driverData);

      if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
      {
         /* Enable 32 bit Discriptors */
         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, BCR20);
         ioValue = In16( configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP);

         ioValue &= 0xff00;

         /* AYD 11-15-96 */
         if (driverData->PCnetFlag == PCNETPCI)
            ioValue |= 0x02;     /* SWSTYLE = 2 */
         else
            ioValue |= 0x03;      /* SWSTYLE = 3 */

         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP, ioValue);

         if (driverData->PCnetFlag == PCNETPCI_II)
         {
            /* AYD 11-15-96 */
            /* Enable Burst Read/Write Mode and Set No Underflow on Transmit. */
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, BCR18);
            ioValue = In16( configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP);
            /* Set NOUFLO, BREADE and BWRITE. Bits 11, 6 and 5 */
            /* ioValue |= 0x0860; */
            ioValue |= 0x0800;
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP, ioValue);

/* #ifdef DEBUG
       NiosBreak();
#endif */

             /* Read BCR33, bit #10 should indicate link speed. 0 - 10, 1 - 100 MBPS*/

             Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, BCR33);
             ioValue = In16( configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP);

             if (ioValue & 0x0400)
                configTable->MLIDCFG_LineSpeed = 100;
             else
                configTable->MLIDCFG_LineSpeed = 10;

         }

         /* AYD 02-09-96 Set Full Duplex Mode */
         if ( driverData->FullDuplex )
         {
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, BCR9);
            ioValue = In16( configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP);
            ioValue |= 0x3;
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP, ioValue);
           }
      }

      if (driverData->PCnetFlag)
      {
         if (driverData->PCnetFlag == PCNETISA)
         {
            /* Configure Bus register */
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR2);
            ioValue = (driverData->BusType == ODI_BUSTYPE_EISA) ? (LEVEL_INIT   | 0x02) :
                                                         (FASTISA_INIT | 0x02);
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->IDP_BDP, ioValue);

            /* Configure FIFO/DMA Burst register */
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR80);
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
                                 RCVFW_INIT | XMTFW_INIT | XMTSP_INIT | 0x020);

            /* Configure Bus Timer register */
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR82);
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, 0x91);

         }

         /* Configure config register */
         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR4);
         ioValue = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);

          /* AYD 10-13-95 */

         if (driverData->PCnetFlag == PCNETISA)
            ioValue = (((ioValue & 0xbfff) | 0x2800) | DMAPLUS_INIT);
         else
            ioValue = ( ioValue | 0x0800 ); /* APAD_XMT Auto Pad */

         ioValue |= ENTST; /* Enable Test Mode or Runt Packet Accept */
         Slow();
         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, ioValue);

         /* AYD 12-18-95 */ /* AYD 02-13-96 */
         if (driverData->PCnetFlag == PCNETISA)
            ioRPA = GET_UINT16(&driverData->InitializationBlock);
         else
            ioRPA = GET_UINT16(&driverData->PCI_InitializationBlockPtr->Mode);

         /* AYD 03-29-96 Using ioRPA for temp. storage Mode word */
         if ( ioRPA & 0x8000 )
         {
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR124);
            ioRPA = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
            ioRPA |= 0x0008;   /* Enable RPA */
            Slow();
            Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, ioRPA);
         }

         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR4);
         ioValue &= ~ENTST; /* Disable Test Mode or Runt Packet Accept */
         Slow();
         Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, ioValue);
      }

      /* Send low word of physical address of Initialization Block */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR1);
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
           (UINT16)initPtr);

      /* Send high word of physical address of Initialization Block */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR2);
      initPtr = (void *)((UINT32)initPtr >> 16);
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP,
           (UINT16)initPtr);

      /* Send initialize command to NIC */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR0);
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, INIT);

      /* Wait up to 100us for IDON bit to set */

      startTime = CMSMGetMicroTimer();
      /* NiosDprintf(START_TIME, startTime); */
      startTime = -startTime;
      do
        {
         ioValue = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);
          /* NiosDprintf(STATUS, ioValue); */
         /* NiosBreak(); */
         if ((ioValue & IDON) != 0)
            break;
      }
      while ( ((currentTime=CMSMGetMicroTimer()) + startTime) < 0x20000);


      /* NiosDprintf(CURRENT_TIME, currentTime+startTime); */

      if ((ioValue & IDON) == 0)
         return ODISTAT_FAIL;

      /* Clear IDON bit */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, ioValue);

      /* Start the NIC */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, STRT);
      Slow();
      ioValue = In16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP);

      /* AYD 05-30-96 Clear all other bits in case if NIC received a packet */
      ioValue &= (RXON | TXON | STRT | INIT);

      if ( ioValue != (RXON | TXON | STRT | INIT))
         return ODISTAT_FAIL;

      /* Enable the NIC */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, INEA);

      CMSMUpdateConfigTables(driverData, configTable);

      return   ODISTAT_SUCCESSFUL;
   }
   else
      return   ODISTAT_SUCCESSFUL;

}   /* End DriverReset */


/***********************************************************************\
*                                                                       *
*
*   Name:
*      UINT32 DriverInit(struct _HSM_STACK *hsmStack)
*
*   Description:
*
*      This routine will call CEtherTSMRegisterHSM,
*      CMSMParseDriverParameters, CMSMRegisterHardwareOptions,
*      CMSMSetHardwareInterrupt, CMSMRegisterMLID, initialize
*      variables in the Adapter Data Space and reset/initialize
*      the card.
*
*   Parameters in:
*
*      hsmStack -      Pointer to HSM's stack parameters which will
*                     dealt with by the MSM at different stages of
*                     DriverInit.
*
*   Things to do:
*
*      1) Set up PCnetISA adapter data space variables that are
*      configurable from the command line when AddOption/ParseOptions
*      is implemented.
*
*   Values returned:
*
*      0         if successful
*      ALL_ONES if failure
*
*                                                                       *
************************************************************************/
UINT32   DriverInit(CHSM_STACK *hsmStack)
{
   CONFIG_TABLE   *configTable;
   DRIVER_DATA    *driverData;
   REG_TYPE         retValue;
   UINT16         ioValue;
   UINT32         nodeIndex;
   UINT32         checksum;
   UINT8          ioValue8;
   UINT32         LocalPCnetFlag = 0;
   UINT32         scanSeq,   uniqueID, busTag, busType;
   UINT16         slot;
   UINT8            cfgBlock[256];
   CMSM_PNP_ISA_CONFIG_INFO        *cfgBlockPnPPtr;
   UINT8            cfgBlockPnP[512];
   static MEON      productID[4] = {0x22, 0x10, 0x00, 0x20}; /* PCnetPCI */
   static MEON      productIDPnP[4] = {0x04, 0x96, 0x55, 0xAA}; /* PCnetISA+ */


   /* VendorID for PCnetISA+ is "ADV55AA"   00001, 00100, 10110
    compressed ASCII (0x0496) and 0x55AA */

   DriverParameterBlock.DriverInitParmPointer = (CHSM_STACK *)&hsmStack;

   CMSMInitParser(&DriverParameterBlock);

   IoOption.Parameter1.Range = 0;

     if( CMSMParseSingleParameter(&ISAOption) == ODISTAT_SUCCESSFUL )
   {
      DriverParameterBlock.DriverNeedsBelow16Meg = 1;
      DriverConfigTemplate.MLIDCFG_SGCount = 2;
   }
   else
   {
      scanSeq = -1;
        if( CMSMSearchAdapter (&scanSeq, ODI_BUSTYPE_PCI, 4, productID,
               (void **)&busTag,   &uniqueID)
               == ODI_NBI_SUCCESSFUL)
        {
         DriverParameterBlock.DriverNeedsBelow16Meg = 0;
         DriverConfigTemplate.MLIDCFG_SGCount = 16;
        }
   }


   /* Let TSM/MSM know we are here */
   if  (CEtherTSMRegisterHSM(&DriverParameterBlock, &configTable)
       != ODISTAT_SUCCESSFUL)
   {
      CMSMReturnDriverResources(configTable);
      return   (ALL_ONES);
   }

   /* DMAOption.Flags &= ~REQUIREDPARAM;
   DMAOption.Link = NULL; */

   /* Find out if we load the driver for ISA type of adapter which will
    require DMA, PORT, IRQ parameters on command line in case if machine
    has two or more different kind (PCI, ISA etc.) of NICs */
     if( CMSMParseSingleParameter(&ISAOption) == ODISTAT_SUCCESSFUL )
   {
      if ( DriverInitISA(&LocalPCnetFlag, configTable) != ODISTAT_SUCCESSFUL )
         return ALL_ONES;
   }
   else
   {
      SlotsWithMyBoard.OptionCount = 0;
      scanSeq = -1;

      /* Find all of the PCnetISA+'s in the machine */
      while (SlotsWithMyBoard.OptionCount < 8 && CMSMSearchAdapter (
               &scanSeq,
               ODI_BUSTYPE_ISA,
               4,
               productIDPnP,
               (void **)&busTag,
               &uniqueID)
               == ODI_NBI_SUCCESSFUL)

      {
           if( CMSMGetInstanceNumber( (void *)busTag, uniqueID, &slot ) ==
               ODI_NBI_SUCCESSFUL)
          {
            SlotsWithMyBoard.Slot[SlotsWithMyBoard.OptionCount] = (UINT32)slot;
            SlotsWithMyBoard.OptionCount++;
          }
         /* NiosDprintf(UNIQUE_ID, uniqueID); */
      }

      scanSeq = -1;
      /* Find all of the PCnetPCI's in the machine */
      while (SlotsWithMyBoard.OptionCount < 8 && CMSMSearchAdapter (
               &scanSeq,
               ODI_BUSTYPE_PCI,
               4,
               productID,
               (void **)&busTag,
               &uniqueID)
               == ODI_NBI_SUCCESSFUL)
      {
           if(CMSMGetInstanceNumber( (void *)busTag, uniqueID, &slot ) ==
               ODI_NBI_SUCCESSFUL)
          {
            SlotsWithMyBoard.Slot[SlotsWithMyBoard.OptionCount] = (UINT32)slot;
            SlotsWithMyBoard.OptionCount++;
         }
         /* NiosDprintf(UNIQUE_ID, uniqueID); */
      }

      if (SlotsWithMyBoard.OptionCount)
      {
         configTable->MLIDCFG_Slot = SlotsWithMyBoard.Slot[0];

         if (SlotsWithMyBoard.OptionCount > 1)
         {
            if (CMSMParseDriverParameters(&DriverParameterBlock, &SlotOption) != ODISTAT_SUCCESSFUL)
            {
               CMSMReturnDriverResources(configTable);
               return ODISTAT_FAIL;
            }
         }
         else
         {
            /* Call CMSMParseDriverParameters at least ones to parse for frame */
            if (CMSMParseDriverParameters(&DriverParameterBlock, NULL) != ODISTAT_SUCCESSFUL)
            {
               CMSMReturnDriverResources(configTable);
               return ODISTAT_FAIL;
            }
         }

         if (CMSMGetInstanceNumberMapping(configTable->MLIDCFG_Slot, (void **)&busTag, &uniqueID) ==
                     ODI_NBI_SUCCESSFUL &&
             CMSMGetBusType((void *)busTag, &busType) == ODI_NBI_SUCCESSFUL)
         {
            switch ( busType )
            {
               case ODI_BUSTYPE_ISA:
                  cfgBlockPnPPtr = (CMSM_PNP_ISA_CONFIG_INFO *)cfgBlockPnP;
                  if ( CMSMGetCardConfigInfo ( (void *)busTag,
                                         uniqueID,
                                         512,
                                         0,
                                           NULL,
                                         cfgBlockPnPPtr) == ODI_NBI_SUCCESSFUL )
                  {
                       configTable->MLIDCFG_DBusTag = (void *)busTag;
                       configTable->MLIDCFG_IOPort0 = *(cfgBlockPnPPtr->CPNPIOPortBase);
                       configTable->MLIDCFG_Interrupt0 = *(cfgBlockPnPPtr->CPNPIRQRegisters);
                       configTable->MLIDCFG_DMALine0 = *(cfgBlockPnPPtr->CPNPDMAList);
                     LocalPCnetFlag = PCNETISA;

/*#ifdef DEBUG
                     NiosDprintf(PORT, configTable->MLIDCFG_IOPort0);
                     NiosDprintf(IRQ , configTable->MLIDCFG_Interrupt0);
                     NiosDprintf(DMA , configTable->MLIDCFG_DMALine0);
                     NiosDprintf(SLOT, configTable->MLIDCFG_Slot);
#endif*/
                  }
                  else
                     LocalPCnetFlag = -1;
                  break;
               case ODI_BUSTYPE_PCI:
                  if( CMSMGetCardConfigInfo ( (void *)busTag,
                                       uniqueID,
                                       256,
                                          0,
                                         NULL,
                                         cfgBlock) == ODI_NBI_SUCCESSFUL )
                  {
                      /* Check if I/O space bit enabled in PCI Command Register */
                     if( (*((UINT16*)((UINT8*)cfgBlock+0x4)) & 0x0001) == 0)
                     {
                        CMSMPrintString (
                           configTable,
                           MSG_TYPE_INIT_ERROR,
                            CNEAMD_NOPORTERR_MSG,
                           NULL,
                           NULL);

                        CMSMReturnDriverResources (configTable);
                        return (ODISTAT_FAIL);
                     }

                     /* AYD 11-15-96 Re-init DriverParameterBlock for PCI */
                     if ( *(cfgBlock+0x8) >= 0x16 )
                     {
                        DriverParameterBlock.DriverSendPtr = (void (*)())DriverSendPCI_II;
                        DriverParameterBlock.DriverISRPtr = (void (*)())DriverISRPCI_II;
                        LocalPCnetFlag = PCNETPCI_II;            /* PCnetPCI_II or PCnetFast */
                     }
                     else
                     {
                        DriverParameterBlock.DriverSendPtr = (void (*)())DriverSendPCI;
                        DriverParameterBlock.DriverISRPtr = (void (*)())DriverISRPCI;
                        LocalPCnetFlag = PCNETPCI;            /* PCnetPCI or PCnet-32 */
                     }

                     DriverParameterBlock.DriverEndOfChainFlag = 1;

                     configTable->MLIDCFG_SharingFlags |= MS_SHARE_IRQ0_BIT;
                      configTable->MLIDCFG_DBusTag = (void *)busTag;
                     configTable->MLIDCFG_IOPort0 = *((UINT16*)((UINT8*)cfgBlock+0x10)) & 0xfffc;
                     configTable->MLIDCFG_Interrupt0 = *(cfgBlock+0x3c); /* int number */
                      configTable->MLIDCFG_DMALine0 = 0xff;

/* #ifdef DEBUG
                      NiosDprintf(PORT, configTable->MLIDCFG_IOPort0);
                      NiosDprintf(IRQ , configTable->MLIDCFG_Interrupt0);
                     NiosDprintf(DMA , configTable->MLIDCFG_Slot);
#endif */

                     /* To enable Bus Master bit in PCI Config Space of PCnetPCI */
                     /* Some PCI BIOSs do not set this bit on PCnetPCI */
                     /* Let use NBI API to enable Bus Master bit in PCnetPCI Config Space */
   /*                  CMSMWrtConfigSpace16((void *)busTag,
                               uniqueID,
                               0x4,
                              (*( (UINT16 *)( (UINT8 *)cfgBlock+0x04 )) | 0x0004) & 0xFFBF); */
                  }
                  else
                     LocalPCnetFlag = -1;
                  break;
               default:
                  LocalPCnetFlag = -1;
                  break;
            }
            if( LocalPCnetFlag == -1)
            {
               CMSMReturnDriverResources (configTable);
               return (ODISTAT_FAIL);
            }
         }
         else
         {
            CMSMReturnDriverResources (configTable);
            return (ODISTAT_FAIL);
         }
      }
      else /* if not a PCnetPCI or PCnetISA+ */
      {
         if ( DriverInitISA(&LocalPCnetFlag, configTable) != ODISTAT_SUCCESSFUL )
            return ALL_ONES;
      } /* End of not PCnetPCI */
   }

   switch ( LocalPCnetFlag )
      {
         case 1:                  /* PCnetISA or PCnetISA+ */
            DriverParameterBlock.DriverNeedsBelow16Meg = 1;
            DriverParameterBlock.DriverEndOfChainFlag = 0;
            DriverParameterBlock.DriverSendPtr = (void (*)())DriverSendISA;
            DriverParameterBlock.DriverISRPtr = (void (*)())DriverISRISA;
            configTable->MLIDCFG_SGCount = 16;
            break;
         case 2:                 /* PCnetPCI */
            break;
         case 3:                 /* PCnetPCI_II or PCnetFast */
            break;
         default:                /* LANCE */
            DriverParameterBlock.DriverNeedsBelow16Meg = 1;
            DriverParameterBlock.DriverEndOfChainFlag = 0;
            DriverParameterBlock.DriverSendPtr = (void (*)())DriverSendLANCE;
            DriverParameterBlock.DriverISRPtr = (void (*)())DriverISRISA;
            break;
      }
   /* Register hardware with OS */
   if ((retValue = CMSMRegisterHardwareOptions(configTable, &driverData)) == REG_TYPE_FAIL)
   {
      /* Another adapter is using one of the resources we tried to register */
      CMSMReturnDriverResources(configTable);
      return   (ALL_ONES);
   }

   /* AYD 09-25-95 Added Switch */
   switch ( LocalPCnetFlag )
      {
         case 1:
            driverData->PCnetFlag = PCNETISA;      /* 1 */
            break;
         case 2:
            driverData->PCnetFlag = PCNETPCI;      /* 2 */
            break;
         case 3:
            driverData->PCnetFlag = PCNETPCI_II;   /* 3 */
            break;
         default:
            driverData->PCnetFlag = LANCE;         /* 0 */
            break;
      }


   /* Allocate memory for transmit buffers if using Am7990 LANCE chipset.   */
   /* AYD 09-20-95 */
   /* AYD 05-29-96 Moved memory allocation in front of DriverReset */
   if (retValue != REG_TYPE_NEW_FRAME)
   {
        if ( driverData->PCnetFlag == LANCE )
        {
         driverData->TxBuffers = CMSMAlloc(driverData, BUFFER_SIZE * TX_BUFFERS);
         if (driverData->TxBuffers == NULL)
         {
            CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR,
               CNEAMD_ALLOCMEMERR_MSG,
               NULL ,NULL);
            CMSMReturnDriverResources(configTable);
            return   ALL_ONES;
         }

        }
   }
   /* AYD 06-07-96 */
   /* Save highly used I/O port values in Adapter Data Space   */

   driverData->RDP    = configTable->MLIDCFG_IOPort0 + 0x10;
   driverData->RAP    = configTable->MLIDCFG_IOPort0 + 0x12;
   driverData->Reset   = configTable->MLIDCFG_IOPort0 + 0x14;
   driverData->IDP_BDP   = configTable->MLIDCFG_IOPort0 + 0x16;

   /* AYD 04-01-95 Reset the adapter  because in DriverInitISA we stopped
    the chip */
   if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
   {
       DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
       configTable->MLIDCFG_SharingFlags &= ~MS_SHUTDOWN_BIT;
   }

   if (retValue == REG_TYPE_NEW_FRAME)
   {

   /* 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);
   }

   /* To enable Bus Master bit in PCI Config Space of PCnetPCI */
   /* Some PCI BIOSs do not set this bit on PCnetPCI */
   /* Let use NBI API to enable Bus Master bit in PCnetPCI Config Space */
   if( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II ) )
      CMSMWrtConfigSpace16((void *)busTag,
                     uniqueID,
                     0x4,
                     (*( (UINT16 *)( (UINT8 *)cfgBlock+0x04 )) | 0x0004) & 0xFFBF);

   /* AYD 03-14-95 Made Full-Duplex mode optional */
   if( CMSMParseSingleParameter(&FullDuplexOption) == ODISTAT_SUCCESSFUL )
      driverData->FullDuplex = 1;
   else
      driverData->FullDuplex = 0;

   /* New adapter being loaded */
   CFixUpStatStrings(driverData);      /* Initialize statistic strings */

   /* Get bus type. DriverReset needs it in case we're on an EISA bus. */
   CMSMGetBusType(configTable->MLIDCFG_DBusTag, &driverData->BusType);

   /* Save bus tag. This will make run time functions more effecient */
   driverData->BusTag  = configTable->MLIDCFG_DBusTag;

   /* Read node address from adapter unless there was a node override   */

   if ( ADDR_EQUAL((&configTable->MLIDCFG_NodeAddress), &BroadcastAddress) )
    for(nodeIndex = 0; nodeIndex < 6; nodeIndex += 2)
    {
            ioValue=In16(driverData->BusTag,
               (void *)(configTable->MLIDCFG_IOPort0 + nodeIndex));
            PUT_UINT16(&configTable->MLIDCFG_NodeAddress.nodeAddress[nodeIndex], ioValue);
    }


   /* 2048 to fit jabber packets */

   driverData->CommonMaximumSize = 2048;

   /* Check ROM for valid NE2100 or PCnet family NIC.   */

   for(checksum = 0, nodeIndex=0 ;
         nodeIndex < 12;
      nodeIndex++)
   {
      ioValue8=In8(driverData->BusTag,
            (void *)(configTable->MLIDCFG_IOPort0 + nodeIndex));
      checksum += (UINT32)ioValue8;
   }

   nodeIndex += 2;
   ioValue8=In8(driverData->BusTag,
         (void *)(configTable->MLIDCFG_IOPort0 + nodeIndex));
   checksum += (UINT32)ioValue8;
   nodeIndex += 1;
   ioValue8=In8(driverData->BusTag,
         (void *)(configTable->MLIDCFG_IOPort0 + nodeIndex));
   checksum += (UINT32)ioValue8;

   nodeIndex -= 3;
   ioValue=In16(driverData->BusTag,
         (void *)(configTable->MLIDCFG_IOPort0 + nodeIndex));

  if (checksum != (UINT32)ioValue)
  {
      CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR,
         CNEAMD_BADCHECKSUM_MSG,
         NULL ,NULL);
      CMSMReturnDriverResources(configTable);
      return   ALL_ONES;
  }

   /* AYD 06-11-96 Moved DMAStart in to DriverReset */
   /* Set up DMA channel */

   /* if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
      DMAStart( (void *)driverData->BusTag, 0, 0,
        (void *)driverData->BusTag, 0, 0,
        0, (UINT32)configTable->MLIDCFG_DMALine0, 0xc0, 0); */

/* AYD 09-25-95 */
   if ( driverData->PCnetFlag == 0 )
      DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount = TX_BUFFERS;
   else
      DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount = TX_BUFFERS_FRAG/16;

   /* Initialize/Reset adapter */
  if ( DriverReset(driverData, configTable, OP_SCOPE_ADAPTER) != ODISTAT_SUCCESSFUL )
  {
      CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR,
         CNEAMD_BADBOARD_MSG,
         NULL ,NULL);
      CMSMReturnDriverResources(configTable);
      return   ALL_ONES;
  }


   /* Allow MSM to register the MLID with the LSL */
  if ( (CMSMRegisterMLID(driverData, configTable) ) != ODISTAT_SUCCESSFUL )
  {
      CMSMReturnDriverResources(configTable);
      return   ALL_ONES;
  }

   /* Set up our interrupt procedure.         */
  if ( CMSMSetHardwareInterrupt(driverData, configTable) != ODISTAT_SUCCESSFUL)
  {
      CMSMReturnDriverResources(configTable);
      return (ALL_ONES);
  }

   /* Set up call back to detect transmit and receive timeouts */

  if ( (CMSMScheduleAES(driverData, (MLID_AES_ECB *)&driverData->DAES))
      != ODISTAT_SUCCESSFUL)
  {
      CMSMReturnDriverResources(configTable);
      return   ALL_ONES;
  }

   /***********************************************************************\
    ** 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 =
         DriverParameterBlock.DriverModuleHandle;
      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   = NICShortName;
   NESL_EPBPtr->EPBDataPtr0   = configTable;
   NESL_EPBPtr->EPBDataPtr1   = NULL;
   NESL_EPBPtr->EPBEventScope = EPB_SPECIFIC_EVENT;
   NESL_EPBPtr->EPBReserved   = 0;

   /* Generate NESL MLID Card Insertion Complete Event */
   CMSMNESLProduceEvent(NESLServiceResumeNECBPtr,
                            NULL,
                            NESL_EPBPtr);

   return   0;

}   /* End DriverInit */

/* This is a sample code how to enable Bus Master bit in PCI Config Space
of PCnetPCI. Some PCI BIOSs do not set this bit on PCnetPCI */

/* Mechanism #2 */
/* Function */
/*
Out8(configTable->MLIDCFG_DBusTag, (void *)0x0cf8,
      0x10 | ((uniqueID & 0x00000007) << 1) );

Out8(configTable->MLIDCFG_DBusTag, (void *)0x0cfa,
       (uniqueID & 0x0000ff00) >> 8  );

ioValue = 0xc000 + ( ( (uniqueID & 0x00f8 ) >> 3) * 256 + 4 );

scanSeq = In32( configTable->MLIDCFG_DBusTag, (void *) ioValue);

NiosDprintf("StatusComReg = %X  \r\n", scanSeq);

Out32(configTable->MLIDCFG_DBusTag,
               (void *)ioValue, scanSeq | 0x4);

Out8(configTable->MLIDCFG_DBusTag, (void *)0x0cf8, 0);
*/

/* Mechanism #1 */
/*
Out32(configTable->MLIDCFG_DBusTag, (void *)0x0cf8,
      0x80000000 | (uniqueID << 8) | 4   );

scanSeq = In32( configTable->MLIDCFG_DBusTag, (void *)0x0cfc);

NiosDprintf("StatusComReg = %X  \r\n", scanSeq);

Out32(configTable->MLIDCFG_DBusTag, (void *)0x0cf8,
      0x80000000 | (uniqueID << 8) | 4   );

Out32(configTable->MLIDCFG_DBusTag, (void *)0x0cfc,
      scanSeq & 0xffff0004   );

Out32(configTable->MLIDCFG_DBusTag, (void *)0x0cf8,
      ( (uniqueID << 8) | 4) & 0x7fffffff );
*/

/***********************************************************************\
*                                                                       *
*
*   Name:
*      ODISTAT DriverInitISA( *PCnetFlagISA, *configTable)
*
*   Description:
*
*
*   Parameters in:
*                   NONE
*   Parameters out:
*                  LocalPCnetFlag = 0 - LANCE
*                                  1 - PCnetISA
*
*
*   Values returned:
*
*       ODISTAT_SUCCESSFUL   if successful
*      ODISTAT_FAIL         if failure
*
*                                                                       *
************************************************************************/
ODISTAT   DriverInitISA( UINT32 *PCnetFlagISA, CONFIG_TABLE   *configTable )
{
   UINT16         ioValue;

   DMAOption.Flags |= REQUIREDPARAM;
   DMAOption.Link = &IntOption;

   /* Parse resources in case of LANCE, PCnetISA, PCnetISA+ */
   if (CMSMParseDriverParameters(&DriverParameterBlock, &DMAOption) != ODISTAT_SUCCESSFUL)
   {
      CMSMReturnDriverResources(configTable);
      return ODISTAT_FAIL;
   }

   /* AYD 06-11-96 Set the bus tag in case of ISA */
   configTable->MLIDCFG_DBusTag = 0;

   configTable->MLIDCFG_SharingFlags |= MS_SHUTDOWN_BIT;

   /* AYD 06-11-96    Mask DMA before stoping NIC to prevent hang on SMP box */
   DMACleanup((UINT32)configTable->MLIDCFG_DMALine0);

   /*  AYD 04-01-95 Stop the adapter to read Chip ID for PCnetISA */
   Out16(configTable->MLIDCFG_DBusTag,
            (void *)(configTable->MLIDCFG_IOPort0 + 0x12), CSR0);
   /* Disable adapter's interrupts */
   Out16(configTable->MLIDCFG_DBusTag,
            (void *)(configTable->MLIDCFG_IOPort0 + 0x10), 0);
   /* Stop the adapter */
   Out16(configTable->MLIDCFG_DBusTag,
            (void *)(configTable->MLIDCFG_IOPort0 + 0x10), STOP);

   /* Get Chip ID and  set PCnetFlag */
   /* AYD 10-04-95 */
   Out16(configTable->MLIDCFG_DBusTag,
     (void *)(configTable->MLIDCFG_IOPort0 + 0x12), CSR88);
   ioValue = In16(configTable->MLIDCFG_DBusTag,
              (void *)(configTable->MLIDCFG_IOPort0 + 0x10));
   ioValue &= 0x0003;

     if ( ioValue == 0x0003 )
   {
      Out16(configTable->MLIDCFG_DBusTag,
       (void *)(configTable->MLIDCFG_IOPort0 + 0x12), CSR89);
      ioValue = In16(configTable->MLIDCFG_DBusTag,
                (void *)(configTable->MLIDCFG_IOPort0 + 0x10));

      if ( ((ioValue & 0x0fff) == 0) || ((ioValue & 0x0fff) == 0x0226) )
         *PCnetFlagISA = 1;           /* PCnetISA or PCnetISA+ */
      else
         *PCnetFlagISA = 0;           /* LANCE */
   }
   else
      *PCnetFlagISA = 0;           /* LANCE */

   return ODISTAT_SUCCESSFUL;

}     /* End of DriverInitISA */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      void   CFixUpStatStrings(
*                        DRIVER_DATA         *driverData)
*
*   Description:
*
*      This function initializes the statistic table entry strings to
*      point to the language enabled message strings.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*
*   Values returned:
*
*                                                                       *
************************************************************************/

void CFixUpStatStrings(DRIVER_DATA *driverData)
{
/* driverData->TotalTxPacketTable.StatString=(MEON_STRING *)CMLID_TOTALTX_STR;
   driverData->TotalRxPacketTable.StatString=(MEON_STRING *)CMLID_TOTALRX_STR;
   driverData->NoECBAvailableTable.StatString=(MEON_STRING *)CMLID_NOECB_STR;
   driverData->PacketTxTooBigTable.StatString=(MEON_STRING *)CMLID_TXTOOBIG_STR;
   driverData->PacketTxTooSmallTable.StatString=(MEON_STRING *)CMLID_TXTOOSMALL_STR;
   driverData->PacketRxOverflowTable.StatString=(MEON_STRING *)CMLID_RXOVERFLOW_STR;
   driverData->PacketRxTooBigTable.StatString=(MEON_STRING *)CMLID_RXTOOBIG_STR;
   driverData->PacketRxTooSmallTable.StatString=(MEON_STRING *)CMLID_RXTOOSMALL_STR;
   driverData->PacketTxMiscErrorTable.StatString=(MEON_STRING *)CMLID_TXMISC_STR;
   driverData->PacketRxMiscErrorTable.StatString=(MEON_STRING *)CMLID_RXMISC_STR;
   driverData->RetryTxTable.StatString=(MEON_STRING *)CMLID_RETRYTX_STR;
   driverData->ChecksumErrorTable.StatString=(MEON_STRING *)CMLID_CRCERR_STR;
   driverData->HardwareRxMismatchTable.StatString=(MEON_STRING *)CMLID_HWRXMISMATCH_STR;
   driverData->TotalRxOKByteTable.StatString=(MEON_STRING *)CMLID_RXOKMYTES_STR;
   driverData->TotalTxOKByteTable.StatString=(MEON_STRING *)CMLID_TXOKBYTES_STR;
   driverData->TotalGroupAddrTxTable.StatString=(MEON_STRING *)CMLID_TXGROUPADDR_STR;
   driverData->TotalGroupAddrRxTable.StatString=(MEON_STRING *)CMLID_RXGROUPADDR_STR;
   driverData->AdapterResetTable.StatString=(MEON_STRING *)CMLID_RESET_STR;
   driverData->AdapterOprTimeStampTable.StatString=(MEON_STRING *)CMLID_OPRTIME_STR;
   driverData->QDepthTable.StatString=(MEON_STRING *)CMLID_TXQDEPTH_STR;

   driverData->TxOKSingleCollisionTable.StatString=(MEON_STRING *)CETHER_SINGLECOL_STR;
   driverData->TxOKMultipleCollisionsTable.StatString=(MEON_STRING *)CETHER_MULTICOL_STR;
   driverData->TxOKButDeferredTable.StatString=(MEON_STRING *)CETHER_DEFERRED_STR;
   driverData->TxAbortLateCollisionTable.StatString=(MEON_STRING *)CETHER_LATECOL_STR;
   driverData->TxAbortExcessCollisionsTable.StatString=(MEON_STRING *)CETHER_EXCESSCOL_STR;
   driverData->TxAbortCarrierSenseTable.StatString=(MEON_STRING *)CETHER_CARRSENSE_STR;
   driverData->TxAbortExDeferralTable.StatString=(MEON_STRING *)CETHER_TXABORT_STR;
   driverData->RxAbortFrameAlignmentTable.StatString=(MEON_STRING *)CETHER_RXABORT_STR;
 */
   driverData->HeartbeatErrorTable.StatString=(MEON_STRING *)CNEAMD_HEARTBEAT_STR;
   driverData->MemoryErrorTable.StatString=(MEON_STRING *)CNEAMD_MEMERR_STR;
   driverData->TxOverflowTable.StatString=(MEON_STRING *)CNEAMD_TXOVERFLOW_STR;
   driverData->TxUnderflowTable.StatString=(MEON_STRING *)CNEAMD_TXUNDERFLOW_STR;
   driverData->TxBufferErrorTable.StatString=(MEON_STRING *)CNEAMD_TXBUFFERERR_STR;
   driverData->ECBsOver16MegTable.StatString=(MEON_STRING *)CNEAMD_ECBOVER16MEG_STR;
   driverData->TxECBsOver16MegTable.StatString=(MEON_STRING *)CNEAMD_TXECBOVER16MEG_STR;
   driverData->ECBOverflowTable.StatString=(MEON_STRING *)CNEAMD_ECBOVERFLOW_STR;
}   /* End CFixUpStatStrings */

/***********************************************************************\
*                                                                       *
*
*   Name:
*      ODISTAT   DriverShutdown(
*                        DRIVER_DATA         *driverData,
*                        CONFIG_TABLE      *configTable,
*                         UINT32            shutdownType,
*                        OPERATION_SCOPE   operationScope)
*
*   Description:
*
*      This function shuts down the adapter. If its a permanent shutdown,
*      return any memory allocated at DriverInit.
*
*   Parameters in:
*
*      driverData -      Pointer to HSM's Adapter Data Space.
*      configTable -      Pointer to HSM's default Configuration Table.
*      shutdownType -      PERMANENT_SHUTDOWN
*                        TEMPORARY_SHUTDOWN
*      operationScope -   OP_SCOPE_ADAPTER or OP_SCOPE_LOGICAL_BOARD
*
*   Values returned:
*
*                                                                       *
************************************************************************/

ODISTAT   DriverShutdown(
               DRIVER_DATA         *driverData,
               CONFIG_TABLE      *configTable,
               UINT32             shutdownType,
               OPERATION_SCOPE   operationScope)
{

   UINT32   startTime, currentTime;
   RCB      *rcb;
   TX_DESC   *txTable;
   UINT32   descriptor;
   TCB      *tcb;

   if (operationScope == OP_SCOPE_ADAPTER)
   {
      if (shutdownType == SHUTDOWN_PERMANENT)
      {
      if (driverData->TxBuffers)
      {
            CMSMFree(driverData, driverData->TxBuffers);
            driverData->TxBuffers = NULL;
      }
      /* if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
         DMACleanup((UINT32)configTable->MLIDCFG_DMALine0); */
      }

      /* AYD 06-11-96 Call DMACleanup always */
      if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
         DMACleanup((UINT32)configTable->MLIDCFG_DMALine0);

      if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
      {
         /* Wait upt to 100ms for DMA request line to drop */
         startTime = CMSMGetMicroTimer();
         startTime = -startTime;
         while ( ((currentTime=CMSMGetMicroTimer()) + startTime) < 100000) /* AYD */
            if ( (DMAStatus((UINT32)configTable->MLIDCFG_DMALine0) & 0x02) == 0)
               break;
      }

      /* Stop the adapter */
      /* AYD 10-13-95 */
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RAP, CSR0);
      Out16(configTable->MLIDCFG_DBusTag, (void *)driverData->RDP, STOP);

      /* AYD 05-20-96  Return all RCB before clearing the discriptors */
      /* Return any RCBs that we have queued up */
      while(driverData->NeedRCBCount != RX_BUFFERS) /* AYD != */
      {
         rcb = driverData->RCBTable[driverData->RxNextToReturn];

         driverData->RxNextToReturn++;
         driverData->RxNextToReturn &= (RX_BUFFERS - 1);
         driverData->NeedRCBCount++;
         CMSMReturnRCB(driverData, rcb);
      }

      /* AYD 04-09-96 added code to clear Receive Descriptors */
      /* Clear receive descriptors if Am79C960 PCnetISA */
      if ( (driverData->PCnetFlag == PCNETISA) || (driverData->PCnetFlag == LANCE) )
      Set32(configTable->MLIDCFG_DBusTag,
            NULL,
            driverData->RxDescriptorTablePtr,
            0,
            (sizeof(RX_DESC) * RX_BUFFERS) / 4);

      /* AYD 05-20-96 Changed RX_DESC to PCI_RX_DESC */
      if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
       Set32(configTable->MLIDCFG_DBusTag,
            NULL,
            driverData->PCI_RxDescriptorTablePtr,
            0,
            (sizeof(PCI_RX_DESC) * RX_BUFFERS) / 4);


      driverData->RxNextToReturn = 0;
      driverData->RxNextToAllocate = 0;


      /* Initialize Am7990 LANCE transmit descriptors */
      if ( driverData->PCnetFlag == 0)
         {
            txTable = (TX_DESC *)GET_UINT32(&driverData->TxDescriptorTablePtr);
            if (txTable)
            for (descriptor=0; descriptor < TX_BUFFERS; descriptor++)
            {
               txTable[descriptor].TxDescAddr.TxAttr.Attr = (T_ENP | T_STP);
               driverData->TxStartTime[descriptor] = 0;
            }
            DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount = TX_BUFFERS;
         }

      /* Initialize Am79C960 PCnetISA transmit descriptors */
      /* AYD 09-25-95 Changed TX_BUFFERS to TX_BUFFERS_FRAG/16 */
      /* AYD 04-19-96 Changed  initializetion of transmit descriptors */

      if (driverData->PCnetFlag)
      {
      while(DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount < TX_BUFFERS_FRAG/16)
      {
        tcb = driverData->TCBTable[driverData->TxNextToReturn];

         /* AYD 03-29-96 Check if this is an end of the TCB list */
         if (tcb == NULL)
             break;

        driverData->TxStartTime[driverData->TxNextToReturn] = 0;
        driverData->TxNextToReturn =(UINT32)
            ((driverData->TxLastDesc[driverData->TxNextToReturn] + 1)
                  & (TX_BUFFERS_FRAG-1));

         DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount++;

        CEtherTSMFastSendComplete(driverData, tcb, 0);

      }
      }

      /* AYD 05-20-96  Clear all transmit discriptors after returning TCBs */
      /* Clear transmit descriptors if Am79C960 PCnetISA */
      if (driverData->PCnetFlag == PCNETISA)
      Set32(configTable->MLIDCFG_DBusTag,
            NULL,
            driverData->TxDescriptorTablePtr,
            0,
            (sizeof(TX_DESC) * TX_BUFFERS_FRAG) / 4);

      /* AYD 05-20-96 Changed TX_DESC to PCI_TX_DESC */
      if ( (driverData->PCnetFlag == PCNETPCI) || (driverData->PCnetFlag == PCNETPCI_II) )
       Set32(configTable->MLIDCFG_DBusTag,
            NULL,
            driverData->PCI_TxDescriptorTablePtr,
            0,
            (sizeof(PCI_TX_DESC) * TX_BUFFERS_FRAG) / 4);

      driverData->TxNextToReturn = 0;
      driverData->TxNextToSend = 0;
      return(ODISTAT_SUCCESSFUL);
   }
   else
      return(ODISTAT_SUCCESSFUL);

}   /* End DriverShutdown */

/***********************************************************************\
*                                                                       *
*
*   Name:
*         void DriverRemove(void)
*
*   Description:
*         HSM being unloaded. Call CMSMDriverRemove to let the CMSM
*         give back all of our resources and call our DriverShutdown
*         routine for all instances of our driver.
*
*   Parameters in:
*
*      None
*
*   Values returned:
*
*      None
*
*                                                                       *
************************************************************************/
void   DriverRemove(void)
{

/* TNL 12/06/95 Clean up all NESL related stuff   */

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

   CMSMDriverRemove(DriverParameterBlock.DriverModuleHandle);
   return;
}   /* End DriverRemove */