// Sample code file: cne2000.c
// Warning: This code has been marked up for HTML
/*--------------------------------------------------------------------------*
* $name: CNE2000.C
* $version: 6
* $date_modified: 12181998
* $description: This module contains the HardWare specific routines
* to initialize and control the Novell NE2000 board.
* $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.
*--------------------------------------------------------------------------*/
/*****************************************************************************
*
* Title: C language NE2000 HSM
*
* Filename: NE2000.C
*
* ODI Spec Ver: 1.11
*
* Description: This module contains the HardWare specific routines
* to initialize and control the Novell NE2000 board.
*
* Modification History:
*
* 10-07-96 AYD Set Bus Tag to zero assume that ISA is default bus
* Replaced MSMGetMicroTimer call with MSMGetCurrentTime call
* in DriverSend path and DriverCallBack
*
* 10-08-96 MCD Added null entry to Driver Parameter Block structure for
* Driver Priority Queue entry
*
* 10-08-96 TNL Modified DriverPromiscuousChange code to support RMC bit.
*
* 12-04-96 MPK Made changes in Driverinit, to make sure that the MLID
* is registered before the Hardware Interrupts are enabled.
* Also made changes to make sure that the NBI code does not
* acciendentally corrupt the DBus_tag Pointer in case of failure
*
* 02-19-97 MPK Made changes in Driverinit, to call CMSMInitParser to use
* the new parser operations. Also made the change in
* CheckForSharedRAM to call CMSMParseParameter
* instead of CMSMParseDriverParameter.
*
* 07-01-97 PSK Changed DriverISR() to check for physical board
* shutdown, not logical board shutdown.
*
* 08-19-97 JCJ DriverShutdown is modified to check the scope of the operation
* SPD# 161807
*
* 11-25-97 WTT DriverInit was fixed to re-enable the card for new
* frame types. CheckForSharedRAM leaves the card disabled which
* is okay for the first frame type since DriverReset is called.
* However, the loading of additional frame types left the card
* disabled until something else triggered a reset. The code now
* calls driverReset for new frame types.
* SPD #161807
*
* 08-25-98 KRA Fixed CheckForSharedRAM to supply the ParseString for the
* MemOption record. Since CMSMParseSingleParameter is used,
* There must be a valid ParseString. If the parse was
* successful, the memory address is stored in the config table.
* SPD 201866.
*
****************************************************************************/
#ifdef OUT_CHAR
#include "..\..\..\nios_h\nios.h"
UINT32 NiosDebugCharOut(UINT8);
#endif
/*===[ Include files specific to current platform ]======================*/
#include <portable.h>
/*===[ Generic HSM Include files ]===========================*/
#include <odi.h>
#include <odi_nbi.h>
#include <odi_nesl.h>
/*AYD */
#include <nesl_str.h>
#include <parser.h>
#include <cmsm.h>
#include <cne2000.txt>
#ifndef NULL
#define NULL 0L
#endif
/*===[ External data ]===================================================*/
extern MLID_CONFIG_TABLE DriverConfigTemplate;
/*===[ Manifest constants ]==============================================*/
#define MAX_NUM_NE2000s 16
#define RECEIVESTATUSTEST 0x4e
#define MAX_MAC_HEADER 14+3+5 /* SNAP header is max for ethernet. */
/* Variable equates (for convenience and/or clarity) */
/* PCMCIA Option */
#define PROD_ID_LEN 0x0004 /* 4 byte product ID for PCMCIA */
/* Control1 Register Bits */
#define NIC_SMADDRLOW 0x3F
#define NIC_SMMEMENABLE 0x40
#define NIC_SMRESET 0x80
/* Control2 Register Bits */
#define NIC_SMADDRHI 0x1F
#define NIC_SMMEMWIDTH 0x40
#define NIC_SMBUSWIDTH 0x80
/* Command Register Bits */
#define NIC_PAGE0 0x22
#define NIC_PAGE1 0x62
#define NIC_PAGE0DMAWRITE 0x12
#define NIC_PAGE2DMAWRITE 0x92
#define NIC_REMOTEDMAWR 0x12
#define NIC_REMOTEDMARD 0x0A
#define NIC_ABORTDMAWR 0x32
#define NIC_ABORTDMARD 0x2A
#define NIC_PAGE0STOP 0x21
#define NIC_PAGE1STOP 0x61
#define NIC_TRANSMIT 0x26
#define NIC_TXINPROGRESS 0x04
/* Interrupt Mask Register Bits */
#define NIC_MASKBYTE 0x00
#define NIC_UNMASKBYTE 0x1f
/* Interrupt Status Register Bits */
#define NIC_PACKETREADY 0x15
#define NIC_RECVERROR 0x14
#define NIC_RDC 0x40
#define NIC_TXCOMPLETE 0x0A
#define NIC_TRANSMITERROR 0x08
#define NIC_OVW 0x10
#define NIC_RXERR 0x04
#define NIC_RX 0x01
#define NIC_REQINT 0x7F
/* Transmit Status Flag Bits */
#define SENDINGPAGEONE 0x01
#define USEPAGEONE 0x02
#define PAGETWOWAITING 0x04
/* Transmit Status Register Bits */
#define NIC_COLLISIONS 0x04
#define NIC_EXCESSCOLLISIONS 0x08
#define NIC_CARRIERSENSELOST 0x10
#define NIC_FIFOUNDERRUN 0x20
#define NIC_CDHEARTBEAT 0x40
#define NIC_OUTOFWINDOWCOLL 0x80
/* Receive Status Register Bits */
#define NIC_CRCERROR 0x02
#define NIC_FRAMECRCERROR 0x06
#define NIC_FIFOOVERRUNERROR 0x08
#define NIC_MISSEDPACKETERROR 0x10
/* Receive Configuration Bits */
#define NIC_SAVEERRORS 0x01
#define NIC_SAVERUNTS 0x02
#define NIC_BROADCAST 0x04
#define NIC_MULTICAST 0x08
#define NIC_PROMISCUOUS 0x10
#define NIC_MONITOR 0x20
/* Transmit Configuration Register Bits */
#define NIC_INTLOOPBACK 0x02
#define NIC_EXTLOOPBACK 0x04
/* Data Configuration Register Bits */
#define NIC_NORMALDATACONFIG 0x49
#define PSTART 0x4C
#define PSTOP 0x80
#define RAMPSTART 0x0C
#define RAMPSTOP 0x40
#define RPACKET 4
/*===[ Type definitions ]==================================================*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Get Configuration Info Structure.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
typedef struct _GetConfigInfo_ {
UINT16 Socket;
UINT16 Attributes;
UINT8 Vcc;
UINT8 Vpp1;
UINT8 Vpp2;
UINT8 IntType;
UINT32 ConfigBase;
UINT8 Status;
UINT8 Pin;
UINT8 Copy;
UINT8 ConfigIndex;
UINT8 Present;
UINT8 FirstDevType;
UINT8 FuncCode;
UINT8 SysInitMask;
UINT8 ManufCode[4];
/* UINT16 ManufCode;
UINT16 ManufInfo; */
UINT8 CardValues;
UINT8 AssignedIRQ;
UINT16 IRQAttributes;
UINT16 BasePort1;
UINT8 NumPorts1;
UINT8 Attributes1;
UINT16 BasePort2;
UINT8 NumPorts2;
UINT8 Attributes2;
UINT8 IOAddrLines;
} GetConfigInfo;
typedef struct _HW8390hdr_
{
UINT8 RReceiveStatus;
UINT8 RNextBuffer;
UINT16 RByteCount;
} HW8390hdr;
typedef struct _DRIVER_DATA_
{
UINT8 *NICRAMSegmentBase;
UINT8 *NICRAMSegmentLimit;
UINT8 *NICRAMReceiveRingStart;
UINT32 TxStartTime;
UINT32 TransmitSize1;
UINT32 TransmitSize2;
UINT32 RxFragments;
UINT32 SkipValue;
int TotalBytes;
UINT32 RetryCounter;
void *BusTag;
UINT8 Control1Value;
UINT8 Control2Value;
UINT8 TransmitStatusFlag;
UINT8 ReceiveStatusTest;
UINT8 NextPage;
UINT8 RetryTxFlag;
UINT8 OverflowRestartFlag;
UINT8 FirstTimeInit;
UINT8 TransmitPage0;
UINT8 TransmitPage1;
UINT8 CRCWorkArea[6];
UINT8 PCMCIAFlag;
UINT8 Align0[3]; /* TNL 9/21/95 Changed from Align0[2] */
/* NE2000 I/O Register Values */
void *Control1; /* Shared RAM, IO Base + 0 */
void *Control2; /* Shared RAM, IO Base + 5 */
void *Prom; /* Shared RAM, IO Base + 8 */
void *Command; /* IO Base + 0 (or 0x10) */
void *PageStart; /* IO Base + 1 (or 0x11) */
void *PageStop; /* IO Base + 2 (or 0x12) */
void *Boundary; /* IO Base + 3 (or 0x13) */
void *TransmitStatus; /* IO Base + 4 (or 0x14) */
void *TransmitByteCount0; /* IO Base + 5 (or 0x15) */
void *TransmitByteCount1; /* IO Base + 6 (or 0x16) */
void *InterruptStatus; /* IO Base + 7 (or 0x17) */
void *RemoteStartAddress0; /* IO Base + 8 (or 0x18) */
void *RemoteStartAddress1; /* IO Base + 9 (or 0x19) */
void *RemoteByteCount0; /* IO Base + A (or 0x1A) */
void *RemoteByteCount1; /* IO Base + B (or 0x1B) */
void *ReceiveConfiguration; /* IO Base + C (or 0x1C) */
void *TransmitConfiguration; /* IO Base + D (or 0x1D) */
void *DataConfiguration; /* IO Base + E (or 0x1E) */
void *InterruptMask; /* IO Base + F (or 0x1F) */
void *NICData; /* IO Base + 0x10 (or 0x20) */
void *Reset; /* IO Base + 0x1f (or NA ) */
#define PhysicalReg0 PageStart
#define TransmitPage TransmitStatus
#define NumberCollisions TransmitByteCount0
#define FIFO TransmitByteCount1
#define Current InterruptStatus
#define ReceiveStatus ReceiveConfiguration
#define CurrentDMA0 RemoteStartAddress0
#define CurrentDMA1 RemoteStartAddress1
#define MulticastAddrReg RemoteStartAddress0
#define TallyCounter0 TransmitConfiguration
#define TallyCounter1 DataConfiguration
#define TallyCounter2 InterruptMask
#define SizeOfCRCField 4
/* Look ahead buffer. Max lookahead size + max mac hdr + 8390 hdr + */
/* a byte (rounded up to 4) for evenization overflow. */
UINT8 ReceiveHeader[128 + MAX_MAC_HEADER + 4 + 4];
/* AES ECB */
MLID_AES_ECB mlidAESECB;
/* Statistics Table */
MLID_STATS_TABLE StatsTable;
/* Generic Statistics Table Entries */
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;
/* Media Statistics Table Entries */
StatTableEntry TxOKSingleCollisionTable;
StatTableEntry TxOKMultipleCollisionsTable;
StatTableEntry TxOKButDeferredTable;
StatTableEntry TxAbortLateCollisionTable;
StatTableEntry TxAbortExcessCollisionsTable;
StatTableEntry TxAbortCarrierSenseTable;
StatTableEntry TxAbortExDeferralTable;
StatTableEntry RxAbortFrameAlignmentTable;
/* Custom Statistics Table Entries */
StatTableEntry UnderrunErrorTable;
StatTableEntry TransmitTimeoutTable;
StatTableEntry RxPagingErrorTable;
StatTableEntry RxFIFOOverrunErrorTable;
StatTableEntry RxMissedPacketTable;
StatTableEntry GotNothingTable;
StatTableEntry UnsupportedFrameTable;
StatTableEntry UnsupportedMulticastTable;
StatTableEntry BackToBackSendTable;
StatTableEntry EnqueueSendTable;
/* Generic counters */
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;
/* Media counters */
UINT32 TxOKSingleCollision;
UINT32 TxOKMultipleCollisions;
UINT32 TxOKButDeferred;
UINT32 TxAbortLateCollision;
UINT32 TxAbortExcessCollisions;
UINT32 TxAbortCarrierSense;
UINT32 TxAbortExDeferral;
UINT32 RxAbortFrameAlignment;
/* Custom counters */
UINT32 UnderrunErrorCount;
UINT32 TransmitTimeoutCount;
UINT32 RxPagingErrorCount;
UINT32 RxFIFOOverrunErrorCount;
UINT32 RxMissedPacketCount;
UINT32 GotNothingCount;
UINT32 UnsupportedFrameCount;
UINT32 UnsupportedMulticastCount;
UINT32 BackToBackSendCount;
UINT32 EnqueueSendCount;
} DRIVER_DATA;
/* Parameter Option Description Structures */
struct
{
UINT32 OptionCount;
UINT32 UNumOptVal[24];
} MemOptionList =
{24, {0x0d0000, 0x0d4000, 0x0d8000, 0x0dc000,
0x0c0000, 0x0c4000, 0x0c8000, 0x0cc000,
0x0e0000, 0x0e2000, 0x0e4000, 0x0e6000,
0x0e8000, 0x0ea000, 0x0ec000, 0x0ee000,
0x0f0000, 0x0f2000, 0x0f4000, 0x0f6000,
0x0f8000, 0x0fa000, 0x0fc000, 0x0fe000}};
struct
{
UINT32 OptionCount;
UINT32 UNumOptVal[7];
} IoOptionList = {7, {0x300, 0x320, 0x340, 0x360, 0x240, 0x280, 0x2c0}};
struct
{
UINT32 OptionCount;
UINT32 UNumOptVal[9];
} IntOptionList = {9, {3, 2, 4, 5, 9, 10, 11, 12, 15}};
struct
{
UINT32 OptionCount;
UINT32 UNumOptVal[8];
} SlotsWithMyBoard = {0, {0, 0, 0, 0, 0, 0, 0, 0}};
DRIVER_OPTION MemOption =
{ NULL, NULL, (PARAMETER_OPTIONS *)&MemOptionList, 0, 0, MEMPARAM,
OPTIONALPARAM | ENUMPARAM, };
DRIVER_OPTION IoOption =
{ &MemOption, NULL, (PARAMETER_OPTIONS *)&IoOptionList, 0, 0, PORTPARAM,
REQUIREDPARAM | ENUMPARAM, };
DRIVER_OPTION IntOption =
{ &IoOption, NULL, (PARAMETER_OPTIONS *)&IntOptionList, 0, 0, INTPARAM,
REQUIREDPARAM | ENUMPARAM, };
DRIVER_OPTION SlotOption =
{ NULL, NULL, (PARAMETER_OPTIONS *)&SlotsWithMyBoard, 0, 0, SLOTPARAM,
REQUIREDPARAM | ENUMPARAM, };
/*===[ Include files specific Ethernet MLIDs ]===========================*/
#include "ethertsm.h"
/*===[ Global variables ]==================================================*/
MEON_STRING CHSMSPEC[] = {CNE2000_SPECVER_TXTMSG};
MEON_STRING NICShortName[] = {CNE2000_SHORTNAME_TXTMSG};
/* DriverMessages will be filled in by MSM(<TSM>RegisterHSM) to point */
/* to message enabled messages. */
MEON **DriverMessages = NULL;
#define NUM_OF_PROD_ID 2
MEON NE2000ProdID[8] = {0x8f, 0x00, 0x07, 0x2A,
0xA4, 0x00, 0x02, 0x00};
/* Data pointers needed for NESL event production */
EPB *NESL_EPBPtr = NULL;
NESL_ECB *NESLServiceResumeNECBPtr = NULL;
BOOLEAN NESLRegisterDone = FALSE;
/* Driver Data Space template. MSMRegisterHardwareOptions will initialize */
/* each adapter data space with the values in this template. */
#define NUMBER_OF_GENERICS 20L
#define NUMBER_OF_MEDIAS 8L
#define NUMBER_OF_CUSTOMS 10L
DRIVER_DATA DriverDataTemplate =
{
NULL, /* NICRAMSegmentBase */
NULL, /* NICRAMSegmentLimit */
NULL, /* NICRAMReceiveRingStart */
0, /* TxStartTime; */
0, /* TransmitSize1; */
0, /* TransmitSize2; */
0, /* RxFragments */
0, /* SkipValue */
0, /* TotalBytes */
0, /* RetryCounter */
NULL, /* BusTag */
0, /* Control1Value */
0, /* Control2Value */
0x0002, /* TransmitStatusFlag; */
0x4E, /* ReceiveStatusTest */
PSTART + 1, /* NextPage; */
0, /* RetryTxFlag; */
0, /* OverflowRestartFlag; */
1, /* FirstTimeInit; */
0xC0, /* TransmitPage0 */
0xC6, /* TransmitPage1 */
{0}, /* CRCWorkArea[6]; */
0, /* PCMCIA Flag */
{0}, /* Align0[3]; */
/* NE2000 I/O Register Values */
NULL, /* Control1 */
NULL, /* Control2 */
NULL, /* Prom */
NULL, /* Command; IO Base + 0 */
NULL, /* PageStart; IO Base + 1 */
NULL, /* PageStop; IO Base + 2 */
NULL, /* Boundary; IO Base + 3 */
NULL, /* TransmitStatus; IO Base + 4 */
NULL, /* TransmitByteCount0; IO Base + 5 */
NULL, /* TransmitByteCount1; IO Base + 6 */
NULL, /* InterruptStatus; IO Base + 7 */
NULL, /* RemoteStartAddress0; IO Base + 8 */
NULL, /* RemoteStartAddress1; IO Base + 9 */
NULL, /* RemoteByteCount0; IO Base + 10 */
NULL, /* RemoteByteCount1; IO Base + 11 */
NULL, /* ReceiveConfiguration; IO Base + 12 */
NULL, /* TransmitConfiguration; IO Base + 13 */
NULL, /* DataConfiguration; IO Base + 14 */
NULL, /* InterruptMask; IO Base + 15 */
NULL, /* NICData; IO Base + 16 */
NULL, /* Reset; IO Base + 1f */
/* Look ahead buffer. ReceiveHeader[128] */
{0},
/* AES ECB, MLID_AES_ECB mlidAESECB */
{
NULL, /* NextLink */
NULL, /* fn ptr */
AES_TYPE_PROCESS_CONTINUOUS, /* type */
1000, /* interval in ms */
NULL, /* reserved */
{0},
},
/* Statistics Table */
{
0x04, /* StatisticsMajVer; */
0x00, /* StatisticsMinVer; */
NUMBER_OF_GENERICS, /* StatsTable->MNumGenericCounters */
(StatTableEntry (*)[])&DriverDataTemplate.TotalTxPacketTable,
/* StatsTable->MGenericCountsPtr */
NUMBER_OF_MEDIAS, /* StatsTable->MNumMediaCounters */
(StatTableEntry (*)[])&DriverDataTemplate.TxOKSingleCollisionTable,
/* StatsTable->MMediaCountersPtr */
NUMBER_OF_CUSTOMS, /* StatsTable->MNumCustomCounters */
(StatTableEntry (*)[])&DriverDataTemplate.UnderrunErrorTable
}, /* StatsTable->MCustomCountersPtr */
/* Generic Statistics Table Entries */
{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 */
/* Media Statistics Table Entries */
{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 */
/* Custom Statistics Table Entries */
{ODI_STAT_UINT32, /* UnderrunErrorTable->StatUseFlag */
&DriverDataTemplate.UnderrunErrorCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* TransmitTimeoutTable->StatUseFlag */
&DriverDataTemplate.TransmitTimeoutCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* RxPagingErrorTable->StatUseFlag */
&DriverDataTemplate.RxPagingErrorCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* RxFIFOOverrunErrorTable->StatUseFlag */
&DriverDataTemplate.RxFIFOOverrunErrorCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* RxMissedPacketTable->StatUseFlag */
&DriverDataTemplate.RxMissedPacketCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* GotNothingTable->StatUseFlag */
&DriverDataTemplate.GotNothingCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* UnsupportedFrameTable->StatUseFlag */
&DriverDataTemplate.UnsupportedFrameCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* UnsupportedMulticastTable->StatUseFlag */
&DriverDataTemplate.UnsupportedMulticastCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* BackToBackTable->StatUseFlag */
&DriverDataTemplate.BackToBackSendCount, /* ->StatCounter */
NULL}, /* ->StatString */
{ODI_STAT_UINT32, /* EnqueueSendTable->StatUseFlag */
&DriverDataTemplate.EnqueueSendCount, /* ->StatCounter */
NULL}, /* ->StatString */
/* Generic counters */
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, /* TotalTxOKByteCountLow; */
0, /* TotalTxOKByteCountHigh; */
0, /* TotalRxOKByteCountLow; */
0, /* TotalRxOkByteCountHigh; */
0, /* TotalGroupAddrTxCount; */
0, /* TotalGroupAddrRxCount; */
0, /* AdapterResetCount; */
0, /* AdapterOprTimeStamp; */
0, /* QDepth; */
/* Media counters */
0, /* TxOKSingleCollision; */
0, /* TxOKMultipleCollisions; */
0, /* TxOKButDeferred; */
0, /* TxAbortLateCollision; */
0, /* TxAbortExcessCollisions; */
0, /* TxAbortCarrierSense; */
0, /* TxAbortExDeferral; */
0, /* RxAbortFrameAlignment; */
/* Custom counters */
0, /* UnderrunErrorCount; */
0, /* TransmitTimeoutCount; */
0, /* RxPagingErrorCount; */
0, /* RxFIFOOverrunErrorCount; */
0, /* RxMissedPacketCount; */
0, /* GotNothingCount; */
0, /* UnsupportedFrameCount; */
0, /* UnsupportedMulticastCount; */
0, /* BackToBackSendCount; */
0, /* EnqueueSendCount; */
};
/*===[ Function prototypes ]=============================================== */
void DriverSend(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
TCB *tcb,
UINT32 bytesToSend,
void *phystcb);
void DriverISR(
DRIVER_DATA *driverData);
ODISTAT DriverReset(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
OPERATION_SCOPE operationScope);
ODISTAT DriverShutdown(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
UINT32 shutdownType,
OPERATION_SCOPE operationScope);
ODISTAT DriverMulticastChange(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
GROUP_ADDR_LIST_NODE *mcTable,
UINT32 numEntries,
UINT32 funAddrBits);
ODISTAT DriverPromiscuousChange(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
UINT32 changeTo);
BOOLEAN DriverDisableInterrupt(
DRIVER_DATA *driverData,
BOOLEAN flag);
void DriverEnableInterrupt(
DRIVER_DATA *driverData);
ODISTAT DriverTestHardware(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable);
UINT32 CalculateHash(GROUP_ADDR_LIST_NODE *multiaddress);
void ModifyNICHashTableBit(
DRIVER_DATA *driverData,
UINT32 BitIndex);
void DriverCallback(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable);
void CFixUpStatStrings(DRIVER_DATA *driverData);
/*===[ DriverParameterBlock ]=============================================== */
DRIVER_PARM_BLOCK DriverParameters =
{
sizeof(DRIVER_PARM_BLOCK),/* DriverParameterSize */
NULL, /* DriverInitParamPointer. */
0, /* DriverModuleHandle set by MSM; */
NULL, /* *DriverBoardPointer Set by MSM */
NULL, /* *DriverAdapterPointer Set by MSM */
&DriverConfigTemplate, /* *DriverConfigTemplatePointer; */
0, /* DriverFirmwareSize Not used */
NULL, /* *DriverFirmwareBuffer Not used */
0, /* DPB_Reserved0 */
0, /* DPB_Reserved1 */
0, /* DPB_Reserved2 */
0, /* DPB_Reserved3 */
sizeof(DRIVER_DATA), /* DRIVER_DATASize; */
&DriverDataTemplate, /* *DRIVER_DATATemplatePtr; */
(UINT32)&(((DRIVER_DATA *)NULL)->StatsTable), /* DriverStatisticsTableOffset; */
0, /* DriverEndOfChainFlag; */
0, /* DriverSendWantsECBs; */
-1, /* DriverMaxMulticast; */
0, /* DriverNeedsBelow16Meg; */
NULL,
NULL,
DriverISR,
DriverMulticastChange,
NULL, /* DriverPoll */
DriverReset,
DriverSend,
DriverShutdown,
NULL, /* DPB_Reserved4 */
DriverPromiscuousChange,
NULL, /* DriverStatisticsChange */
NULL, /* DriverRxLookAheadChange */
NULL, /* DriverManagement */
DriverEnableInterrupt,
DriverDisableInterrupt,
NULL, /* DriverISR2 */
&DriverMessages, /* DriverMessagesPtr */
&CHSMSPEC, /* HSM Specification Version */
NULL, /* DrvierPriorityQueue */
NULL /* DriverDisableInterrupt2Ptr */
};
MLID_CONFIG_TABLE DriverConfigTemplate =
{
CNE2000_CONFIGSIG_TXTMSG, /* MLIDCFG_Signature[26]; */
0x01, /* MLIDCFG_MajorVersion; */
0x21, /* MLIDCFG_MinorVersion; */
{0xff,0xff,0xff,0xff,0xff,0xff}, /* MLIDCFG_NodeAddress[ADDR_SIZE]; */
0xAC48, /* MLIDCFG_ModeFlags; */
0x0000, /* MLIDCFG_BoardNumber; */
0x0000, /* MLIDCFG_BoardInstance; */
0x000005ea, /* MLIDCFG_MaxFrameSize; */
0x000005dc, /* MLIDCFG_BestDataSize; */
0x000005dc, /* MLIDCFG_WorstDataSize; */
NULL, /* *MLIDCFG_CardName; */
NICShortName, /* *MLIDCFG_ShortName; */
NULL, /* *MLIDCFG_FrameTypeString; */
0x0000, /* MLIDCFG_Reserved0; */
0x0003, /* MLIDCFG_FrameID; */
0x0001, /* MLIDCFG_TransportTime; */
NULL, /* *MLIDCFG_SourceRouting; */
10, /* MLIDCFG_LineSpeed; */
18, /* MLIDCFG_LookAheadSize; */
0, /* MLIDCFG_SGCount */
0, /* MLIDCFG_Reserved1 */
0, /* MLIDCFG_PrioritySup; */
NULL, /* MLIDCFG_Reserved2; */
0, /* MLIDCFG_DriverMajorVer; */
0, /* MLIDCFG_DriverMinorVer; */
0x0000, /* MLIDCFG_Flags; */
0x000A, /* MLIDCFG_SendRetries; */
NULL, /* *MLIDCFG_DriverLink; */
0x0000, /* MLIDCFG_SharingFlags; */
0xffff, /* 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; */
0xff, /* MLIDCFG_DMALine0; */
0xff, /* MLIDCFG_DMALine1; */
NULL, /* *MLIDCFG_ResourceTag; */
NULL, /* *MLIDCFG_Config; */
NULL, /* *MLIDCFG_CommandString; */
{0}, /* MLIDCFG_LogicalName[18]; */
0x00000000, /* MLID_LinearMemory0; */
0x00000000, /* MLID_LinearMemory1; */
0x0000, /* MLIDChannelNumber */
NULL, /* MLIDCFG_DBusTag; */
1, /* MLIDCFG_DIOConfigMajor; */
0, /* MLIDCFG_DIOConfigMinor; */
};
UINT32 IoPortData[] = {0x300, 0x320, 0x340, 0x360, 0x240, 0x280, 0x2c0};
UINT32 Interrupt0Data[] = {2, 3, 4, 5, 10, 11, 12, 15};
UINT32 MemoryDecode0Data[] = {
0x0d0000, 0x0d4000, 0x0d8000, 0x0dc000,
0x0c0000, 0x0c4000, 0x0c8000, 0x0cc000,
0x0e0000, 0x0e2000, 0x0e4000, 0x0e6000,
0x0e8000, 0x0ea000, 0x0ec000, 0x0ee000,
0x0f0000, 0x0f2000, 0x0f4000, 0x0f6000,
0x0f8000, 0x0fa000, 0x0fc000, 0x0fe000};
UINT8 IntTable[] = {3, 4, 5, 2, 10, 11, 12, 15};
/*======================================================================
Procedure Name: DriverSend
Arguments:
driverData - Ptr to Our Data Space
configTable - Ptr to Our config Table.
tcb - Ptr to the TCB
bytesToSend - Has the number of bytes to send.
Returns: void
Abstract: This function will transfer the packet described by the
TCB to the NIC and initiate the send.
Notes:
=======================================================================*/
void DriverSend(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
TCB *tcb,
UINT32 bytesToSend,
void *phystcb)
{
TCB_FRAGMENT_BLOCK *fragbase;
FRAGMENT_STRUCT *fragmentptr;
UINT32 packetsize;
UINT32 i, j, oddbyte;
UINT16 tempword;
UINT8 nicstatus, *dataptr;
DriverSendTop:
#ifdef OUT_CHAR
NiosDebugCharOut ('S');
#endif /* OUT_CHAR */
/* Set DMA complete, if not set. */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_RDC);
/* Figure out which xmit buf to use next */
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
driverData->TransmitSize1 = bytesToSend;
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 0x00);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, 0x40);
}
else
{
driverData->TransmitSize2 = bytesToSend;
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 0x00);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, 0x46);
}
/* Evenize packetsize */
packetsize = tcb->TCB_DataLen;
packetsize += (packetsize & 1);
Out8(driverData->BusTag, driverData->RemoteByteCount0, (UINT8)(packetsize /* & 0xFF */ ));
Out8(driverData->BusTag, driverData->RemoteByteCount1, (UINT8)(packetsize >> 8));
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMAWR);
/* Copy Frame header to the NIC */
/* We can only copy even values to card. */
/* So if odd send all but last byte of hdr now (we will do the last */
/* byte later.) */
OutBuff16(
driverData->BusTag,
driverData->NICData,
&tcb->TCB_MediaHeader,
tcb->TCB_MediaHeaderLen / 2);
/* Setup the fragment pointers */
fragbase = tcb->TCB_FragBlockPtr;
fragmentptr = &(fragbase->TCB_Fragment);
/* Check if frame header is odd length */
if (tcb->TCB_MediaHeaderLen & 1)
{
/* The header is odd copy it plus first data byte */
oddbyte = 1;
tempword = VALUE_TO_HILO_UINT16((*((UINT8 *)(&(tcb->TCB_MediaHeader)) + tcb->TCB_MediaHeaderLen -1) << 8) |
(*(UINT8 *)fragmentptr->FragmentAddress));
Out16(
driverData->BusTag,
driverData->NICData,
tempword);
}
else oddbyte = 0;
/* Copy fragments to the NIC. */
for(i = fragbase->TCB_FragmentCount; i > 0; --i)
{
if (fragmentptr->FragmentLength == 0)
++fragmentptr;
else
{
dataptr = fragmentptr->FragmentAddress;
OutBuff16(
driverData->BusTag,
driverData->NICData,
dataptr + oddbyte,
(fragmentptr->FragmentLength - oddbyte) / 2);
if((fragmentptr->FragmentLength - oddbyte) & 1)
{
oddbyte = 1;
tempword = (dataptr[fragmentptr->FragmentLength - 1]) << 8;
while (i > 1) /* Don't illegal access off the end of the frag list */
{
++fragmentptr;
if (fragmentptr->FragmentLength != 0)
{
dataptr = fragmentptr->FragmentAddress;
tempword = tempword | dataptr[0];
break;
}
--i;
}
tempword = VALUE_TO_HILO_UINT16(tempword);
Out16(driverData->BusTag, driverData->NICData, tempword);
}
else
{
++fragmentptr;
oddbyte = 0;
}
}
}
/* Check if NIC is ready to send. */
for (nicstatus = 0, j = 0; !(nicstatus & NIC_RDC) & j < 65534;
nicstatus = In8( driverData->BusTag, driverData->InterruptStatus), j++);
if ( !nicstatus & NIC_RDC)
{
/* Can't get DMA_Complete, this is bad */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_RDC); /* Set the DMA complete */
CMSMPrintString( configTable, MSG_TYPE_RUNTIME_ERROR, CNE2000_DMAERR_MSG, 0, 0);
DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
goto DriverSendTop;
}
if (!(driverData->TransmitStatusFlag & SENDINGPAGEONE))
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
/* Send packet */
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* Note the time */
driverData->TxStartTime = CMSMGetCurrentTime();
driverData->RetryCounter = configTable->MLIDCFG_SendRetries;
driverData->TransmitStatusFlag = SENDINGPAGEONE;
/* Give TCB back to MSM (Lying Send) */
CEtherTSMFastSendComplete(driverData, tcb, 0);
#ifdef OUT_CHAR
NiosDebugCharOut ('s');
#endif /* OUT_CHAR */
return;
}
else
{
#ifdef OUT_CHAR
NiosDebugCharOut ('w');
#endif /* OUT_CHAR */
driverData->TransmitStatusFlag = PAGETWOWAITING;
CEtherTSMFastSendComplete(driverData, tcb, 0);
}
/* Junk to keep compiler happy, optimizer should remove. */
phystcb = phystcb;
}
/*=====================================================================
Procedure Name: DriverSendSharedRAM
Arguments:
driverData - Ptr to Our Data Space
configTable - Ptr to Our config Table.
tcb - Ptr to the TCB
bytesToSend - Has the number of bytes to send.
Returns: void
Abstract: This function will transfer the packet described by the
TCB to the NIC and initiate the send.
Notes:
=======================================================================*/
void DriverSendSharedRAM(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
TCB *tcb,
UINT32 bytesToSend,
void *phystcb)
{
FRAGMENTSTRUCT *fragmentptr;
UINT32 fragsize;
UINT32 i;
UINT8 *fragptr, *dataptr;
/* Figure out which xmit buf to use next */
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
driverData->TransmitSize1 = bytesToSend;
dataptr = driverData->NICRAMSegmentBase;
}
else
{
driverData->TransmitSize2 = bytesToSend;
dataptr = driverData->NICRAMSegmentBase + 0x600;
}
/* Copy Frame header to the NIC */
MovToBus16(driverData->BusTag, NULL, dataptr,
&tcb->TCB_MediaHeader, tcb->TCB_MediaHeaderLen / 2);
if (tcb->TCB_MediaHeaderLen & 1)
{
MovToBus8 (driverData->BusTag, NULL, dataptr + tcb->TCB_MediaHeaderLen - 1,
((UINT8 *)&tcb->TCB_MediaHeader) + tcb->TCB_MediaHeaderLen - 1, 1);
}
dataptr += tcb->TCB_MediaHeaderLen;
fragmentptr = &(tcb->TCB_FragBlockPtr->TCB_Fragment);
for(i = tcb->TCB_FragBlockPtr->TCB_FragmentCount; i > 0; --i)
{
fragptr = fragmentptr->FragmentAddress;
fragsize = fragmentptr->FragmentLength;
MovToBus16(driverData->BusTag, NULL, dataptr,
fragptr, fragsize / 2);
if (fragsize & 1)
MovToBus8 (driverData->BusTag, NULL, dataptr + fragsize - 1,
fragptr + fragsize - 1, 1);
++fragmentptr;
dataptr += fragsize;
}
if (!(driverData->TransmitStatusFlag & SENDINGPAGEONE))
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
/* Send packet */
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* Note the time */
driverData->TxStartTime = CMSMGetCurrentTime();
driverData->RetryCounter = configTable->MLIDCFG_SendRetries;
driverData->TransmitStatusFlag = SENDINGPAGEONE;
/* Give TCB back to MSM (Lying Send) */
CEtherTSMFastSendComplete(driverData, tcb, 0);
return;
}
else
{
driverData->TransmitStatusFlag = PAGETWOWAITING;
CEtherTSMFastSendComplete(driverData, tcb, 0);
}
/* Junk to keep compiler happy, optimizer should remove. */
phystcb = phystcb;
configTable = configTable;
}
/*======================================================================
Procedure Name: DriverISR
Arguments: driverData - ptr to our local data spaace.
Returns: void
Abstract: This routine handles packet reception and transmit
complete interrupts.
Notes:
========================================================================*/
void DriverISR(
DRIVER_DATA *driverData)
{
CONFIG_TABLE *configTable;
int i, j, k;
UINT32 rcvStatus, status, StartTime, curtime, elapsedtime;
UINT8 nicstatus, currentcommand, currentpage, newboundary;
UINT8 oddbyte;
UINT16 bytecount, tempword;
RCB *rcb;
UINT32 pktsize = 0, startbyte, numbytes, fragsize;
FRAGMENTSTRUCT *fragmentptr;
UINT8 *dataptr, *fragptr, *tempptr;
HW8390hdr *HW_hdr;
/* 970701 PSK - Check physical board shutdown status, not logical board.
if ((DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard->
MLIDCFG_SharingFlags) & MS_SHUTDOWN_BIT)
*/
/* Is the driver shutdown? */
if ( DADSP_TO_CMSMADSP(driverData)->CMSMStatusFlags & SHUTDOWN )
/* If so, clear any interrupts that the NIC is requesting and exit. */
{
Out8(driverData->BusTag, driverData->InterruptStatus, In8(driverData->BusTag, driverData->InterruptStatus));
#ifdef OUT_CHAR
NiosDebugCharOut ('x');
#endif /* OUT_CHAR */
return;
}
else
{
PollAgain:
/* Get NIC status */
nicstatus = In8(driverData->BusTag, driverData->InterruptStatus);
/* Check for packet ready to be received. */
if(nicstatus & NIC_PACKETREADY)
{
if(nicstatus & NIC_RECVERROR)
{
/* 950228 MCD removed a "switch" stmt here and replaced it with the */
/* following "if" tests. These tests MUST be done in this order; */
/* do not change them. */
/* We have Errors, Handle them. */
if (nicstatus & NIC_OVW) /* Buffer Overflow */
{
#ifdef OUT_CHAR
NiosDebugCharOut ('O');
#endif /* OUT_CHAR */
++(driverData->PacketRxOverflowCount);
/* Save Tx active bit */
currentcommand = In8(driverData->BusTag, driverData->Command);
/* Put NIC in STOP mode */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
/* Stop the remote DMA */
Out8(driverData->BusTag, driverData->RemoteByteCount0, 0);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 0);
/* Idle for about 2 ms to let current Tx or Rx finish */
StartTime = CMSMGetMicroTimer();
for (elapsedtime = 0; elapsedtime < 2000;
elapsedtime = ((curtime = CMSMGetMicroTimer()) - StartTime > 0)
? (curtime - StartTime) : (StartTime - curtime));
/* Reset the overflow bit */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_OVW);
/* If Tx'ing during overflow set flag so can restart Tx later */
if ((currentcommand & NIC_TXINPROGRESS) &&
!(In8(driverData->BusTag, driverData->InterruptStatus) & NIC_TXCOMPLETE))
++(driverData->RetryTxFlag);
/* Put NIC into Loopback mode until we empty receive buffers */
/* Note that we are using external loopback, this fixes */
/* overflow hangs on rev C 8390s in IPXLOAD test */
Out8(driverData->BusTag, driverData->TransmitConfiguration, NIC_EXTLOOPBACK);
/* Re-enable card in loopback mode */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
++(driverData->OverflowRestartFlag);
/* see if more packets are waiting */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
currentpage = In8(driverData->BusTag, driverData->InterruptStatus);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
if(currentpage != (driverData->NextPage))
goto ReceiveNextPacket;
goto TestForLoopback;
}
else if (nicstatus & NIC_RXERR) /* Receive Error */
{
#ifdef OUT_CHAR
NiosDebugCharOut ('o');
#endif /* OUT_CHAR */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_RXERR);
if (In8(driverData->BusTag, driverData->ReceiveStatus) & NIC_FIFOOVERRUNERROR)
{
++(driverData->RxFIFOOverrunErrorCount); /* Inform diagnostics */
++(driverData->PacketRxMiscErrorCount);
}
driverData->RxAbortFrameAlignment += (i = In8(driverData->BusTag, driverData->TallyCounter0));
driverData->PacketRxMiscErrorCount += i;
driverData->ChecksumErrorCount += In8(driverData->BusTag, driverData->TallyCounter1);
driverData->RxMissedPacketCount += (i = In8(driverData->BusTag, driverData->TallyCounter2));
driverData->PacketRxMiscErrorCount += i;
goto PollAgain;
}
configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
}
else /* Receive with no error */
{
#ifdef OUT_CHAR
NiosDebugCharOut ('R');
#endif /* OUT_CHAR */
/* Is there data to receive? */
/* Switch to page1 registers */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
currentpage = In8(driverData->BusTag, driverData->Current);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
if (currentpage == driverData->NextPage)
{
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_RX);
++driverData->GotNothingCount;
goto PollAgain;
}
ReceiveNextPacket:
/* Clear Receive status */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_RX);
if (driverData->NICRAMSegmentBase == 0)
/* Card is not in shared RAM mode */
{
/****************************************************************\
* *
* Time to read in the packet received. *
* *
* Read in 4 byte buffers header, 14 byte Ethernet header and *
* following X bytes into ReceiveHeader to properly analyse *
* packet length and media type and do look ahead. *
* *
\****************************************************************/
/* Time to receive the packet. */
/* Setup the Remote Start Address of NIC */
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 00);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, (UINT8)(driverData->NextPage));
/* Calculate evenized (hdr size + 4 byte 8390 hdr) */
bytecount = ((DADSP_TO_CMSMADSP(driverData)->CMSMMaxFrameHeaderSize) + 5) & ~0x01;
Out8(driverData->BusTag, driverData->RemoteByteCount0, (UINT8)bytecount /* & 0xFF */);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 00);
/* Issue the Remote Read DMA command to the NIC. */
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMARD);
/* Read in the frame header. */
status = InBuff16(
driverData->ReceiveHeader,
driverData->BusTag,
driverData->NICData,
bytecount / 2);
HW_hdr = (HW8390hdr *) driverData->ReceiveHeader;
if(HW_hdr->RReceiveStatus & driverData->ReceiveStatusTest)
{
/* We have a paging Error. */
goto PagingError;
}
/* Number of bytes in incoming packet is the harware reported value minus */
/* the four byte hardware header. */
bytecount = VALUE_FROM_LOHI_UINT16(GET_UINT16(&(HW_hdr->RByteCount)));
/* If # pages > 8 the reported length is wrong (it is MOD 2048) */
/* so let's correct it. */
if ((i = ((int)HW_hdr->RNextBuffer - (int)driverData->NextPage)) < 0)
i += PSTOP - PSTART;
if (i > 8)
bytecount += (--i >> 3) << 11;
pktsize = (UINT16)bytecount - 4; /* HW hdr size */
/* Figure out new NextPage and see if we agree with the HW */
/* Round up to include the four byte CRC and the rest of the */
/* current page. */
bytecount += 4 /* size of CRC */ + 0xFF;
/* High order byte of bytecount now has number of pages used, */
/* add this to NextPage to calc new NextPage. */
bytecount += driverData->NextPage << 8;
/* Adjust if we wrapped. */
if((bytecount >> 8) >= PSTOP)
{
/* 950228 MCD fixed the following calculation. */
bytecount += (PSTART - PSTOP) << 8;
}
if((bytecount >> 8) != HW_hdr->RNextBuffer)
{
/* We have a paging Error. */
goto PagingError;
}
/* Update the Boundary */
driverData->NextPage = (UINT8)(bytecount >> 8);
/* Let the upper level guys decide if (and where) we want the packet. */
rcvStatus = (HW_hdr->RReceiveStatus >> 1) & 0x03;
rcb = CEtherTSMGetRCB(
driverData,
(UINT8 *)(&(driverData->ReceiveHeader[RPACKET])),
pktsize,
rcvStatus,
&startbyte,
&numbytes);
if(rcb)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('G');
#endif /* OUT_CHAR */
/* 950317 MCD added this test for protection */
if (numbytes > 0)
{
startbyte += sizeof(HW8390hdr);
driverData->TotalBytes = numbytes;
/* The next piece is complicated. Here is the theory. If startbyte */
/* and numbytes are both even we are OK. If startbyte is even and */
/* numbytes is odd we need to inc numbytes so we can read an even */
/* number of bytes. If startbyte is odd and numbytes is even we need */
/* to dec startbyte and inc numbytes by 2 to start even and read an */
/* even number of bytes. If both start byte and numbytes is odd we */
/* need to dec startbyte and inc numbytes by one. */
if (startbyte & 1)
{
--startbyte;
driverData->SkipValue = 1;
++numbytes;
}
numbytes += (numbytes & 1);
Out8(driverData->BusTag, driverData->RemoteStartAddress0, (UINT8)(startbyte /* 0xFF */));
Out8(driverData->BusTag, driverData->RemoteByteCount0, (UINT8)(numbytes /* 0xFF */));
Out8(driverData->BusTag, driverData->RemoteByteCount1, (UINT8)(numbytes >> 8));
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMARD);
fragmentptr = (FRAGMENTSTRUCT *)(&(rcb->RCBFragStruct));
oddbyte = 0;
for(i = rcb->RCBFragCount; i > 0 && driverData->TotalBytes > 0; --i)
{
if (fragmentptr->FragmentLength == 0)
++fragmentptr;
else
{
dataptr = fragmentptr->FragmentAddress;
fragsize = fragmentptr->FragmentLength - oddbyte;
if ((driverData->TotalBytes - (int)fragsize) <= 0)
{
fragsize = driverData->TotalBytes - oddbyte;
}
driverData->TotalBytes -= fragsize + oddbyte;
if( driverData->SkipValue == 1)
{
tempword = In16( driverData->BusTag, driverData->NICData);
HOST_TO_HILO_UINT16(&tempword);
tempptr = dataptr + oddbyte;
*tempptr = (UINT8) tempword;
driverData->SkipValue = 0;
++dataptr;
--fragsize;
}
status = InBuff16(
dataptr + oddbyte,
driverData->BusTag,
driverData->NICData,
(UINT32)fragsize / 2);
if(fragsize & 1)
{
tempword = In16(driverData->BusTag, driverData->NICData);
HOST_TO_HILO_UINT16(&tempword);
((UINT8 *)dataptr)[fragsize + oddbyte - 1] = (UINT8)(tempword >> 8);
j = i;
while (j > 1) /* Don't illegal access off the end of the frag list */
{
++fragmentptr;
if (fragmentptr->FragmentLength != 0)
{
oddbyte = 1;
dataptr = fragmentptr->FragmentAddress;
dataptr[0] = (UINT8)tempword;
j = 0;
}
else
{
--i;
--j;
}
}
}
else
{
oddbyte = 0;
++fragmentptr;
}
}
}
}
#ifdef OUT_CHAR
NiosDebugCharOut ('r');
#endif /* OUT_CHAR */
CEtherTSMFastRcvComplete(
driverData,
rcb);
}
newboundary = driverData->NextPage;
--newboundary;
if(newboundary < PSTART)
{
newboundary = PSTOP - 1;
}
Out8(driverData->BusTag, driverData->Boundary, newboundary);
/* see if more packets are waiting */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
currentpage = In8(driverData->BusTag, driverData->InterruptStatus);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
if(currentpage != (driverData->NextPage))
{
goto ReceiveNextPacket;
}
}
else
{
/* Receive a packet, shared RAM mode. */
HW_hdr = (HW8390hdr *)(driverData->NICRAMSegmentBase + (driverData->NextPage << 8));
dataptr = (UINT8 *)HW_hdr + sizeof(HW8390hdr);
if (HW_hdr->RReceiveStatus & driverData->ReceiveStatusTest)
{
/* We have a paging Error. */
goto PagingError;
}
/* Number of bytes in incoming packet is the harware reported value minus */
/* the four byte hardware header. */
bytecount = VALUE_FROM_LOHI_UINT16(GET_UINT16(&(HW_hdr->RByteCount)));
/* If # pages > 8 the reported length is wrong (it is MOD 2048) */
/* so let's correct it. */
if ((i = ((int)HW_hdr->RNextBuffer - (int)driverData->NextPage)) < 0)
i += RAMPSTOP - RAMPSTART;
if (i > 8)
bytecount += (--i >> 3) << 11;
pktsize = (UINT16)bytecount - 4; /* HW hdr size */
/* Figure out new NextPage and see if we agree with the HW */
/* Round up to include the four byte CRC and the rest of the */
/* current page. */
bytecount += 4 /* size of CRC */ + 0xFF;
/* High order byte of bytecount now has number of pages used, */
/* add this to NextPage to calc new NextPage. */
bytecount += driverData->NextPage << 8;
/* Adjust if we wrapped. */
if((bytecount >> 8) >= RAMPSTOP)
{
bytecount += (RAMPSTART - RAMPSTOP) << 8;
}
if((bytecount >> 8) != HW_hdr->RNextBuffer)
{
/* We have a paging Error. */
goto PagingError;
}
/* Update the Boundary */
driverData->NextPage = (UINT8)(bytecount >> 8);
/* Let the upper level guys decide if (and where) we want the packet. */
rcvStatus = (HW_hdr->RReceiveStatus >> 1) & 0x03;
rcb = CEtherTSMGetRCB(
driverData,
(UINT8 *)dataptr,
pktsize,
rcvStatus,
&startbyte,
&numbytes);
if(rcb)
{
/* This test is for protection */
if (numbytes > 0)
{
driverData->TotalBytes = numbytes;
dataptr += startbyte;
fragmentptr = (FRAGMENTSTRUCT *)(&(rcb->RCBFragStruct));
for(i = rcb->RCBFragCount; i > 0 && driverData->TotalBytes > 0; --i)
{
if (fragmentptr->FragmentLength == 0)
++fragmentptr;
else
{
fragptr = fragmentptr->FragmentAddress;
fragsize = fragmentptr->FragmentLength;
/* Change next line from "< 0" to "<= 0" */
if ((driverData->TotalBytes - (int)fragsize) <= 0)
{
fragsize = driverData->TotalBytes;
}
driverData->TotalBytes -= fragsize;
if(dataptr + fragsize <= driverData->NICRAMSegmentLimit)
{
MovFromBus16(fragptr, driverData->BusTag,
NULL, dataptr, fragsize / 2);
if (fragsize & 1)
MovFromBus8 (fragptr + fragsize - 1, driverData->BusTag, NULL,
dataptr + fragsize - 1, 1);
dataptr += fragsize;
}
else
{
MovFromBus16(fragptr, driverData->BusTag, NULL, (void *) dataptr,
(j = (UINT8 *)driverData->NICRAMSegmentLimit - dataptr) / 2);
if (j & 1)
MovFromBus8 (fragptr + j - 1, driverData->BusTag, NULL,
dataptr + j - 1, 1);
k = fragsize - j;
MovFromBus16(fragptr + j, driverData->BusTag, NULL,
driverData->NICRAMReceiveRingStart, k / 2);
if (k & 1)
MovFromBus8 (fragptr + fragsize - 1, driverData->BusTag, NULL,
(UINT8 *)driverData->NICRAMReceiveRingStart + k - 1, 1);
dataptr = driverData->NICRAMReceiveRingStart + k;
}
++fragmentptr;
}
}
}
CEtherTSMFastRcvComplete(driverData, rcb);
}
newboundary = driverData->NextPage;
--newboundary;
if(newboundary < RAMPSTART)
{
newboundary = RAMPSTOP - 1;
}
Out8(driverData->BusTag, driverData->Boundary, newboundary);
/* see if more packets are waiting */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
currentpage = In8(driverData->BusTag, driverData->InterruptStatus);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
if(currentpage != (driverData->NextPage))
{
goto ReceiveNextPacket;
}
}
}
/* No more data in receive buffers, before we go back to PollAgain */
/* check to see if we were cleaning out the receive buffers because */
/* of a receive overflow. */
TestForLoopback:
if (!driverData->OverflowRestartFlag)
goto PollAgain;
else
{
/****************************************************************\
* *
* Now that receive buffers are empty, we can finish handling *
* the Buffer Overflow error by placing the NIC out of the *
* loopback mode and sending out the current Tx buffer if it had *
* been active at the time of overflow and got cancelled by the *
* stop command. *
* *
\****************************************************************/
#ifdef OUT_CHAR
NiosDebugCharOut ('o');
#endif /* OUT_CHAR */
Out8(driverData->BusTag, driverData->TransmitConfiguration, 0);
driverData->OverflowRestartFlag = 0;
if (!driverData->RetryTxFlag)
goto PollAgain;
else
{
/****************************************************************\
* *
* A transmit was cancelled during overflow condition. *
* Re-send it. *
* *
\****************************************************************/
#ifdef OUT_CHAR
NiosDebugCharOut ('q');
#endif /* OUT_CHAR */
driverData->RetryTxFlag = 0;
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
}
else
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage1);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize2 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize2 >> 8));
}
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* AYD 10-07-96 */
driverData->TxStartTime = CMSMGetCurrentTime();
/* TNL 7/11/95 Add next line */
configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
driverData->RetryCounter = configTable->MLIDCFG_SendRetries;
goto PollAgain;
}
}
}
else
/* Check for Transmit Complete or Error */
if(nicstatus & NIC_TXCOMPLETE)
{
/* Reset interrupt bits */
Out8(driverData->BusTag, driverData->InterruptStatus, NIC_TXCOMPLETE);
/* Check for a Transmit Error. */
if(nicstatus & NIC_TRANSMITERROR)
{
/* We have an Error. Handle it. */
#ifdef OUT_CHAR
NiosDebugCharOut ('e');
#endif /* OUT_CHAR */
if ((status = In8(driverData->BusTag, driverData->TransmitStatus)) & NIC_EXCESSCOLLISIONS)
{
++(driverData->TxAbortExcessCollisions);
++(driverData->PacketTxMiscErrorCount);
}
else if (status & NIC_FIFOUNDERRUN)
{
++(driverData->UnderrunErrorCount);
++(driverData->PacketTxMiscErrorCount);
if (status & NIC_COLLISIONS)
{
if ((i = In8(driverData->BusTag, driverData->NumberCollisions)) > 1)
driverData->TxOKMultipleCollisions += i;
else
++(driverData->TxOKSingleCollision);
}
}
if (--(driverData->RetryCounter) == 0)
goto TransmitNextPacket;
++(driverData->RetryTxCount);
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
}
else
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage1);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize2 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize2 >> 8));
}
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* AYD 10-07-96 */
driverData->TxStartTime = CMSMGetCurrentTime();
goto PollAgain;
}
else
{
/* We had a Transmit complete. */
#ifdef OUT_CHAR
NiosDebugCharOut ('T');
#endif /* OUT_CHAR */
/* Increment collision counters */
if (i = In8(driverData->BusTag, driverData->NumberCollisions))
if (i > 1)
driverData->TxOKMultipleCollisions += i;
else
++(driverData->TxOKSingleCollision);
TransmitNextPacket:
++(DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount);
driverData->TxStartTime = 0;
if (driverData->TransmitStatusFlag & PAGETWOWAITING)
/****************************************************************\
* *
* We just completed a send, but there is already another *
* packet transfered to the board. We just need to issue the *
* send for it. *
* *
\****************************************************************/
{
++driverData->BackToBackSendCount;
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
}
else
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage1);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize2 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize2 >> 8));
}
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* AYD 10-07-96 */
driverData->TxStartTime = CMSMGetCurrentTime();
/* TNL 7/11/95 Add next line */
configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
driverData->RetryCounter = configTable->MLIDCFG_SendRetries;
driverData->TransmitStatusFlag ^= (USEPAGEONE | PAGETWOWAITING);
}
else
{
driverData->TransmitStatusFlag = USEPAGEONE;
}
#ifdef OUT_CHAR
NiosDebugCharOut ('t');
#endif /* OUT_CHAR */
}
}
}
return;
PagingError:
#ifdef OUT_CHAR
NiosDebugCharOut ('P');
#endif /* OUT_CHAR */
++(driverData->RxPagingErrorCount); /* Inform diagnostics */
++(driverData->PacketRxMiscErrorCount);
configTable = DADSP_TO_CMSMADSP(driverData)->CMSMDefaultVirtualBoard;
DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
}
/*=========================================================================
Procedure Name: DriverReset
Arguments:
driverData - is a ptr to the adapter data space.
framedata - is a ptr to the frame specific data.
operationScope - OP_SCOPE_ADAPTER or OP_SCOPE_LOGICAL_BOARD.
Returns: ODISTAT
SUCCESSFUL - The adapter was reset successfully.
FAIL - The adapter failed the reset.
Abstract: This routine is to initialize the adapter a leave it
in an operational state.
Notes:
==========================================================================*/
ODISTAT DriverReset(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
OPERATION_SCOPE operationScope)
{
UINT8 portvalue, temp8a, temp8b;
if (operationScope == OP_SCOPE_ADAPTER)
{
/* increment stats counter. */
++driverData->AdapterResetCount;
if (driverData->NICRAMSegmentBase == 0)
{
/* Board in I/O mode, do I/O reset stuff */
/* Do a hard reset. */
portvalue = In8(driverData->BusTag, driverData->Reset);
Slow();
Out8(driverData->BusTag, driverData->Reset, portvalue);
}
else
{
/* Board in Shared Mem Mode so do Shared Mem reset stuff */
Out8(driverData->BusTag, driverData->Control2, driverData->Control2Value);
/* Pull on the reset signal for a while */
Out8(driverData->BusTag, driverData->Control1, driverData->Control1Value | NIC_SMRESET);
Slow();
Out8(driverData->BusTag, driverData->Control1, driverData->Control1Value | !NIC_SMRESET);
}
/* Set to Page 0 registers */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
Slow();
if(driverData->FirstTimeInit)
{
/* Check if command register is alive */
portvalue = In8(driverData->BusTag, driverData->Command);
if((portvalue != 0x21) && (portvalue != 0x23))
{
/* port failure return fail */
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_BADBOARD_MSG, 0, 0);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
return ODISTAT_FAIL;
}
}
Out8(driverData->BusTag, driverData->DataConfiguration, NIC_NORMALDATACONFIG);
/* Clear RBCR0 and RBCR1 */
Out8(driverData->BusTag, driverData->RemoteByteCount0, 0x00);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 0x00);
Out8(driverData->BusTag, driverData->ReceiveConfiguration, NIC_BROADCAST);
driverData->RetryTxFlag = 0;
driverData->OverflowRestartFlag = 0;
CEtherTSMUpdateMulticast(driverData);
/* We need to be in loopback mode to prevent getting a receive during */
/* the RAM tests */
if (driverData->NICRAMSegmentBase == 0)
{
temp8a = PSTART;
temp8b = PSTOP;
}
else
{
temp8a = RAMPSTART;
temp8b = RAMPSTOP;
}
Out8(driverData->BusTag, driverData->TransmitConfiguration, NIC_INTLOOPBACK);
Out8(driverData->BusTag, driverData->PageStart, temp8a);
Out8(driverData->BusTag, driverData->Boundary, temp8a);
Out8(driverData->BusTag, driverData->PageStop, temp8b);
/* Clear interrupt bits */
Out8(driverData->BusTag, driverData->InterruptStatus, 0xff);
Out8(driverData->BusTag, driverData->InterruptMask, NIC_UNMASKBYTE);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1STOP);
Out8(driverData->BusTag, driverData->InterruptStatus, temp8a + 1); /* Current */
driverData->NextPage = temp8a + 1;
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
if(driverData->FirstTimeInit)
{
if (DriverTestHardware(driverData, configTable))
{
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
return ODISTAT_FAIL;
}
}
Out8(driverData->BusTag, driverData->TransmitPage,
driverData->TransmitPage0);
driverData->TransmitStatusFlag = USEPAGEONE;
DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount = 2;
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
Out8(driverData->BusTag, driverData->TransmitConfiguration, 0x00);
driverData->OverflowRestartFlag = 0;
return ODISTAT_SUCCESSFUL;
}
else
return ODISTAT_SUCCESSFUL;
} /* End DriverReset. */
/*======================================================================
Procedure Name: CheckForSharedRAM
Arguments: none
Returns: ODISTAT
ODISTAT_SUCCESSFUL - Card in I/O mode or
card in shared mem mode and "MEM=" present.
ODISTAT_FAIL - Doesn't happen right now but, if we find
a situation we can't deal with.
Abstract: This routine tests the card's hardware and the driver's config
table to be sure that we have all the parameters we need
and sets DriverSendPtr in the Driver Parameter Block to
point to DriverSendSharedRAM. This is necessary in and of
itself and also is used in DriverInit to tell us which
mode we are in.
Notes:
========================================================================*/
ODISTAT CheckForSharedRAM(
CONFIG_TABLE *configTable)
{
UINT8 oldVal, newVal, saveVal;
void *rsa;
/* Assume for now card is NOT shared RAM, save current value of NICCommand */
/* register and force to page 0 */
saveVal = In8(configTable->MLIDCFG_DBusTag, (void *)configTable->MLIDCFG_IOPort0);
Out8(configTable->MLIDCFG_DBusTag, (void *)configTable->MLIDCFG_IOPort0, NIC_PAGE0STOP);
Slow();
/* Read the RemoteStartAddress */
rsa = (void *)(configTable->MLIDCFG_IOPort0 + 8);
oldVal = In8(configTable->MLIDCFG_DBusTag, rsa);
/* Write a new value */
Out8(configTable->MLIDCFG_DBusTag, rsa, oldVal ^ 0x01);
Slow();
/* Try to read it back */
newVal = In8(configTable->MLIDCFG_DBusTag, rsa);
/* Put back the original value */
Out8(configTable->MLIDCFG_DBusTag, rsa, oldVal);
if (newVal == oldVal ^ 0x01)
{
/* Card is in I/O mode */
DriverParameters.DriverSendPtr = &DriverSend;
return ODISTAT_SUCCESSFUL;
}
else
{
/* Card is in shared memory mode, restore saved value */
Out8(configTable->MLIDCFG_DBusTag, (void *)(configTable->MLIDCFG_IOPort0), saveVal);
Slow();
/* Put NIC in PAGE0 mode just in case we aren't there already. */
saveVal = In8(configTable->MLIDCFG_DBusTag, (void *)(configTable->MLIDCFG_IOPort0 + 0x10));
Out8(configTable->MLIDCFG_DBusTag, (void *)(configTable->MLIDCFG_IOPort0 + 0x10), NIC_PAGE0STOP);
Slow();
/* Check to see if card is even present */
rsa = (void *)(configTable->MLIDCFG_IOPort0 + 0x10 + 8);
oldVal = In8(configTable->MLIDCFG_DBusTag, rsa);
/* Write a new value */
Out8(configTable->MLIDCFG_DBusTag, rsa, oldVal ^ 0x01);
Slow();
/* Try to read it back */
newVal = In8(configTable->MLIDCFG_DBusTag, rsa);
/* Put back the original value */
Out8(configTable->MLIDCFG_DBusTag, rsa, oldVal);
if (newVal == oldVal ^ 0x01)
{
/* Shared RAM card IS present */
DriverParameters.DriverSendPtr = &DriverSendSharedRAM;
if (configTable->MLIDCFG_MemoryAddress0 != 0)
/* We have a memory address so we are done */
return ODISTAT_SUCCESSFUL;
else
{
/* The card is in shared memory mode and the user has not supplied */
/* a memory address so, lets ask him for one. */
MemOption.Flags |= REQUIREDPARAM;
/* MPK 970219 CMSMParseDriverParameters(&DriverParameters, &MemOption); */
/* Set up the ParseString. Since MEM is being parsed for */
/* with CMSMParseSingleParameter and not by */
/* CMSMParseDriverParameters, we have to provide the ParseString. */
MemOption.ParseString = CNE2000_MEM_PARSE_STRING_TXTMSG;
if (CMSMParseSingleParameter(&MemOption) != ODISTAT_SUCCESSFUL)
{
return ODISTAT_FAIL;
}
/* Save the parsed MEM value in the config table. */
configTable->MLIDCFG_MemoryAddress0 =
(void *)MemOption.Parameter1.Max;
}
}
else
{
/* No card there, restore saved value */
Out8(configTable->MLIDCFG_DBusTag, (void *)(configTable->MLIDCFG_IOPort0 + 0x10), saveVal);
Slow();
return ODISTAT_FAIL;
}
}
return ODISTAT_SUCCESSFUL;
} /* End CheckForSharedRAM */
/*======================================================================
Procedure Name: DoRAMTest
Arguments: UINT16 testPattern
Returns: UINT32
TRUE - The NE2000's memory passed the test.
FALSE - The NE2000's memory failed the test.
Abstract: This routine will test Static RAM by writing the pattern
provided to all areas of memory and reading them back.
Notes:
========================================================================*/
UINT32 DoRAMTest(
DRIVER_DATA *driverData,
UINT16 testPattern)
{
UINT32 i, j;
if (driverData->NICRAMSegmentBase == 0)
{
/* Set remote start address to 0x4000 */
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 0);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, 0x40);
/* Set remote byte count to 0x4000 */
Out8(driverData->BusTag, driverData->RemoteByteCount0, 0);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 0x40);
/* Tell the NIC to start writing */
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMAWR);
/* And feed it our test pattern to write. */
for (i = 0; i < 0x2000; i++)
Out16(driverData->BusTag, driverData->NICData, testPattern);
/* Now read it back and check it. */
/* Set remote start address to 0x4000 */
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 0);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, 0x40);
/* Set remote byte count to 0x4000 */
Out8(driverData->BusTag, driverData->RemoteByteCount0, 0);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 0x40);
/* Tell the NIC to start reading */
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMARD);
/* Read and compare. */
for (i = 0; i < 0x2000; i++)
{
j = In16(driverData->BusTag, driverData->NICData);
if (j != testPattern)
return FALSE;
}
return ODISTAT_SUCCESSFUL;
}
else
{
/* First write the test pattern to the shared memory buffer. */
Set16(driverData->BusTag, NULL, driverData->NICRAMSegmentBase, testPattern, 0x2000);
/* Then read it back and compare. */
for (i = 0; i < 0x2000; i++)
{
j = Rd16(driverData->BusTag, NULL, driverData->NICRAMSegmentBase + (i * 2));
if (j != testPattern)
return FALSE;
}
return ODISTAT_SUCCESSFUL;
}
}
/*======================================================================
Procedure Name: DriverTestHardware
Arguments: framedata - Pointer to the Frame data space.
*driverData - Pointer to the Drivers data space.
Returns: ODISTAT
ODISTAT_SUCCESSFUL - The Hardware is OK.
ODISTAT_FAIL - The Hardware is not OK.
Abstract: This routine will set the NIC's node address, the NIC's
physical registers, and test the NIC's static RAM.
Notes:
=======================================================================*/
ODISTAT DriverTestHardware(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
UINT32 i;
UINT8 *memptr;
UINT8 buffer[20];
if (driverData->NICRAMSegmentBase == 0)
{
Out8(driverData->BusTag, driverData->RemoteStartAddress0, 0);
Out8(driverData->BusTag, driverData->RemoteStartAddress1, 0);
/* Read 16 bytes (I don't understand this `16 * 2' but, it is that */
/* way in the ASM code.) */
Out8(driverData->BusTag, driverData->RemoteByteCount0, 16 * 2);
Out8(driverData->BusTag, driverData->RemoteByteCount1, 0);
Out8(driverData->BusTag, driverData->Command, NIC_REMOTEDMARD);
/* Get the node address. Place it in the config table unless the user has */
/* supplied a node address override. */
if( configTable->MLIDCFG_NodeAddress.nodeAddress[0] == 0xff)
memptr = (UINT8 *)&(configTable->MLIDCFG_NodeAddress);
else
memptr = (UINT8 *)&(driverData->ReceiveHeader);
for( i = 0 ; i < 6; ++i)
memptr[i] = In8(driverData->BusTag, driverData->NICData);
/* Check that this is an NE2000 in a 16 bit slot by looking for the 'WW' */
/* signature in the next 10 bytes of the PROM. */
if ( driverData->PCMCIAFlag == 0)
{
for( i = 0; i < 10; ++i)
{
buffer[i] = In8(driverData->BusTag, driverData->NICData);
}
if (buffer[8] != 'W' || buffer[9] != 'W')
{
if (buffer[8] == 'B' || buffer[9] == 'B')
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_8BITSLOT_MSG, 0, 0);
}
else
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_NOBOARD_MSG, 0, 0);
}
return ODISTAT_FAIL;
}
} /* End of if PCCard = 0 ? */
}
else
{
/* Board in shared memory mode */
if( configTable->MLIDCFG_NodeAddress.nodeAddress[0] == 0xff)
for( i = 0, memptr = driverData->Prom; i < 6; ++i, ++memptr)
configTable->MLIDCFG_NodeAddress.nodeAddress[i] = In8(driverData->BusTag, (void *)memptr);
}
/* Set to page 1 registers */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1STOP);
/* Write address to Register */
Out8(driverData->BusTag, driverData->PageStart, configTable->MLIDCFG_NodeAddress.nodeAddress[0]);
Out8(driverData->BusTag, driverData->PageStop, configTable->MLIDCFG_NodeAddress.nodeAddress[1]);
Out8(driverData->BusTag, driverData->Boundary, configTable->MLIDCFG_NodeAddress.nodeAddress[2]);
Out8(driverData->BusTag, driverData->TransmitStatus, configTable->MLIDCFG_NodeAddress.nodeAddress[3]);
Out8(driverData->BusTag, driverData->TransmitByteCount0, configTable->MLIDCFG_NodeAddress.nodeAddress[4]);
Out8(driverData->BusTag, driverData->TransmitByteCount1, configTable->MLIDCFG_NodeAddress.nodeAddress[5]);
/* Set to page 0 Registers */
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
/****************************************************************\
* *
* Now that we know we are really dealing with an NE2000 in the *
* right slot, we can safely test memory. *
* NE2000 contain Static RAM. Running a checkerboard test will *
* catch retention, open or shorted faults common to S-RAM. *
* *
\****************************************************************/
if (DoRAMTest(driverData, 0xa5a5) || DoRAMTest(driverData, 0x5a5a))
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_MEMERR_MSG, 0, 0);
return ODISTAT_FAIL;
}
/* Verify that the HSM's INT matches what the board is configured for */
if (VerifyIRQ( driverData, configTable))
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_IRQERR_MSG, 0, 0);
return ODISTAT_FAIL;
}
return ODISTAT_SUCCESSFUL;
}
/*=========================================================================
Procedure Name: VerifyIRQ
Arguments:
driverData - is a ptr to the adapter data space.
configTable - is a ptr to the config table.
Returns: ODISTAT
SUCCESSFUL - The IRQ was verified successfully.
FAIL - No IRQ was received from the adapter.
Abstract: This routine will verify that the IRQ selected by the user
matches the IRQ configured on the adapter. This is done by
configuring the card for internal lookback, performing a
(garbage) transmit to force an interrupt, and seeing if the
appropriate interrupt is generated.
Notes:
==========================================================================*/
ODISTAT VerifyIRQ(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
UINT8 intIndex;
if (driverData->NICRAMSegmentBase != 0)
/* Card is an NE2000+ (AT/LANTIC chip) */
{
/* Read mode config reg A, mask off and shift INT bits. */
intIndex = In8(driverData->BusTag, driverData->RemoteByteCount0);
intIndex = (intIndex & 0x38) >> 3;
if (configTable->MLIDCFG_Interrupt0 == IntTable[intIndex])
return ODISTAT_SUCCESSFUL;
else
return ODISTAT_FAIL;
}
/* If card is an NE2000 (8390 chip) we can not verify the IRQ. */
return ODISTAT_SUCCESSFUL;
}
/*======================================================================
Procedure Name: DriverInit
Arguments: None.
Returns:
SUCCESSFUL - The Hardware has been initilized.
FAIL - The Hardware failed to initilize.
Abstract: This routine is called by the MSM at load time. It will
call EtherTSMRegisterHSM, MSMSetHardwareInterrupt,
MSMRegisterMLID. It will also initialize variables in the
Adapter Data Space and initialize the card.
Notes:
========================================================================*/
ODISTAT DriverInit(
struct _MODULE_HANDLE_ *ModuleHandle,
SCREEN_HANDLE *ScreenHandle,
MEON *CommandLine,
MEON *ModuleLoadPath,
UINT32 UnitializedDataLength,
void *CustomDataFileHandle,
UINT32 (* FileRead)(
void *FileHandle,
UINT32 FileOffset,
void *FileBuffer,
UINT32 FileSize),
UINT32 CustomDataOffset,
UINT32 CustomDataSize,
UINT32 NumMsgs,
MEON **Msgs)
{
UINT32 iooffset;
CONFIG_TABLE *configTable;
DRIVER_DATA *driverData;
UINT32 error;
REG_TYPE retValue;
UINT8 k;
UINT32 slotsWithMyBoardCount;
UINT32 magicNumber, uniqueID;
UINT8 *configInfo = 0;
UINT8 pcCard = 0;
UINT8 numOfProductID = 0;
GetConfigInfo *gConfInfo;
CHSM_STACK chsmStack;
void *temp_DBusTag;
/* Setup a Stack */
chsmStack.ModuleHandle = ModuleHandle;
chsmStack.ScreenHandle = ScreenHandle;
chsmStack.CommandLine = CommandLine;
chsmStack.ModuleLoadPath = ModuleLoadPath;
chsmStack.UnitializedDataLength = UnitializedDataLength;
chsmStack.CustomDataFileHandle = CustomDataFileHandle;
chsmStack.FileRead = FileRead;
chsmStack.CustomDataOffset = CustomDataOffset;
chsmStack.CustomDataSize = CustomDataSize;
chsmStack.NumMsgs = NumMsgs;
chsmStack.Msgs = Msgs;
DriverParameters.DriverInitParmPointer = &chsmStack;
/* MPK 970219 - Must initialize the parser before we can call it */
CMSMInitParser(&DriverParameters);
if (CEtherTSMRegisterHSM(&DriverParameters, &configTable) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
/***********************************************************************\
** scan all socket for our card
\***********************************************************************/
slotsWithMyBoardCount = 0;
for (k = 0, numOfProductID = 0;
numOfProductID < NUM_OF_PROD_ID;
++numOfProductID, k += PROD_ID_LEN)
{
magicNumber = -1;
while ( CMSMSearchAdapter(&magicNumber, ODI_BUSTYPE_PCMCIA,
PROD_ID_LEN, (MEON *)&NE2000ProdID[k],
&temp_DBusTag,
&uniqueID) == ODI_NBI_SUCCESSFUL)
{
configTable->MLIDCFG_DBusTag = temp_DBusTag;
if ( CMSMGetInstanceNumber(configTable->MLIDCFG_DBusTag,
uniqueID,
(UINT16 *)&SlotsWithMyBoard.UNumOptVal[slotsWithMyBoardCount])
== ODI_NBI_SUCCESSFUL)
{
++slotsWithMyBoardCount;
}
}
}
if (slotsWithMyBoardCount)
{
SlotsWithMyBoard.OptionCount = slotsWithMyBoardCount;
pcCard = 1;
if (slotsWithMyBoardCount == 1)
{
configTable->MLIDCFG_Slot = SlotsWithMyBoard.UNumOptVal[0];
if (CMSMParseDriverParameters(&DriverParameters, NULL) == ODISTAT_FAIL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
}
else if (CMSMParseDriverParameters(&DriverParameters, &SlotOption) == ODISTAT_FAIL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
if ( CMSMGetInstanceNumberMapping(
configTable->MLIDCFG_Slot,
&configTable->MLIDCFG_DBusTag,
&uniqueID)
!= ODI_NBI_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
configInfo = CMSMInitAlloc(37 + 4096);
if (CMSMGetCardConfigInfo(
configTable->MLIDCFG_DBusTag,
uniqueID, (37 + 4096), 37, 0, configInfo) == ODI_NBI_SUCCESSFUL)
{
gConfInfo = ( GetConfigInfo *)configInfo;
configTable->MLIDCFG_Interrupt0 = gConfInfo->AssignedIRQ;
configTable->MLIDCFG_IOPort0 = gConfInfo->BasePort1;
configTable->MLIDCFG_NodeAddress.nodeAddress[0] = configInfo[0xFF0 + 37];
configTable->MLIDCFG_NodeAddress.nodeAddress[1] = configInfo[0xFF2 + 37];
configTable->MLIDCFG_NodeAddress.nodeAddress[2] = configInfo[0xFF4 + 37];
configTable->MLIDCFG_NodeAddress.nodeAddress[3] = configInfo[0xFF6 + 37];
configTable->MLIDCFG_NodeAddress.nodeAddress[4] = configInfo[0xFF8 + 37];
configTable->MLIDCFG_NodeAddress.nodeAddress[5] = configInfo[0xFFA + 37];
CMSMFree(NULL, configInfo);
}
else
{
CMSMFree(NULL, configInfo);
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
}
else /* Legacy ISA NE2000 card */
{
if (CMSMParseDriverParameters(&DriverParameters, &IntOption) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
/* Set Bus Tag to zero assume that ISA is default bus */
configTable->MLIDCFG_DBusTag = 0;
}
if (CheckForSharedRAM(configTable) != ODISTAT_SUCCESSFUL)
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_NOBOARD_MSG, 0, 0);
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
/* Restore Io/MemOption Parameter1 field since parser blows it away */
MemOption.Parameter1.Range = IoOption.Parameter1.Range = 0;
if (DriverParameters.DriverSendPtr != &DriverSend)
/* Card is in Shared RAM mode so, lets set the shared memory length */
{
configTable->MLIDCFG_MemorySize0 = 0x400;
}
/* Register the Hardware Options */
retValue = CMSMRegisterHardwareOptions(
configTable,
&driverData);
if (retValue == REG_TYPE_NEW_ADAPTER)
{
/* This is a new adpater */
CFixUpStatStrings(driverData); /* Initialize statistics strings */
/* Get the BusTag */
driverData->BusTag = configTable->MLIDCFG_DBusTag;
/* Set up the I/O address table. */
iooffset = 0;
if (DriverParameters.DriverSendPtr != &DriverSend)
/* Card is in Shared RAM mode */
{
driverData->Control1Value = (((int)configTable->MLIDCFG_MemoryAddress0 >> 13) & 0x3F )| 0x40;
driverData->Control2Value = ((int)configTable->MLIDCFG_MemoryAddress0 >> 19) | 0xC0;
driverData->NICRAMSegmentBase = configTable->MLIDCFG_LinearMemory0;
driverData->NICRAMReceiveRingStart = (UINT8 *)configTable->MLIDCFG_LinearMemory0 + (RAMPSTART << 8);
driverData->NICRAMSegmentLimit = driverData->NICRAMReceiveRingStart + ((RAMPSTOP - RAMPSTART) << 8);
driverData->Control1 = (void *)(configTable->MLIDCFG_IOPort0 + 0x00);
driverData->Control2 = (void *)(configTable->MLIDCFG_IOPort0 + 0x05);
driverData->Prom = (void *)(configTable->MLIDCFG_IOPort0 + 0x08);
driverData->TransmitPage0 = 0x00;
driverData->TransmitPage1 = 0x06;
iooffset = 0x10;
}
/* Setup the rest of the I/O addresses from Base IO and iooffset. */
driverData->Command = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x00);
driverData->PageStart = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x01);
driverData->PageStop = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x02);
driverData->Boundary = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x03);
driverData->TransmitStatus = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x04);
driverData->TransmitByteCount0 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x05);
driverData->TransmitByteCount1 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x06);
driverData->InterruptStatus = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x07);
driverData->RemoteStartAddress0 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x08);
driverData->RemoteStartAddress1 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x09);
driverData->RemoteByteCount0 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0a);
driverData->RemoteByteCount1 = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0b);
driverData->ReceiveConfiguration = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0c);
driverData->TransmitConfiguration = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0d);
driverData->DataConfiguration = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0e);
driverData->InterruptMask = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x0f);
driverData->NICData = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x10);
driverData->Reset = (void *)(configTable->MLIDCFG_IOPort0 + iooffset + 0x1f);
/* Setup the TxFreeCount */
DADSP_TO_CMSMADSP(driverData)->CMSMTxFreeCount = 2;
driverData->PCMCIAFlag = pcCard;
error = DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
if (error)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
driverData->FirstTimeInit = 0;
--driverData->AdapterResetCount;
if (CMSMRegisterMLID(driverData, configTable) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
else
{
/* Connect the Hardware Interrupt */
error = CMSMSetHardwareInterrupt(
driverData,
configTable);
if (error)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
driverData->mlidAESECB.DriverAES = &DriverCallback;
if (CMSMScheduleAES(driverData, &(driverData->mlidAESECB)))
{
CMSMPrintString(configTable, MSG_TYPE_INIT_ERROR, CNE2000_AESERR_MSG, 0, 0);
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
/***********************************************************************\
** TNL 12/05/95 Register with NESL as producer of Service Resume event.
\***********************************************************************/
if (!NESLRegisterDone)
{
if ((NESLServiceResumeNECBPtr = (
NESL_ECB *)CMSMInitAlloc(sizeof(NESL_ECB))) == NULL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
NESLServiceResumeNECBPtr->NecbVersion = NESL_VERSION2;
NESLServiceResumeNECBPtr->NecbEventName = NESL_Service_Resume;
NESLServiceResumeNECBPtr->NecbRefData = NESL_NOT_UNIQUE_PRODUCER |
NESL_BROADCAST_EVENT | NESL_SORT_CONSUMER_BOTTOM_UP;
NESLServiceResumeNECBPtr->NecbOwner = ModuleHandle;
NESLServiceResumeNECBPtr->NecbContext = NULL;
if (CMSMNESLRegisterProducer(NESLServiceResumeNECBPtr) != NESL_OK)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
if ((NESL_EPBPtr = (EPB *)CMSMInitAlloc(sizeof(EPB))) == NULL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
NESL_EPBPtr->EPBMajorVersion = EPBMajVer;
NESL_EPBPtr->EPBMinorVersion = EPBMinVer;
NESLRegisterDone = TRUE;
}
/* Set up to produce NESL MLID Card Insertion Complete event */
NESL_EPBPtr->EPBEventName = NESL_Service_Resume;
NESL_EPBPtr->EPBEventType = NESL_MLID_Card_Insertion_Complete;
NESL_EPBPtr->EPBModuleName = 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 ODISTAT_SUCCESSFUL;
}
}
else if (retValue == REG_TYPE_NEW_FRAME)
{
/* This is a new frame type for an existing board */
/* Re-Enable the card - CheckForSharedRAM left the card disabled. */
/* Set up to produce NESL MLID Card Insertion Complete event */
error = DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
if (error)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
--driverData->AdapterResetCount;
NESL_EPBPtr->EPBDataPtr0 = configTable;
/* Generate NESL MLID Card Insertion Complete Event */
CMSMNESLProduceEvent(NESLServiceResumeNECBPtr,
NULL,
NESL_EPBPtr);
return ODISTAT_SUCCESSFUL;
}
else
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
}
/***********************************************************************\
* *
*
* 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->UnderrunErrorTable.StatString=(MEON_STRING *)CNE2000_UNDRRUN_STR;
driverData->TransmitTimeoutTable.StatString=(MEON_STRING *)CNE2000_TXTIMEOUT_STR;
driverData->RxPagingErrorTable.StatString=(MEON_STRING *)CNE2000_RXPAGERR_STR;
driverData->RxFIFOOverrunErrorTable.StatString=(MEON_STRING *)CNE2000_RXOVRRUN_STR;
driverData->RxMissedPacketTable.StatString=(MEON_STRING *)CNE2000_MISSDPKT_STR;
driverData->GotNothingTable.StatString=(MEON_STRING *)CNE2000_GOTNOTHING_STR;
driverData->UnsupportedFrameTable.StatString=(MEON_STRING *)CNE2000_UNSUPFRAME_STR;
driverData->UnsupportedMulticastTable.StatString=(MEON_STRING *)CNE2000_UNSUPMULTI_STR;
driverData->BackToBackSendTable.StatString=(MEON_STRING *)CNE2000_BTOBSEND_STR;
driverData->EnqueueSendTable.StatString=(MEON_STRING *)CNE2000_QDSEND_STR;
} /* End CFixUpStatStrings */
/*======================================================================
Procedure Name: DriverRemove
Arguments: none
Returns: void
Abstract: This routine is called to do any necessary clean up
and shutdown and then call MSMDriver remove. It
prepares the driver to be removed.
Notes:
========================================================================*/
void DriverRemove()
{
/* Clean up all NESL related stuff */
CMSMNESLDeRegisterProducer(NESLServiceResumeNECBPtr);
CMSMFree(NULL,NESLServiceResumeNECBPtr);
CMSMFree(NULL,NESL_EPBPtr);
CMSMDriverRemove(DriverParameters.DriverModuleHandle);
return;
}
/*======================================================================
Procedure Name: DriverMulticastChange
Arguments: configTable - Ptr to Our config Table.
driverData - Ptr to Our Data Space
mcTable - Ptr to the multicast table (mostly
for use in ethernet)
numEntries - The number of valid entries in the
multicast table.
funAddrBits - Thirty-two word with bit set for each
active functional address (for Token
Ring and FDDI)
Returns: void
Abstract:
This routine will modify the NIC's multicast registers to
enable it to receive the multicast addresses listed in
the multicast table. Each entry in the multicast table is as
follows:
bytes 0-5 = Multicast Address.
bytes 6-7 = Entry used(Non zero if used).
Notes:
=========================================================================*/
ODISTAT DriverMulticastChange(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
GROUP_ADDR_LIST_NODE *mcTable,
UINT32 numEntries,
UINT32 funAddrBits)
{
UINT32 i, bitindex;
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
for ( i = 0; i < 8; i++)
Out8(driverData->BusTag, ((UINT8 *)(driverData->MulticastAddrReg)) + i, 0);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
for ( i = 0; i < numEntries; i++)
{
bitindex = CalculateHash(mcTable + i);
ModifyNICHashTableBit(driverData, bitindex);
}
Out8(driverData->BusTag, driverData->ReceiveConfiguration, NIC_MULTICAST | NIC_BROADCAST);
/* Junk to keep compiler happy, optimizer should remove. */
configTable = configTable;
funAddrBits = funAddrBits;
return ODISTAT_SUCCESSFUL;
}
/*======================================================================
Procedure Name: CalculateHash
Arguments: This routine will take the 6-byte multicast address
passed to it and calculate a CRC as the 8390 would. It
will return the upper 6-bits of the CRC.
Returns: UINT32 Index to the bit to be set in the 8390's
multicast hash table.
Abstract:
Notes:
========================================================================*/
UINT32 CalculateHash(GROUP_ADDR_LIST_NODE *multiAddress)
{
UINT32 crc, index, j, carry;
UINT8 temp[6];
#define POLYNOMIAL 0x04C11DB6
COPY_ADDR(temp, multiAddress->GRP_ADDR.nodeAddress);
crc = 0xFFFFFFFF;
for (index = 0; index < 6; ++index)
{
for (j = 0; j < 8; ++j)
{
carry = ( (crc & 0x80000000) ? 1 : 0) ^ (temp[index] & 01);
crc <<= 1;
temp[index] >>= 1;
if(carry)
crc = ((crc ^ POLYNOMIAL) | carry);
}
}
crc >>= 26;
return (crc);
}
/*======================================================================
Procedure Name: ModifyNICHashTableBit
Arguments: UINT32 bitIndex
Returns: void
Abstract: Thus routine will set a bit in the 8390 multicast
hash table.
Notes:
========================================================================*/
void ModifyNICHashTableBit(
DRIVER_DATA *driverData,
UINT32 bitIndex)
{
UINT8 temp;
UINT32 tmpIndex;
tmpIndex = bitIndex >> 3;
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
temp = In8 (driverData->BusTag, (void *)((UINT8 *)driverData->MulticastAddrReg + tmpIndex));
Out8(driverData->BusTag, (void *)((UINT8 *)driverData->MulticastAddrReg + tmpIndex),
temp | (0x01 << ((tmpIndex << 3) ^ bitIndex)));
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
}
/*======================================================================
Procedure Name: DriverPromiscuousChange
Arguments: configTable - Ptr to Our config Table.
driverData - Ptr to Our Data Space
changeTo - 0 disable promiscous mode
- PROM_MODE_RMC enable remote
multicast frames only
- OTHER enable full promiscous mode
Returns: void
Abstract:
Notes:
========================================================================*/
ODISTAT DriverPromiscuousChange(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
UINT32 changeTo)
{
UINT32 i;
UINT8 temp;
if (changeTo == PROM_MODE_RMC)
{
/* Enable remote multicast */
driverData->ReceiveStatusTest = 0x4e;
Out8(driverData->BusTag, driverData->ReceiveConfiguration,
NIC_BROADCAST | NIC_MULTICAST);
temp = 0xff;
}
else if (changeTo)
{
/* Enable promiscous mode */
driverData->ReceiveStatusTest = 0x40;
Out8(driverData->BusTag, driverData->ReceiveConfiguration,
NIC_SAVEERRORS | NIC_SAVERUNTS | NIC_BROADCAST | NIC_MULTICAST | NIC_PROMISCUOUS);
temp = 0xff;
}
else
{
/* Disable promiscous mode */
driverData->ReceiveStatusTest = 0x4e;
Out8(driverData->BusTag, driverData->ReceiveConfiguration,
NIC_BROADCAST | NIC_MULTICAST);
temp = 0x00;
}
Out8(driverData->BusTag, driverData->Command, NIC_PAGE1);
for ( i = 0; i < 8; i++)
Out8(driverData->BusTag, ((UINT8 *)(driverData->MulticastAddrReg)) + i, temp);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0);
/* Junk to keep compiler happy, optimizer should remove. */
configTable = configTable;
return ODISTAT_SUCCESSFUL;
}
/*======================================================================
Procedure Name: DriverCallback
Arguments:
driverData - Ptr to Our Data Space.
configTable - Ptr to Our config Table.
Returns: void
Abstract: This routine will be executed once every second. It will
detect if the hardware does not complete a transmission. If this
happens the hardware will be reset, the transmission
of that packet will be aborted and the next packet in the
queue will be sent if there is one.
Notes:
========================================================================*/
void DriverCallback(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
UINT32 i;
#ifdef OUT_CHAR
NiosDebugCharOut ('C');
#endif /* OUT_CHAR */
/* If no Tx active or Tx not yet active for 2 sec then exit */
/* AYD 10-07-96*/
/* CMSMGetMicroTimer() - driverData->TxStartTime < 2000000) */
if (!driverData->TxStartTime |
CMSMGetCurrentTime() - driverData->TxStartTime <= 36)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('c');
#endif /* OUT_CHAR */
return;
}
/* Increment approp stats counters */
if ((i = In8(driverData->BusTag, driverData->NumberCollisions)) > 1)
driverData->TxOKMultipleCollisions += i;
else
++(driverData->TxOKSingleCollision);
if (In8(driverData->BusTag, driverData->Command) & NIC_TXINPROGRESS)
{
CMSMPrintString(
configTable,
MSG_TYPE_RUNTIME_WARNING,
CNE2000_TXTIMEOUT_MSG,
0, 0);
}
DriverReset(driverData, configTable, OP_SCOPE_ADAPTER);
++(driverData->TransmitTimeoutCount);
++(driverData->PacketTxMiscErrorCount);
driverData->TxStartTime = 0;
Out8(driverData->BusTag, driverData->InterruptStatus, 0x0A); /* Reset all transmit bits */
/* Another transmit waiting? */
if (driverData->TransmitStatusFlag & PAGETWOWAITING)
/****************************************************************\
* *
* We just aborted a send, but there is already another *
* packet transfered to the board. We just need to issue the *
* send for it. *
* *
\****************************************************************/
{
++driverData->BackToBackSendCount;
if (driverData->TransmitStatusFlag & USEPAGEONE)
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage0);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize1 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize1 >> 8));
}
else
{
Out8(driverData->BusTag, driverData->TransmitPage, driverData->TransmitPage1);
Out8(driverData->BusTag, driverData->TransmitByteCount0, (UINT8)(driverData->TransmitSize2 /* & 0xFF */));
Out8(driverData->BusTag, driverData->TransmitByteCount1, (UINT8)(driverData->TransmitSize2 >> 8));
}
Out8(driverData->BusTag, driverData->Command, NIC_TRANSMIT);
/* AYD 10-07-96 */
driverData->TxStartTime = CMSMGetCurrentTime();
driverData->RetryCounter = configTable->MLIDCFG_SendRetries;
driverData->TransmitStatusFlag ^= (USEPAGEONE | PAGETWOWAITING);
}
else
{
driverData->TransmitStatusFlag = USEPAGEONE;
}
#ifdef OUT_CHAR
NiosDebugCharOut ('d');
#endif /* OUT_CHAR */
return;
}
/*======================================================================
Procedure Name: DriverDisableInterrupt
Arguments:
driverData - Ptr to Our Data Space.
Returns: 0(false) if the driver was requesting an interrupt
1(true) if the driver was not requesting an interrupt
Abstract: This routine will disable the adapters ability to
interrupt the host.
Notes:
========================================================================*/
BOOLEAN DriverDisableInterrupt(
DRIVER_DATA *driverData,
BOOLEAN flag)
{
UINT8 nicstatus;
#ifdef OUT_CHAR
NiosDebugCharOut ('{');
#endif /* OUT_CHAR */
flag = flag;
nicstatus = In8(driverData->BusTag, driverData->InterruptStatus);
Out8(driverData->BusTag, driverData->InterruptMask, NIC_MASKBYTE);
if (nicstatus & NIC_REQINT)
{
return TRUE;
}
else
{
return FALSE;
}
}
/*======================================================================
Procedure Name: DriverEnableInterrupt
Arguments:
driverData - Ptr to Our Data Space.
Returns: void
Abstract: This routine will enable the adapters ability to
interrupt the host.
Notes:
========================================================================*/
void DriverEnableInterrupt(
DRIVER_DATA *driverData)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('}');
#endif /* OUT_CHAR */
Out8(driverData->BusTag, driverData->InterruptMask, NIC_UNMASKBYTE);
return;
}
/*======================================================================
Procedure Name: DriverShutdown
Arguments:
driverData - Ptr to Our Data Space.
configTable - Ptr to Our config Table.
shutdownType - 0 if permanent shutdown
1 if partial shutdown
operationScope - OP_SCOPE_ADAPTER or OP_SCOPE_LOGICAL_BOARD.
Returns: 0 if successful, ODISTAT_FAIL if unsuccessful
Abstract: This routine will turn off the NIC.
Notes:
========================================================================*/
ODISTAT DriverShutdown(
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
UINT32 shutdownType,
OPERATION_SCOPE operationScope)
{
//JCJ 19-Aug-97 SPD# 161807
//If DriverShutdown is called with a scope of LOGICAL_BOARD, adapter shout not be
//shut down.
if(operationScope == OP_SCOPE_ADAPTER)
{
Out8(driverData->BusTag, driverData->InterruptMask, NIC_MASKBYTE);
Out8(driverData->BusTag, driverData->Command, NIC_PAGE0STOP);
if (driverData->NICRAMSegmentBase != 0)
/* Card is in shared RAM mode */
{
/* Clear memory enable bit and reset adapter */
Out8(driverData->BusTag, driverData->Control1, driverData->Control1Value & !0x40);
}
/* Junk to keep compiler happy, optimizer should remove. */
configTable = configTable;
shutdownType = shutdownType;
}
return ODISTAT_SUCCESSFUL;
}
/*=======================================================================*/
/*=======================================================================*/