// Sample code file: cne3200.c
// Warning: This code has been marked up for HTML
/*--------------------------------------------------------------------------*
* $version: 1.39
* $date_modified: 121898
* $description: LAN Device Driver for CNE3200
* $owner: ODI LAN Driver Manager
* Copyright (c) 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 NE3200 HSM
*
* Filename: NE3200.C
*
* ODI Spec Ver: 1.11
*
* Description: This module contains the HardWare specific routines
* to initialize and control the Novell NE3200 board.
*
* Modification History:
*
* 02-13-97 WTT Changed call CMSMShutdownMlid back to DriverShutdown
* in the DriverReset code. DriverReset gets called by
* DriverInit before the CMSMRegisterMLID has been called.
* CMSMShutdownMLID can not be called before the MLID has
* been registered with the CMSM.
* SPD #150136
*
* 02-18-97 WTT Moved the location of NICShortName after ADSTemplate.
* When it was located before ADSTemplate it was causing
* adpaterRCBList and adapterTCBList to not be on a dword
* boundary.
* SPD #150137
*
* 02-19-97 MPK Changes made in DriverInit to call CMSMInitParser before
* Parsing parameters. as per new specification.
*
* 07-15-97 LON Changes made in DriverReset and DriverShutdown to enable
* instance shutdown and reset of a logical board. If a
* logical board is shutdown then the HSM tells the firmware
* to filter out rcv frames for that particular board.
* SPD# 160926
*
* 08-19-97 JCJ WaitFor procedure has been changed to a simple counter based
* loop from a timer based one, because we can not let other
* process to run at this time. SPD# 159385
*
* 09-23-97 JCJ To avoid compiler warning -1 is type casted with
* struct _TCB_ * while comparing driverData->adapterTCBList[]
* SPD# 166555
*
* 02-10-99 LON When the driver is unloaded it fails to release all ECBs,
* because of a timing window where interrupts were still
* enabled during permanent driver shutdown. This allowed
* the DriverISR routine to allocate RCBs before the
* driver was unloaded (SPD 223362).
*
****************************************************************************/
/*#define OUT_CHAR 1*/
/*===[ Include files specific to this module ]===========================*/
#include "cne3200.h"
#include "cne3200.txt"
/*===[ Global variables ]==================================================*/
#define NUMBER_OF_GENERICS ( \
(UINT32 *) &((DRIVER_DATA *)0)->QDepth - \
(UINT32 *) &((DRIVER_DATA *)0)->TotalTxPacketCount) - 1
#define NUMBER_OF_MEDIAS ( \
(UINT32 *) &((DRIVER_DATA *)0)->RxAbortFrameAlignment - \
(UINT32 *) &((DRIVER_DATA *)0)->TxOKSingleCollision) + 1 \
#define NUMBER_OF_CUSTOMS ( \
(UINT32 *) &((DRIVER_DATA *)0)->NumberOfIntsFiredCount - \
(UINT32 *) &((DRIVER_DATA *)0)->TxRetryFailureCount) + 1 \
/* NOTE: The adapter requires the adapterRCBList and adapterTCBList */
/* be on a dword boundary. Do not place things before the */
/* following template that would cause the list not to be on a */
/* dword boundary. */
DRIVER_DATA ADSTemplate =
{
{0}, /* adapterRCBList */
{0}, /* adapterTCBList */
{0}, /* hostPWSList1 */
{0}, /* hostPWSList2 */
{0}, /* hostRCBList */
{0}, /* hostTCBList */
{0}, /* txStartList */
0, /* tcbQueueHead */
0, /* tcbQueueTail */
0, /* tcbInProcess */
0, /* txStartTime */
0, /* updateStatCount */
0, /* receiveQueueHead */
0, /* receiveQueueTail */
TOTAL_RCBS, /* needRCBCount */
0, /* resetRegister */
0, /* eisaSystemDoorbellEnable */
0, /* eisaSystemDoorbellStatus */
0, /* idleMailbox */
0, /* updateParmMailbox */
0, /* updateStatMailbox */
0, /* tcbValidMailbox */
0, /* pollingMailbox */
0, /* tcbMailbox */
0, /* parametersMailbox */
0, /* logicalToPhysicalOffset */
0, /* nodeAddressPointer */
-1, /* boardNumber8023 */
-1, /* boardNumberEII */
-1, /* boardNumber8022 */
-1, /* boardNumberSNAP */
0, /* maxReceivePacketSize */
0, /* genericStatisticsPointer */
NUMBER_OF_CUSTOMS, /* customStatisticsCount */
0, /* rcbListPointer */
0, /* multicastCount */
0, /* multicastTablePointer */
{0}, /* hostNodeAddress */
0, /* promiscuousMode */
DEFAULT_TIMEOUT_VALUE, /* pollTimeout */
GLOBAL_CONFIG, /* globalConfigValue */
0, /* dummyAlignValue */
0, /* parameterCommand */
0, /* parameter1 */
0, /* parameter2 */
0, /* inDriverPoll */
0, /* inDriverReset */
0, /* inDriverDisable */
{
NULL, /* DAES->NextLink */
DriverCallBack, /* DAES->DriverAES */
AES_TYPE_PROCESS_CONTINUOUS, /* DAES->AesType */
500, /* DAES->TimeInterval */
NULL, /* DAES->AesContext */
{0} /* DAES->AesReserved */
},
0, /* busType */
NULL, /* busTag */
{
4, /* StatsTable->MStatTableMajorVer */
00, /* StatsTable->MStatTableMinorVer */
NUMBER_OF_GENERICS, /* StatsTable->MNumGenericCounters */
&ADSTemplate.TotalTxPacketTable, /* StatsTable->MGenericCountsPtr */
NUMBER_OF_MEDIAS, /* StatsTable->MNumMediaCounters */
&ADSTemplate.TxOKSingleCollisionTable, /* StatsTable->MMediaCountersPtr */
NUMBER_OF_CUSTOMS, /* StatsTable->MNumCustomCounters */
&ADSTemplate.TxRetryFailureTable, /* StatsTable->MCustomCountersPtr */
},
{
ODI_STAT_UINT32, /* TotalTxPacketTable->StatUseFlag */
&ADSTemplate.TotalTxPacketCount, /* TotalTxPacketTable->StatCounter */
0 /* TotalTxPacketTable->StatString */
},
{
ODI_STAT_UINT32, /* TotalRxPacketTable->StatUseFlag */
&ADSTemplate.TotalRxPacketCount, /* TotalRxPacketTable->StatCounter */
0 /* TotalRxPacketTable->StatString */
},
{
ODI_STAT_UINT32, /* NoECBAvailableTable->StatUseFlag */
&ADSTemplate.NoECBAvailableCount, /* NoECBAvailableTable->StatCounter */
0 /* NoECBAvailableTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketTxTooBigTable->StatUseFlag */
&ADSTemplate.PacketTxTooBigCount, /* PacketTxTooBigTable->StatCounter */
0 /* PacketTxTooBigTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketTxTooSmallTable->StatUseFlag */
&ADSTemplate.PacketTxTooSmallCount, /* PacketTxTooSmallTable->StatCounter */
0 /* PacketTxTooSmallTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketRxOverflowTable->StatUseFlag */
&ADSTemplate.PacketRxOverflowCount, /* PacketRxOverflowTable->StatCounter */
0 /* PacketRxOverflowTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketRxTooBigTable->StatUseFlag */
&ADSTemplate.PacketRxTooBigCount, /* PacketRxTooBigTable->StatCounter */
0 /* PacketRxTooBigTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketRxTooSmallTable->StatUseFlag */
&ADSTemplate.PacketRxTooSmallCount, /* PacketRxTooSmallTable->StatCounter */
0 /* PacketRxTooSmallTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketTxMiscErrorTable->StatUseFlag */
&ADSTemplate.PacketTxMiscErrorCount, /* PacketTxMiscErrorTable->StatCounter */
0 /* PacketTxMiscErrorTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketRxMiscErrorTable->StatUseFlag */
&ADSTemplate.PacketRxMiscErrorCount, /* PacketRxMiscErrorTable->StatCounter */
0 /* PacketRxMiscErrorTable->StatString */
},
{
ODI_STAT_UINT32, /* RetryTxTable->StatUseFlag */
&ADSTemplate.RetryTxCount, /* RetryTxTable->StatCounter */
0 /* RetryTxTable->StatString */
},
{
ODI_STAT_UINT32, /* ChecksumErrorTable->StatUseFlag */
&ADSTemplate.ChecksumErrorCount, /* ChecksumErrorTable->StatCounter */
0 /* ChecksumErrorTable->StatString */
},
{
ODI_STAT_UINT32, /* HardwareRxMismatchTable->StatUseFlag */
&ADSTemplate.HardwareRxMismatchCount, /* HardwareRxMismatchTable->StatCounter */
0 /* HardwareRxMismatchTable->StatString */
},
{
ODI_STAT_UINT64, /* TotalTxOKByteTable->StatUseFlag */
&ADSTemplate.TotalTxOKByteCount, /* TotalTxOKByteTable->StatCounter */
0 /* TotalTxOKByteTable->StatString */
},
{
ODI_STAT_UINT64, /* TotalRxOKByteTable->StatUseFlag */
&ADSTemplate.TotalRxOKByteCount, /* TotalRxOKByteTable->StatCounter */
0 /* TotalRxOKByteTable->StatString */
},
{
ODI_STAT_UINT32, /* TotalGroupAddrTxTable->StatUseFlag */
&ADSTemplate.TotalGroupAddrTxCount, /* TotalGroupAddrTxTable->StatCounter */
0 /* TotalGroupAddrTxTable->StatString */
},
{
ODI_STAT_UINT32, /* TotalGroupAddrRxTable->StatUseFlag */
&ADSTemplate.TotalGroupAddrRxCount, /* TotalGroupAddrRxTable->StatCounter */
0 /* TotalGroupAddrRxTable->StatString */
},
{
ODI_STAT_UINT32, /* AdapterResetTable->StatUseFlag */
&ADSTemplate.AdapterResetCount, /* AdapterResetTable->StatCounter */
0 /* AdapterResetTable->StatString */
},
{
ODI_STAT_UINT32, /* AdapterOprTimeStampTable->StatUseFlag */
&ADSTemplate.AdapterOprTimeStamp, /* AdapterOprTimeStampTable->StatCounter */
0 /* AdapterOprTimeStampTable->StatString */
},
{
ODI_STAT_UINT32, /* QDepthTable->StatUseFlag */
&ADSTemplate.QDepth, /* QDepthTable->StatCounter */
0 /* QDepthTable->StatString */
},
/* topology specific counters */
{
ODI_STAT_UINT32, /* TxOKSingleCollision->StatUseFlag */
&ADSTemplate.TxOKSingleCollision, /* TxOKSingleCollision->StatCounter */
0 /* TxOKSingleCollision->StatString */
},
{
ODI_STAT_UINT32, /* TxOKMultipleCollisions->StatUseFlag */
&ADSTemplate.TxOKMultipleCollisions, /* TxOKMultipleCollisions->StatCounter */
0 /* TxOKMultipleCollisions->StatString */
},
{
ODI_STAT_UINT32, /* TxOKButDeferred->StatUseFlag */
&ADSTemplate.TxOKButDeferred, /* TxOKButDeferred->StatCounter */
0 /* TxOKButDeferred->StatString */
},
{
ODI_STAT_UINT32, /* TxAbortLateCollision->StatUseFlag */
&ADSTemplate.TxAbortLateCollision, /* TxAbortLateCollision->StatCounter */
0 /* TxAbortLateCollision->StatString */
},
{
ODI_STAT_UINT32, /* TxAbortExcessCollisions->StatUseFlag */
&ADSTemplate.TxAbortExcessCollisions, /* TxAbortExcessCollisions->StatCounter */
0 /* TxAbortExcessCollisions->StatString */
},
{
ODI_STAT_UINT32, /* TxAbortCarrierSense->StatUseFlag */
&ADSTemplate.TxAbortCarrierSense, /* TxAbortCarrierSense->StatCounter */
0 /* TxAbortCarrierSense->StatString */
},
{
ODI_STAT_UINT32, /* TxAbortExDeferral->StatUseFlag */
&ADSTemplate.TxAbortExDeferral, /* TxAbortExDeferral->StatCounter */
0 /* TxAbortExDeferral->StatString */
},
{
ODI_STAT_UINT32, /* RxAbortFrameAlignment->StatUseFlag */
&ADSTemplate.RxAbortFrameAlignment, /* RxAbortFrameAlignment->StatCounter */
0 /* RxAbortFrameAlignment->StatString */
},
/* custom counters */
{
ODI_STAT_UINT32, /* TxRetryFailureTable->StatUseFlag */
&ADSTemplate.TxRetryFailureCount, /* TxRetryFailureTable->StatCounter */
0 /* TxRetryFailureTable->StatString */
},
{
ODI_STAT_UINT32, /* ClearToSendTable->StatUseFlag */
&ADSTemplate.ClearToSendCount, /* ClearToSendTable->StatCounter */
0 /* ClearToSendTable->StatString */
},
{
ODI_STAT_UINT32, /* UnderRunTable->StatUseFlag */
&ADSTemplate.UnderRunCount, /* UnderRunTable->StatCounter */
0 /* UnderRunTable->StatString */
},
{
ODI_STAT_UINT32, /* RxDMAOverrunTable->StatUseFlag */
&ADSTemplate.RxDMAOverrunCount, /* RxDMAOverrunTable->StatCounter */
0 /* RxDMAOverrunTable->StatString */
},
{
ODI_STAT_UINT32, /* PacketSlideTable->StatUseFlag */
&ADSTemplate.PacketSlideCount, /* PacketSlideTable->StatCounter */
0 /* PacketSlideTable->StatString */
},
{
ODI_STAT_UINT32, /* DummyRCBTable->StatUseFlag */
&ADSTemplate.DummyRCBCount, /* DummyRCBTable->StatCounter */
0 /* DummyRCBTable->StatString */
},
{
ODI_STAT_UINT32, /* AdapterReset1Table->StatUseFlag */
&ADSTemplate.AdapterReset1Count, /* AdapterReset1Table->StatCounter */
0 /* AdapterReset1Table->StatString */
},
{
ODI_STAT_UINT32, /* BadFragLengthTable->StatUseFlag */
&ADSTemplate.BadFragLengthCount, /* BadFragLengthTable->StatCounter */
0 /* BadFragLengthTable->StatString */
},
{
ODI_STAT_UINT32, /* PollingTimeoutTable->StatUseFlag */
&ADSTemplate.PollingTimeoutCount, /* PollingTimeoutTable->StatCounter */
0 /* PollingTimeoutTable->StatString */
},
{
ODI_STAT_UINT32, /* AdapterDiedTable->StatUseFlag */
&ADSTemplate.AdapterDiedCount, /* AdapterDiedTable->StatCounter */
0 /* AdapterDiedTable->StatString */
},
{
ODI_STAT_UINT32, /* NumberOfIntsFiredTable->StatUseFlag */
&ADSTemplate.NumberOfIntsFiredCount, /* NumberOfIntsFiredTable->StatCounter */
0 /* NumberOfIntsFiredTable->StatString */
},
0, /* TotalTxPacketCount */
0, /* TotalRxPacketCount */
0, /* NoECBAvailableCount */
0, /* PacketTxTooBigCount */
0, /* PacketTxTooSmallCount */
0, /* PacketRxOverflowCount */
0, /* PacketRxTooBigCount */
0, /* PacketRxTooSmallCount */
0, /* PacketTxMiscErrorCount */
0, /* PacketRxMiscErrorCount */
0, /* RetryTxCount */
0, /* ChecksumErrorCount */
0, /* HardwareRxMismatchCount */
{0, 0}, /* TotalRxOKByteCount */
{0, 0}, /* TotalTxOKByteCount */
0, /* TotalGroupAddrTxCount */
0, /* TotalGroupAddrRxCount */
0, /* AdapterResetCount */
0, /* AdapterOprTimeStamp */
0, /* QDepth */
/* topology counters */
0, /* TxOKSingleCollision */
0, /* TxOKMultipleCollsions */
0, /* TxOKButDeferred */
0, /* TxAbortLateCollision */
0, /* TxAbortExcessCollisions */
0, /* TxAbortCarrierSense */
0, /* TxAbortExDeferral */
0, /* RxAbortFrameAlignment */
/* custom counters */
NUMBER_OF_CUSTOMS, /* CustomCounterCount */
0, /* TxRetryFailureCount */
0, /* ClearToSendCount */
0, /* UnderRunCount */
0, /* RxDMAOverrunCount */
0, /* PacketSlideCount */
0, /* DummyRCBCount */
0, /* AdapterReset1Count */
0, /* BadFragLengthCount */
0, /* PollingTimeoutCount */
0, /* AdapterDiedCount */
0, /* NumberOfIntsFiredCount */
};
MEON_STRING CHSMSPEC[] = {CNE3200_SPECVER_TXTMSG};
MEON **DriverMessages = NULL;
/* 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. */
MEON_STRING NICShortName[] = {CNE3200_SHORTNAME_TXTMSG};
MLID_CONFIG_TABLE DriverConfigTemplate =
{
CNE3200_CONFIGSIG_TXTMSG, /* MLIDCFG_Signature[26]; */
01, /* MLIDCFG_MajorVersion */
21, /* MLIDCFG_MinorVersion */
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, /* MLIDCFG_NodeAddress */
MODE_FLAGS, /* MLIDCFG_ModeFlags */
0, /* MLIDCFG_BoardNumber */
0, /* MLIDCFG_BoardInstance */
0, /* MLIDCFG_MaxFrameSize */
0, /* MLIDCFG_BestDataSize */
0, /* MLIDCFG_WorstDataSize */
NULL, /* MLIDCFG_CardName */
NICShortName, /* MLIDCFG_ShortName */
NULL, /* MLIDCFG_FrameTypeString */
0, /* MLIDCFG_Reserved0 */
0, /* MLIDCFG_FrameID */
1, /* 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 */
FLAGS, /* MLIDCFG_Flags */
5, /* MLIDCFG_SendRetries */
NULL, /* MLIDCFG_DriverLink */
SHARING_FLAGS, /* MLIDCFG_SharingFlags */
0, /* MLIDCFG_Slot */
0x300, /* MLIDCFG_IOPort0 */
0x30, /* MLIDCFG_IORange0 */
0, /* MLIDCFG_IOPort1 */
0, /* MLIDCFG_IORange1 */
NULL, /* MLIDCFG_MemoryAddress0 */
0, /* MLIDCFG_MemorySize0 */
NULL, /* MLIDCFG_MemoryAddress1 */
0, /* MLIDCFG_MemorySize1 */
0xff, /* MLIDCFG_Interrupt0 */
0xff, /* MLIDCFG_Interrupt1 */
0xff, /* MLIDCFG_DMALine0 */
0xff, /* MLIDCFG_DMALine1 */
NULL, /* MLIDCFG_ResourceTag */
NULL, /* MLIDCFG_Config */
NULL, /* MLIDCFG_CommandString */
{0}, /* MLIDCFG_LogicalName */
0, /* MLIDCFG_LinearMemory0 */
0, /* MLIDCFG_LinearMemory1 */
0, /* MLIDCFG_ChannelNumber */
0, /* MLIDCFG_DBusTag */
1, /* MLIDCFG_DIOConfigMajorVr*/
0 /* MLIDCFG_DIOConfigMinorVr*/
};
DRIVER_PARM_BLOCK DriverParameterBlock =
{
sizeof(DRIVER_PARM_BLOCK), /* DriverParameterSize */
NULL, /* DriverInitParmPointer */
NULL, /* DriverModuleHandle */
NULL, /* DriverBoardPointer */
NULL, /* DriverAdapterPointer */
&DriverConfigTemplate, /* DriverConfigTemplatePtr */
-1, /* DriverFirmwareSize */
NULL, /* DriverFirmwareBuffer */
0, /* DPB_Reserved1 */
0, /* DPB_Reserved2 */
0, /* DPB_Reserved3 */
0, /* DPB_Reserved4 */
sizeof (DRIVER_DATA), /* DriverAdapterDataSpaceSize */
&ADSTemplate, /* DriverAdapterDataSpacePtr */
(UINT32) &(((DRIVER_DATA*)0)->StatsTable), /* DriverStatisticsTableOffset*/
0, /* DriverEndOfChainFlag */
-1, /* DriverSendWantsECBs */
20, /* DriverMaxMulticast */
0, /* DriverNeedsBelow16Meg */
NULL, /* DPB_Reserved5 */
NULL, /* DPB_Reserved6 */
DriverISR, /* DriverISRPtr */
DriverMulticastChange, /* DriverMulticastChangePtr */
DriverPoll, /* DriverPollPtr */
DriverReset, /* DriverResetPtr */
DriverSend, /* DriverSendPtr */
DriverShutdown, /* DriverShutdownPtr */
NULL, /* DriverTxTimeoutPtr */
DriverPromiscuousChange, /* DriverPromiscuousChangePtr */
DriverStatisticsChange, /* DriverStatisticsChangePtr */
NULL, /* DriverRxLookAheadChangePtr */
NULL, /* DriverManagementPtr */
DriverEnableInterrupt, /* DriverEnableInterruptPtr */
DriverDisableInterrupt, /* DriverDisableInterruptPtr */
NULL, /* DriverISRPtr2 */
&DriverMessages, /* DriverMessagesPtr */
&CHSMSPEC, /* HSM Specification Version */
NULL, /* Driver Priority Queue Ptr */
NULL /* DriverDisableInterrupt2Ptr */
};
/**************************************************************************\
**
** Parameters required by ParseDriverParameters.
**
\**************************************************************************/
UINT32 SlotsWithMyBoardCount;
struct
{
UINT32 OptionCount;
UINT32 UNumOptVal[8];
} SlotsWithMyBoard = {0, {0, 0, 0, 0, 0, 0, 0, 0}};
DRIVER_OPTION SlotOption =
{ NULL, NULL, (PARAMETER_OPTIONS *)&SlotsWithMyBoard, 0, 0, SLOTPARAM,
REQUIREDPARAM | ENUMPARAM, };
UINT32 commonMaximumSize;
UINT8 eisaInterruptField;
UINT32 systemMemoryMap [2 * 8];
UINT32 pcode;
/**************************************************************************\
**
** Custom Keyword Information.
**
\**************************************************************************/
DRIVER_OPTION PollOption =
{ &SlotOption, CNE3200_POLLOPTION_TXTMSG, 0, 0xffff,
DEFAULT_TIMEOUT_VALUE, CUSTOMPARAM,
OPTIONALPARAM | RANGEPARAM | DEFAULTPRESENT, };
/**************************************************************************\
**
** Procedures
**
\**************************************************************************/
/**************************************************************************\
**
** PROC NAME: DriverInit
**
** This routine will call CEtherTSMRegisterHSM,
** CMSMParseDriverParameters, CMSMRegisterHardwareOptions,
** CMSMSetHardwareInterrupt, CMSMRegisterMLID, initialize
** variables in the Adapter Data Space and reset/initialize
** the card.
**
** Parameters: IN Numerous HSM Stack parameters passed in by the
** loader.
**
** Return Value: ODISTAT_SUCCESSFUL - The Hardware initialized successfully.
** ODISTAT_FAIL - The Hardware failed to initialize.
**
** See Also:
**
\**************************************************************************/
ODISTAT DriverInit (
struct _MODULE_HANDLE_ *ModuleHandle,
SCREEN_HANDLE *ScreenHandle,
MEON *CommandLine,
MEON *ModuleLoadPath,
UINT32 UnitializedDataLength,
void *CustomDataFileHandle,
UINT32 (* FileRead)(
void *FileHandle,
UINT32 FileOffset,
void *FileBuffer,
UINT32 FileSize),
UINT32 CustomDataOffset,
UINT32 CustomDataSize,
UINT32 NumMsgs,
MEON **Msgs)
{
CHSM_STACK chsmStack;
CONFIG_TABLE *configTable;
DRIVER_DATA *driverData;
REG_TYPE ccode;
UINT8 cfgBlock [EISA_CFG_BLOCK_SIZE];
UINT16 block = 0;
UINT32 i, physSlot;
UINT32 scanSeq = -1;
UINT32 uniqueID;
void *temp_DBusTag;
MEON productID[PRODUCT_ID_LEN] = {MANUFACT_CHAR_CODE_1,
MANUFACT_CHAR_CODE_2,
PRODUCT_NUMBER_07,
PRODUCT_NUMBER_01};
/***********************************************************************\
** Fill in HSMStack fields and register the HSM
\***********************************************************************/
chsmStack.ModuleHandle = ModuleHandle;
chsmStack.ScreenHandle = ScreenHandle;
chsmStack.CommandLine = CommandLine;
chsmStack.ModuleLoadPath = ModuleLoadPath;
chsmStack.UnitializedDataLength = UnitializedDataLength;
chsmStack.CustomDataFileHandle = CustomDataFileHandle;
chsmStack.FileRead = FileRead;
chsmStack.CustomDataOffset = CustomDataOffset;
chsmStack.CustomDataSize = CustomDataSize;
chsmStack.NumMsgs = NumMsgs;
chsmStack.Msgs = Msgs;
DriverParameterBlock.DriverInitParmPointer = &chsmStack;
/* 970219 MPK - Initialize the parser before parsing */
CMSMInitParser(&DriverParameterBlock);
if (CEtherTSMRegisterHSM (&DriverParameterBlock, &configTable) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Save maximum packet size for allocating RCB's at run time
\***********************************************************************/
commonMaximumSize = configTable->MLIDCFG_MaxFrameSize;
/***********************************************************************\
** Find all of the ne3200 NICs in the machine
\***********************************************************************/
/* Let MSM search for all NE3200 cards, first check for EISA ID "NVL 07 01 */
SlotsWithMyBoardCount = 0;
while (CMSMSearchAdapter (
&scanSeq,
ODI_BUSTYPE_EISA,
PRODUCT_ID_LEN,
productID,
&temp_DBusTag,
&uniqueID)
== ODI_NBI_SUCCESSFUL)
{
configTable->MLIDCFG_DBusTag = temp_DBusTag;
if ( CMSMGetInstanceNumber(
configTable->MLIDCFG_DBusTag,
uniqueID,
(UINT16 *)&SlotsWithMyBoard.UNumOptVal[SlotsWithMyBoardCount])
== ODI_NBI_SUCCESSFUL)
{
SlotsWithMyBoardCount++;
}
}
/* Now check for EISA ID "NVL 07 02" */
scanSeq = -1;
productID[PRODUCT_ID_LEN - 1] = PRODUCT_NUMBER_02;
while (CMSMSearchAdapter (
&scanSeq,
ODI_BUSTYPE_EISA,
PRODUCT_ID_LEN,
productID,
&temp_DBusTag,
&uniqueID)
== ODI_NBI_SUCCESSFUL)
{
configTable->MLIDCFG_DBusTag =temp_DBusTag;
if ( CMSMGetInstanceNumber(
configTable->MLIDCFG_DBusTag,
uniqueID,
(UINT16 *)&SlotsWithMyBoard.UNumOptVal[SlotsWithMyBoardCount])
== ODI_NBI_SUCCESSFUL)
{
SlotsWithMyBoardCount++;
}
}
SlotsWithMyBoard.OptionCount = SlotsWithMyBoardCount;
if (!SlotsWithMyBoardCount)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_NOBOARD_MSG,
NULL,
NULL);
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
else if (SlotsWithMyBoardCount == 1)
{ /* If only one board then no need to parse for slot */
configTable->MLIDCFG_Slot = SlotsWithMyBoard.UNumOptVal[0];
PollOption.Link = NULL;
}
/***********************************************************************\
** Let the MSM parse the command line
\***********************************************************************/
if ((ccode = CMSMParseDriverParameters(&DriverParameterBlock, &PollOption)) != ODISTAT_SUCCESSFUL)
{ /* If only PollOption then don't die if ODISTAT_ITEM_NOT_PRESENT */
if ((SlotsWithMyBoardCount == 1) && (ccode != ODISTAT_ITEM_NOT_PRESENT))
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
}
/***********************************************************************\
** Store base I/O port based on slot chosen
\***********************************************************************/
if ( CMSMGetInstanceNumberMapping(
configTable->MLIDCFG_Slot,
&configTable->MLIDCFG_DBusTag,
&uniqueID)
!= ODI_NBI_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
if ( CMSMGetUniqueIdentifierParameters(
configTable->MLIDCFG_DBusTag,
uniqueID,
1,
&physSlot)
!= ODI_NBI_SUCCESSFUL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
configTable->MLIDCFG_IOPort0 = (physSlot << 12) + SLOT_0;
/***********************************************************************\
** Read configuration based on slot chosen
\***********************************************************************/
while (TRUE)
{
if (CMSMGetCardConfigInfo (
configTable->MLIDCFG_DBusTag,
uniqueID,
EISA_CFG_BLOCK_SIZE,
block,
NULL,
cfgBlock)
!= ODI_NBI_SUCCESSFUL)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_NOIRQERR_MSG,
NULL,
NULL);
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
block++;
if (cfgBlock [EISA_VALID_INT] & EISA_INT_FUNCTION_BIT)
{
eisaInterruptField = cfgBlock [EISA_INTERRUPT];
if (eisaInterruptField & ISOLATE_INT_MASK)
{
eisaInterruptField &= ISOLATE_INT_MASK;
configTable->MLIDCFG_Interrupt0 = eisaInterruptField;
break;
}
}
}
/***********************************************************************\
** Let MSM Register the hardware options
\***********************************************************************/
if ((ccode = CMSMRegisterHardwareOptions (configTable, &driverData)) == REG_TYPE_FAIL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Check if new frame for existing adapter... if so we're done
\***********************************************************************/
if (ccode == REG_TYPE_NEW_FRAME)
goto DriverInitExit;
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = TOTAL_TCBS;
CFixUpStatStrings (driverData);
if (eisaInterruptField & EISA_SHARED_INT_MASK)
driverData->globalConfigValue &= GLOBAL_CFG_SHARE_MASK;
/***********************************************************************\
** Initialize the ADS now that we have a pointer to it
\***********************************************************************/
if (CMSMGetBusType (configTable->MLIDCFG_DBusTag, &driverData->busType) != ODI_NBI_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Initialize all I/O port addresses and aliases
\***********************************************************************/
driverData->eisaSystemDoorbellEnable = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + SYSTEM_DOORBELL_MASK_REG);
driverData->eisaSystemDoorbellStatus = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + SYSTEM_DOORBELL_INT_STATUS_REG);
driverData->idleMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 0);
driverData->updateParmMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 1);
driverData->updateStatMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 2);
driverData->updateStatCount = 0;
driverData->tcbValidMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 3);
driverData->tcbMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 4);
driverData->pollingMailbox = driverData->tcbMailbox;
driverData->parametersMailbox = (void *) ((UINT8 *) configTable->MLIDCFG_IOPort0 + MAILBOX_REGISTERS + 12);
driverData->resetRegister = (void *) ((UINT32) physSlot << 12);
/***********************************************************************\
** Reset the adapter
\***********************************************************************/
if (CMSMGetPollSupportLevel() > 1)
driverData->pollTimeout = PollOption.Parameter1.Max;
else
driverData->pollTimeout = 0;
for (i = 0; i < TABLE_SIZE; i++)
driverData->adapterRCBList[i] = (RCB *)-1;
for (i = 0; i < TCB_TABLE_SIZE; i++)
driverData->adapterTCBList[i] = (TCB *)-1;
if (DriverReset (driverData, configTable, OP_SCOPE_ADAPTER) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
driverData->AdapterResetCount--;
/***********************************************************************\
** Lets Register with the LSL
\***********************************************************************/
if (CMSMRegisterMLID (driverData, configTable) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Let MSM set up our interrupt procedure and set resetlevel
\******************yy*****************************************************/
if (CMSMSetHardwareInterrupt (driverData, configTable) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Let MSM enable callback and exit DriverInit
\***********************************************************************/
if ((CMSMScheduleAES (driverData, &driverData->DAES)) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
if (driverData->pollTimeout)
{
if (CMSMEnablePolling (driverData) != ODISTAT_SUCCESSFUL)
{
CMSMReturnDriverResources (configTable);
return (ODISTAT_FAIL);
}
}
if (driverData->pollTimeout)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_INFO,
CNE3200_POLLIRQBACKUP_MSG,
(void *) (driverData->pollTimeout * 400),
NULL);
}
else
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_INFO,
CNE3200_IRQMODEONLY_MSG,
NULL,
NULL);
}
/***********************************************************************\
** Determine frame type,
** wait for the parameter mailbox to clear,
** then send Parm Block to the adapter.
\***********************************************************************/
DriverInitExit:
switch (configTable->MLIDCFG_FrameID)
{
case 2:
driverData->boardNumberEII = configTable->MLIDCFG_BoardNumber;
break;
case 3:
driverData->boardNumber8022 = configTable->MLIDCFG_BoardNumber;
break;
case 5:
driverData->boardNumber8023 = configTable->MLIDCFG_BoardNumber;
break;
case 10:
driverData->boardNumberSNAP = configTable->MLIDCFG_BoardNumber;
}
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, 1);
PollOption.Parameter1.Max = 0xffff; /* Reset Options for next load */
/***********************************************************************\
** TNL 12/06/95 Register with NESL as producer of Service Resume event.
\***********************************************************************/
if (!NESLRegisterDone)
{
if ((NESLServiceResumeNECBPtr =
(NESL_ECB *)CMSMInitAlloc(sizeof(NESL_ECB))) == NULL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
NESLServiceResumeNECBPtr->NecbVersion = NESL_VERSION2;
NESLServiceResumeNECBPtr->NecbEventName = NESL_Service_Resume;
NESLServiceResumeNECBPtr->NecbRefData = NESL_NOT_UNIQUE_PRODUCER |
NESL_BROADCAST_EVENT | NESL_SORT_CONSUMER_BOTTOM_UP;
NESLServiceResumeNECBPtr->NecbOwner = ModuleHandle;
NESLServiceResumeNECBPtr->NecbContext = NULL;
if (CMSMNESLRegisterProducer(NESLServiceResumeNECBPtr) != NESL_OK)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
if ((NESL_EPBPtr = (EPB *)CMSMInitAlloc(sizeof(EPB))) == NULL)
{
CMSMReturnDriverResources(configTable);
return ODISTAT_FAIL;
}
NESL_EPBPtr->EPBMajorVersion = EPBMajVer;
NESL_EPBPtr->EPBMinorVersion = EPBMinVer;
NESLRegisterDone = TRUE;
}
/* Set up to produce NESL MLID Card Insertion Complete event */
NESL_EPBPtr->EPBEventName = NESL_Service_Resume;
NESL_EPBPtr->EPBEventType = NESL_MLID_Card_Insertion_Complete;
NESL_EPBPtr->EPBModuleName = 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;
}
/**************************************************************************\
**
** PROC NAME: DriverRemove
**
** This routine will called when the driver image is
** to be deleted from memory.
**
** Parameters: NONE
**
** Return Value: NONE
**
** See Also:
**
\**************************************************************************/
void DriverRemove (void)
{
/* Clean up all NESL related stuff */
CMSMNESLDeRegisterProducer(NESLServiceResumeNECBPtr);
CMSMFree(NULL,NESLServiceResumeNECBPtr);
CMSMFree(NULL,NESL_EPBPtr);
CMSMDriverRemove (DriverParameterBlock.DriverModuleHandle);
return;
}
/**************************************************************************\
**
** PROC NAME: DriverReset
**
** This routine will called when the driver needs to be
** reset to its original pristine state.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
** IN OPERATION_SCOPE operationScope
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
** operationScope - OP_SCOPE_ADPATER or OP_SCOPE_LOGICAL_BOARD
**
** Return Value: ODISTAT_SUCCESSFUL = successful
** ODISTAT_FAIL = unsuccessful
**
** See Also:
**
\**************************************************************************/
ODISTAT DriverReset (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
OPERATION_SCOPE operationScope)
{
RCB *physRCB;
RCB *logRCB;
void *physAddr;
UINT32 i, boardIndex;
CONFIG_TABLE *tempConfig;
driverData->inDriverReset = -1;
if (operationScope == OP_SCOPE_ADAPTER)
{
driverData->AdapterResetCount++;
/***********************************************************************\
** Call DriverShutdown to reset NE3200 and return any TCB's or
** RCB's that the driver has in its possession.
\***********************************************************************/
DriverShutdown (driverData, configTable, SHUTDOWN_PARTIAL, OP_SCOPE_ADAPTER);
/* CMSMShutdownMLID (driverData, SHUTDOWN_PARTIAL);*/
driverData->receiveQueueHead = 0;
driverData->receiveQueueTail = 0;
if (logRCB = CMSMAllocateRCB (driverData, commonMaximumSize, &physRCB))
{
driverData->needRCBCount--;
driverData->hostPWSList1 [0] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0];
driverData->hostPWSList2 [0] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1];
driverData->hostRCBList [0] = logRCB;
driverData->adapterRCBList [0] = physRCB;
driverData->receiveQueueTail++;
}
/***********************************************************************\
** Wait for NIC to report its initial status.
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->idleMailbox, WAIT_BYTE_SET, WAIT_LOOP*2);
/***********************************************************************\
** Check for error conditions.
\***********************************************************************/
if (!(pcode & FIRMWARE_INIT_SUCCESS))
{
if (!pcode)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_FIRMWAREINITERR_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
if (pcode & STATIC_RAM_ERROR_MASK)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_MEMERR_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_CHECKSUMERR_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Firmware initialized successfully...Tell NE3200 where to read
** the firmware from.
\***********************************************************************/
Out8 (configTable->MLIDCFG_DBusTag,
(void *) ((UINT8 *) driverData->idleMailbox + 1),
(UINT8) (DriverParameterBlock.DriverFirmwareSize));
Out8 (configTable->MLIDCFG_DBusTag,
(void *) ((UINT8 *) driverData->idleMailbox + 2),
(UINT8) (VALUE_TO_HILO_UINT16 ((UINT16) (DriverParameterBlock.DriverFirmwareSize))));
physAddr = CMSMGetPhysical (DriverParameterBlock.DriverFirmwareBuffer);
Out32 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->idleMailbox + 4), (UINT32) physAddr);
Out32 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->idleMailbox + 8), 0);
Out8 (configTable->MLIDCFG_DBusTag, driverData->idleMailbox, 0);
/***********************************************************************\
** Wait for the download process to complete.
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->parametersMailbox, WAIT_FIRMWARE, WAIT_LOOP*2);
if (pcode != FIRMWARE_RUNNING)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_FIRMWARESTARTERR_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
/***********************************************************************\
** At this point the firmware is operational.
** Now fill in and send adapter parameter block to adapter.
\***********************************************************************/
driverData->nodeAddressPointer = CMSMGetPhysical (&configTable->MLIDCFG_NodeAddress);
driverData->maxReceivePacketSize = configTable->MLIDCFG_MaxFrameSize;
driverData->genericStatisticsPointer = CMSMGetPhysical (&driverData->PacketTxTooBigCount);
driverData->customStatisticsCount = NUMBER_OF_CUSTOMS;
driverData->rcbListPointer = CMSMGetPhysical (&driverData->adapterRCBList);
CEtherTSMUpdateMulticast (driverData);
for (i = 0; i < ADDR_SIZE; i++)
driverData->hostNodeAddress [i] = configTable->MLIDCFG_NodeAddress.nodeAddress [i];
/***********************************************************************\
** An OP_SCOPE_ADAPTER reset implies that any previous partial
** shutdowns of logical boards are now reactivated. LON 970708
\***********************************************************************/
for (boardIndex=0; boardIndex < 4; boardIndex++)
{
if ((tempConfig = DADSP_TO_CMSMADSP
(driverData)->CMSMVirtualBoardLink [boardIndex]) !=NULL)
{
switch (tempConfig->MLIDCFG_FrameID)
{
case 2:
driverData->boardNumberEII = tempConfig->MLIDCFG_BoardNumber;
break;
case 3:
driverData->boardNumber8022 = tempConfig->MLIDCFG_BoardNumber;
break;
case 5:
driverData->boardNumber8023 = tempConfig->MLIDCFG_BoardNumber;
break;
case 10:
driverData->boardNumberSNAP = tempConfig->MLIDCFG_BoardNumber;
}
}
}
/***********************************************************************\
** Tell the firmware that the driver parameters has been updated.
\***********************************************************************/
Out32 (configTable->MLIDCFG_DBusTag, driverData->parametersMailbox, (UINT32) (CMSMGetPhysical (&driverData->logicalToPhysicalOffset)));
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, 1);
/***********************************************************************\
** Wait for the parameter block to be sent to the adapter ok.
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP * 2);
if (pcode)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_BOARDFAIL_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
/***********************************************************************\
** Parameters downloaded successfully.
\***********************************************************************/
Out8 (configTable->MLIDCFG_DBusTag, driverData->pollingMailbox, 0);
Out8 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->eisaSystemDoorbellEnable + 1), -1);
Out8 (configTable->MLIDCFG_DBusTag, driverData->eisaSystemDoorbellEnable, 1);
Out8 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->eisaSystemDoorbellEnable - 6), driverData->globalConfigValue);
Out8 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->eisaSystemDoorbellEnable - 5), 1);
driverData->inDriverReset = 0;
return ODISTAT_SUCCESSFUL;
}
else
{
/***********************************************************************\
** An OP_SCOPE_LOGICAL reset requests a previously shutdown logical
** board to now be reactivated. LON 970708
\***********************************************************************/
switch (configTable->MLIDCFG_FrameID)
{
case 2:
driverData->boardNumberEII = configTable->MLIDCFG_BoardNumber;
break;
case 3:
driverData->boardNumber8022 = configTable->MLIDCFG_BoardNumber;
break;
case 5:
driverData->boardNumber8023 = configTable->MLIDCFG_BoardNumber;
break;
case 10:
driverData->boardNumberSNAP = configTable->MLIDCFG_BoardNumber;
}
/***********************************************************************\
** Tell the firmware that the driver parameters has been updated.
** Setting the above board to its board number causes the firmware to
** start receiving frames belonging to that board type. LON 970708
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, 1);
/***********************************************************************\
** Wait for the parameter block to be sent to the adapter ok.
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP * 2);
if (pcode)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_BOARDFAIL_MSG,
NULL,
NULL);
driverData->inDriverReset = 0;
return (ODISTAT_FAIL);
}
driverData->inDriverReset = 0;
return ODISTAT_SUCCESSFUL;
}
}
/**************************************************************************\
**
** PROC NAME: DriverMulticastChange
**
** 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).
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
** IN GROUP_ADDR_LIST_NODE *mcTable
** IN UINT32 numEntries
** IN UINT32 functionalTable
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
** mcTable - Pointer to HSM's multicast table entries
** numEntries - The number of entires in multicast table
** functionalTable - 32-bit functional address N/A
**
** Return Value: NONE
**
** See Also: ETHERTSM\CEtherTSMAddMulticastAddress
** ETHERTSM\CEtherTSMDeleteMulticastAddress
** ETHERTSM\CEtherTSMUpdateMulticast
**
\**************************************************************************/
ODISTAT DriverMulticastChange (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
GROUP_ADDR_LIST_NODE *mcTable,
UINT32 numEntries,
UINT32 functionalTable)
{
functionalTable = functionalTable;
driverData->multicastCount = numEntries;
driverData->multicastTablePointer = CMSMGetPhysical ((void *) mcTable);
if (!driverData->inDriverReset)
{
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
pcode++;
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, (UINT8) pcode);
}
return ODISTAT_SUCCESSFUL;
}
/**************************************************************************\
**
** PROC NAME: DriverPromiscuousChange
**
** This routine is called to enable or disable the
** promiscuous mode capabilities of the adapter.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
**
** Return Value: NONE
**
** See Also: ETHERTSM\CEtherTSMPromiscuousChange
**
\**************************************************************************/
ODISTAT DriverPromiscuousChange (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
UINT32 promMode)
{
driverData->promiscuousMode = (UINT8) promMode;
if (!driverData->inDriverReset)
{
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
pcode++;
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, (UINT8) pcode);
}
return ODISTAT_SUCCESSFUL;
}
/**************************************************************************\
**
** PROC NAME: DriverStatisticsChange
**
** This routine will update the statistics table.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
**
** Return Value: NONE
**
** See Also: ETHERTSM\CEtherTSMPromiscuousChange
**
\**************************************************************************/
ODISTAT DriverStatisticsChange (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
UINT32 startTime;
/* Tell firmware to update stats */
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateStatMailbox, 1);
startTime = CMSMGetMicroTimer();
for (startTime = -startTime; (CMSMGetMicroTimer() + startTime) < 16000;);
driverData->updateStatCount = 0;
return ODISTAT_SUCCESSFUL;
}
/**************************************************************************\
**
** PROC NAME: DriverShutdown
**
** This routine will called when the driver needs to be
** shutdown either temporarily or permanently.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
** IN UINT32 shutDownType
** IN OPERATION_SCOPE operationScope
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
** shutDownType - PERMANENT_SHUTDOWN or TEMPORARY_SHUTDOWN
** operationScope - OP_SCOPE_ADAPTER or OP_SCOPE_LOGICAL_BOARD
**
** Return Value: ODISTAT_SUCCESSFUL = successful
** ODISTAT_FAIL = unsuccessful
**
** See Also: ETHERTSM\CEtherTSMShutdown
**
\**************************************************************************/
ODISTAT DriverShutdown (
DRIVER_DATA *driverData,
MLID_ConfigTable *configTable,
UINT32 shutDownType,
OPERATION_SCOPE operationScope)
{
RCB *retRCB;
TCB *retTCB;
UINT32 numRCBs;
UINT32 i;
if (operationScope == OP_SCOPE_LOGICAL_BOARD)
{
if ((configTable->MLIDCFG_SharingFlags & MS_SHUTDOWN_BIT)
&& (!driverData->inDriverReset))
{
/***********************************************************************\
** An OP_SCOPE_LOGICAL shutdown is a request by the MSM/TSM to
** shutdown one logical board. LON 970708
\***********************************************************************/
switch (configTable->MLIDCFG_FrameID)
{
case 2:
driverData->boardNumberEII = -1;
break;
case 3:
driverData->boardNumber8022 = -1;
break;
case 5:
driverData->boardNumber8023 = -1;
break;
case 10:
driverData->boardNumberSNAP = -1;
}
/***********************************************************************\
** Tell the firmware that the driver parameters has been updated.
** Setting the above board to -1 causes the firmware to discard
** rcv frames belonging to that board type. LON 970708
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateParmMailbox, 1);
/***********************************************************************\
** Wait for the parameter block to be sent to the adapter ok.
\***********************************************************************/
pcode = WaitForEvent (driverData, driverData->updateParmMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP * 2);
if (pcode)
{
CMSMPrintString (
configTable,
MSG_TYPE_INIT_ERROR,
CNE3200_BOARDFAIL_MSG,
NULL,
NULL);
return (ODISTAT_FAIL); /* Exit */
}
}
return ODISTAT_SUCCESSFUL; /* Exit */
}
if ( !driverData->inDriverReset) /* OP_SCOPE_ADAPTER */
{
/***********************************************************************\
** Set card into idle state.
\***********************************************************************/
Out8 (configTable->MLIDCFG_DBusTag, driverData->idleMailbox, 1);
pcode = WaitForEvent (driverData, driverData->idleMailbox, WAIT_BYTE_CLEAR, WAIT_LOOP);
}
if (shutDownType == SHUTDOWN_PARTIAL) /* or someday HSM_TEMPORARY_SHUTDOWN */
{
/***********************************************************************\
** Set reset bit and clear abend mailbox.
** Allow reset settling time.
\***********************************************************************/
Out32 (configTable->MLIDCFG_DBusTag, driverData->resetRegister, 1);
Out8 (configTable->MLIDCFG_DBusTag, driverData->idleMailbox, 0);
WaitForEvent (driverData, NULL, WAIT_TIMEOUT, WAIT_RESET);
Out32 (configTable->MLIDCFG_DBusTag, driverData->resetRegister, 0);
}
else
{
if ( !driverData->inDriverReset) /* LON 970708 */
{
/* MSM/TSM called for a Permanent shutdown so disable interrupts. */
Out8 (driverData->busTag, driverData->eisaSystemDoorbellEnable, 0);
}
}
/***********************************************************************\
** Clear interrupt status in case it is level triggered.
\***********************************************************************/
Out8 (configTable->MLIDCFG_DBusTag, driverData->eisaSystemDoorbellStatus,
In8 (configTable->MLIDCFG_DBusTag, driverData->eisaSystemDoorbellStatus));
/***********************************************************************\
** Return any receive ECB's.
\***********************************************************************/
numRCBs = TOTAL_RCBS - driverData->needRCBCount;
while (numRCBs)
{
retRCB = driverData->hostRCBList [driverData->receiveQueueHead];
CMSMReturnRCB (driverData, retRCB);
driverData->receiveQueueHead = (driverData->receiveQueueHead + 1) & TABLE_MASK;
numRCBs--;
}
/***********************************************************************\
** Return any transmit ECB's.
\***********************************************************************/
while (DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount != TOTAL_TCBS)
{
retTCB = driverData->hostTCBList [driverData->tcbQueueHead];
driverData->tcbQueueHead = (driverData->tcbQueueHead + 1) & TCB_TABLE_MASK;
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
CEtherTSMFastSendComplete (driverData, retTCB, -1);
}
/***********************************************************************\
** Shutdown the initialization variables.
\***********************************************************************/
driverData->tcbQueueHead = 0;
driverData->tcbQueueTail = 0;
if (shutDownType == SHUTDOWN_PARTIAL) /* or someday HSM_TEMPORARY_SHUTDOWN */
{
driverData->needRCBCount = TOTAL_RCBS;
}
else
{
/* We're in the process of totally shutting down the driver due
* to a call to our DriverRemove. We reset NeedRCBCount to zero
* so that any pending interrupts that invoke our DriverISR will
* not cause this HSM to request more RCBs be allocated due to
* the NeedRCBCount being non-zero. LON 223362
*/
driverData->needRCBCount = 0;
}
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount = TOTAL_TCBS;
for (i = 0; i < TABLE_SIZE; i++)
{
driverData->adapterRCBList[i] = (RCB *)-1;
driverData->hostRCBList[i] = 0;
}
for (i = 0; i < TCB_TABLE_SIZE; i++)
{
driverData->adapterTCBList[i] = (TCB *)-1;
driverData->hostTCBList[i] = 0;
}
return ODISTAT_SUCCESSFUL;
}
/**************************************************************************\
**
** PROC NAME: DriverSend
**
** This routine will called when the driver wants to
** send a packet described in the TCB to the NIC and
** initiate the send. txStartTime and retryCounter must be
** set to enable the deadman timer.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
** IN TCB *tcb
** IN UINT32 pktSize
** IN TCB *physTcb
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
** tcb - Pointer to the TCB to be processed
** pktSize - The length of the packet to be sent
** physTcb - N/A
**
** Return Value: NONE
**
** See Also: ETHERTSM\CMediaSend
** ETHERTSM\MediaSendRaw8023
** ETHERTSM\MediaSendEthernetII
** ETHERTSM\MediaSend8022Over8023
** ETHERTSM\MediaSend8022Snap
**
\**************************************************************************/
void DriverSend (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable,
TCB *logTCB,
UINT32 pktSize,
void *physTCB)
{
TCB *oldTCB;
#ifdef OUT_CHAR
NiosDebugCharOut ('S');
#endif /* OUT_CHAR */
pktSize = pktSize;
/***********************************************************************\
** Update the transmit lists.
\***********************************************************************/
driverData->hostTCBList [driverData->tcbQueueTail] = logTCB;
driverData->adapterTCBList [driverData->tcbQueueTail] = physTCB;
driverData->txStartList [driverData->tcbQueueTail] = CMSMGetCurrentTime ();
/***********************************************************************\
** Set the TRANSMIT WAITING bit and adjust Q Tail.
\***********************************************************************/
Out8 (configTable->MLIDCFG_DBusTag, (void *) ((UINT8 *) driverData->tcbValidMailbox), (UINT8)((driverData->tcbQueueTail+1) & TCB_TABLE_MASK));
driverData->tcbQueueTail = (driverData->tcbQueueTail + 1) & TCB_TABLE_MASK;
/***********************************************************************\
** Check for transmit pending/done.
\***********************************************************************/
if ((DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount < (TOTAL_TCBS - 1)) &&
(driverData->adapterTCBList [driverData->tcbQueueHead] == (struct _TCB_ *)-1))
{
#ifdef OUT_CHAR
NiosDebugCharOut ('t');
#endif /* OUT_CHAR */
oldTCB = driverData->hostTCBList [driverData->tcbQueueHead];
driverData->tcbQueueHead = (driverData->tcbQueueHead + 1) & TCB_TABLE_MASK;
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
CEtherTSMFastSendComplete (driverData, oldTCB, 0);
}
#ifdef OUT_CHAR
NiosDebugCharOut ('s');
#endif /* OUT_CHAR */
}
/**************************************************************************\
**
** PROC NAME: CFixUpStatStrings
**
** This routine will be called to insert the description
** strings for each counter.
**
** Parameters: IN DRIVER_DATA *driverData
**
** driverData - Pointer to HSM's AdapterDataSPace
**
** Return Value: NONE
**
** See Also: DriverInit
**
\**************************************************************************/
void CFixUpStatStrings (DRIVER_DATA *driverData)
{
driverData->TxRetryFailureTable.StatString = (MEON_STRING *)CNE3200_TXRETRYFAIL_STR;
driverData->ClearToSendTable.StatString = (MEON_STRING *)CNE3200_CLEARSENDTABLE_STR;
driverData->UnderRunTable.StatString = (MEON_STRING *)CNE3200_UNDERRUN_STR;
driverData->RxDMAOverrunTable.StatString = (MEON_STRING *)CNE3200_RXDMAOVERRUN_STR;
driverData->PacketSlideTable.StatString = (MEON_STRING *)CNE3200_PACKETSLIDE_STR;
driverData->DummyRCBTable.StatString = (MEON_STRING *)CNE3200_DUMMYRCB_STR;
driverData->AdapterReset1Table.StatString = (MEON_STRING *)CNE3200_ADAPTERRESET_STR;
driverData->BadFragLengthTable.StatString = (MEON_STRING *)CNE3200_BADFRAGLEN_STR;
driverData->PollingTimeoutTable.StatString = (MEON_STRING *)CNE3200_POLLTIMEOUT_STR;
driverData->AdapterDiedTable.StatString = (MEON_STRING *)CNE3200_ADAPTERDIED_STR;
driverData->NumberOfIntsFiredTable.StatString = (MEON_STRING *)CNE3200_NUMINTSFIRED_STR;
}
/**************************************************************************\
**
** PROC NAME: DriverCallBack
**
** This routine will be executed once every 1/2 second. It
** will detect if the hardware does NOT complete a
** transmission. If this happens, the harware 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.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
**
** Return Value: NONE
**
** See Also: CMSM
**
\**************************************************************************/
void DriverCallBack (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('c');
#endif /* OUT_CHAR */
if (driverData->updateStatCount >= 8) /* 4 sec yet ? */
{
/********************************************************************\
** Tell the adapter to update the statistics.
\********************************************************************/
driverData->updateStatCount = 0;
Out8 (configTable->MLIDCFG_DBusTag, driverData->updateStatMailbox, 1);
}
/***********************************************************************\
** Check for transmits pending, then transmits complete.
\***********************************************************************/
if (DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount == TOTAL_TCBS)
return;
if (driverData->adapterTCBList [driverData->tcbQueueHead] == (struct _TCB_ *)-1)
return;
/***********************************************************************\
** Looks like we have a transmit pending AND its NOT yet complete.
** See if its DEAD.
\***********************************************************************/
if ((CMSMGetCurrentTime () - driverData->txStartList [driverData->tcbQueueHead]) >= DEADMAN_TIMEOUT)
{
driverData->AdapterDiedCount++;
DriverReset (driverData, configTable, OP_SCOPE_ADAPTER);
}
}
/**************************************************************************\
**
** PROC NAME: DriverISR
**
** This routine handles packet reception/errors and transmit
** complete/errors interrupts.
**
** Parameters: IN DRIVER_DATA *driverData
**
** driverData - Pointer to HSM's adapter data space
**
** Return Value: NONE
**
** See Also: CMSM\CMSMInterruptProcedure0
**
\**************************************************************************/
void DriverISR (DRIVER_DATA *driverData)
{
CONFIG_TABLE *configTable;
RCB *logRCB;
RCB *physRCB;
TCB *logTCB;
UINT32 pktSize;
UINT8 sInts;
UINT32 oldRcvQHead;
sInts = sInts; /* Keep compiler happy for now */
#ifdef OUT_CHAR
NiosDebugCharOut ('I');
#endif /* OUT_CHAR */
configTable = DADSP_TO_CMSMADSP (driverData)->CMSMDefaultVirtualBoard;
/***********************************************************************\
** See if we are in our polling routine.
\***********************************************************************/
driverData->NumberOfIntsFiredCount++;
if (driverData->inDriverPoll)
return;
/***********************************************************************\
** <<< Check RCBs >>>
** Check for ALL RCB's and pass them up to LSL for processing.
\***********************************************************************/
while (!driverData->adapterRCBList [driverData->receiveQueueHead])
{
#ifdef OUT_CHAR
NiosDebugCharOut ('r');
#endif /* OUT_CHAR */
/********************************************************************\
** Adjust receive lists.
\********************************************************************/
driverData->adapterRCBList [driverData->receiveQueueHead] = (RCB *) -1;
logRCB = driverData->hostRCBList [driverData->receiveQueueHead];
oldRcvQHead = driverData->receiveQueueHead;
driverData->receiveQueueHead = (driverData->receiveQueueHead + 1) & TABLE_MASK;
driverData->needRCBCount++;
/********************************************************************\
** We are going to use the FastRcvComplete call to process the
** ECB that we have gotten from the adapter. The only problem
** with this is, the old firmware does NOT put the rcvStatus into
** the correct field of the ECB. The current "C" spec has the
** rcvStatus placed in the ECB_PreviousLink field. The firmware
** places the rcvStatus into the ProtocolWorkspace. Therefore, we
** must copy it to the correct location. This means we are 95%
** ECB aware but not quite 100% like we should be without changing
** the firmware.
\********************************************************************/
((ECB *) logRCB)->ECB_PreviousLink = (ECB *) (((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0]);
pktSize = (((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1]);
((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0] = driverData->hostPWSList1 [oldRcvQHead];
((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1] = driverData->hostPWSList2 [oldRcvQHead];
CEtherTSMFastRcvCompleteStatus (
driverData,
logRCB,
pktSize,
(UINT32)((ECB *) logRCB)->ECB_PreviousLink);
}
/***********************************************************************\
** <<< Pre-Allocate RCBs >>>
** Now that we have processed all the RCB's, let's see if we need
** to preallocate any more for the packets coming in off the wire.
\***********************************************************************/
while (driverData->needRCBCount)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('a');
#endif /* OUT_CHAR */
if (logRCB = CMSMAllocateRCB (driverData, commonMaximumSize, &physRCB))
{
driverData->needRCBCount--;
driverData->hostPWSList1 [driverData->receiveQueueTail] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0];
driverData->hostPWSList2 [driverData->receiveQueueTail] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1];
driverData->hostRCBList [driverData->receiveQueueTail] = logRCB;
driverData->adapterRCBList [driverData->receiveQueueTail] = physRCB;
driverData->receiveQueueTail = (driverData->receiveQueueTail + 1) & TABLE_MASK;
}
else
break;
}
/***********************************************************************\
** <<< Check TCBs >>>
** Now we have completely pre-allocated as many RCB's as we can.
** Let's check out the transmits that are finished.
\***********************************************************************/
while ((DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount != TOTAL_TCBS) &&
(driverData->adapterTCBList [driverData->tcbQueueHead] == (struct _TCB_ *)-1))
{
#ifdef OUT_CHAR
NiosDebugCharOut ('t');
#endif /* OUT_CHAR */
logTCB = driverData->hostTCBList [driverData->tcbQueueHead];
driverData->tcbQueueHead = (driverData->tcbQueueHead + 1) & TCB_TABLE_MASK;
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
CEtherTSMFastSendComplete (driverData, logTCB, 0);
}
#ifdef OUT_CHAR
NiosDebugCharOut ('i');
#endif /* OUT_CHAR */
return;
}
/**************************************************************************\
**
** PROC NAME: DriverPoll
**
** This routine will be called by the MSM/OS as dictated by
** the internal polling loop. This will be used as a backup
** to the interrupt method.
**
** Parameters: IN DRIVER_DATA *driverData
** IN FRAME_DS *configTable
**
** driverData - Pointer to HSM's adapter data space
** configTable - Pointer to HSM's frame data space
**
** Return Value: NONE
**
** See Also:
**
\**************************************************************************/
void DriverPoll (
DRIVER_DATA *driverData,
CONFIG_TABLE *configTable)
{
RCB *logRCB;
RCB *physRCB;
TCB *logTCB;
UINT32 pktSize;
UINT32 oldRcvQHead;
#ifdef OUT_CHAR
NiosDebugCharOut ('P');
#endif /* OUT_CHAR */
/***********************************************************************\
** Set in driver poll semaphore and do mailbox thing.
\***********************************************************************/
driverData->inDriverPoll = 1;
Out8 (configTable->MLIDCFG_DBusTag, driverData->pollingMailbox, 0);
/***********************************************************************\
** <<< Check RCBs >>>
** Check for ALL RCB's and pass them up to LSL for processing.
\***********************************************************************/
while (((UINT32) driverData->adapterRCBList [driverData->receiveQueueHead]) <= MAX_PACKET_SIZE)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('r');
#endif /* OUT_CHAR */
/********************************************************************\
** Adjust receive lists.
\********************************************************************/
driverData->adapterRCBList [driverData->receiveQueueHead] = (RCB *) -1;
logRCB = driverData->hostRCBList [driverData->receiveQueueHead];
oldRcvQHead = driverData->receiveQueueHead;
driverData->receiveQueueHead = (driverData->receiveQueueHead + 1) & TABLE_MASK;
driverData->needRCBCount++;
/********************************************************************\
** We are going to use the FastRcvComplete call to process the
** ECB that we have gotten from the adapter. The only problem
** with this is, the old firmware does NOT put the rcvStatus into
** the correct field of the ECB. The current "C" spec has the
** rcvStatus placed in the ECB_PreviousLink field. The firmware
** places the rcvStatus into the ProtocolWorkspace. Therefore, we
** must copy it to the correct location. This means we are 95%
** ECB aware but not quite 100% like we should be without changing
** the firmware.
\********************************************************************/
((ECB *) logRCB)->ECB_PreviousLink = (ECB *) (((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0]);
pktSize = (((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1]);
((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0] = driverData->hostPWSList1 [oldRcvQHead];
((ECB *) logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1] = driverData->hostPWSList2 [oldRcvQHead];
CEtherTSMFastRcvCompleteStatus (
driverData,
logRCB,
pktSize,
(UINT32)((ECB *) logRCB)->ECB_PreviousLink);
}
/***********************************************************************\
** <<< Pre-Allocate RCBs >>>
** Now that we have processed all the RCB's, let's see if we need
** to preallocate any more for the packets coming in off the wire.
\***********************************************************************/
while (driverData->needRCBCount)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('a');
#endif /* OUT_CHAR */
if (logRCB = CMSMAllocateRCB (driverData, commonMaximumSize, &physRCB))
{
driverData->needRCBCount--;
driverData->hostPWSList1 [driverData->receiveQueueTail] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [0];
driverData->hostPWSList2 [driverData->receiveQueueTail] = ((ECB *)logRCB)->ECB_ProtocolWorkspace.PWs_i32val [1];
driverData->hostRCBList [driverData->receiveQueueTail] = logRCB;
driverData->adapterRCBList [driverData->receiveQueueTail] = physRCB;
driverData->receiveQueueTail = (driverData->receiveQueueTail + 1) & TABLE_MASK;
}
else
break;
}
/***********************************************************************\
** <<< Check TCBs >>>
** Now we have completely pre-allocated as many RCB's as we can.
** Let's check out the transmits that are finished.
\***********************************************************************/
while ((DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount != TOTAL_TCBS) &&
(driverData->adapterTCBList [driverData->tcbQueueHead] == (struct _TCB_ *) -1))
{
#ifdef OUT_CHAR
NiosDebugCharOut ('t');
#endif /* OUT_CHAR */
logTCB = driverData->hostTCBList [driverData->tcbQueueHead];
driverData->tcbQueueHead = (driverData->tcbQueueHead + 1) & TCB_TABLE_MASK;
DADSP_TO_CMSMADSP (driverData)->CMSMTxFreeCount++;
CEtherTSMFastSendComplete (driverData, logTCB, 0);
}
driverData->inDriverPoll = 0;
#ifdef OUT_CHAR
NiosDebugCharOut ('p');
#endif /* OUT_CHAR */
return;
}
/**************************************************************************\
**
** PROC NAME: DriverDisableInterrupt
**
** This routine will disable the adapters ability to
** to interrupt the host.
**
** Parameters: IN DRIVER_DATA *driverData
**
** driverData - Pointer to HSM's adapter data space
** flag - TRUE if function is to return a value, else FALSE.
**
**
** Return Value: TRUE if adapter generated the interrupt, else FALSE.
**
** See Also: DriverEnableInterrupt
**
\**************************************************************************/
BOOLEAN DriverDisableInterrupt (DRIVER_DATA *driverData, BOOLEAN flag)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('{');
#endif /* OUT_CHAR */
if (driverData->inDriverDisable) /* We're already disabled, just return */
return (FALSE);
if (flag)
{ /* We need to return value indicating if int is ours or not */
if (In8 (driverData->busTag, driverData->eisaSystemDoorbellStatus) & 1)
{ /* We generated the interrupt, first disable doorbell */
Out8 (driverData->busTag, driverData->eisaSystemDoorbellEnable, 0);
driverData->inDriverDisable = 1; /* Set flag we're disabled */
/* then reset our status */
Out8 (driverData->busTag, driverData->eisaSystemDoorbellStatus, 1);
return (TRUE);
}
}
/*
** Either flag is FALSE or it's not our interrupt, disable NE3200's interrupt
** mechanism only.
*/
Out8 (driverData->busTag, driverData->eisaSystemDoorbellEnable, 0);
driverData->inDriverDisable = 1; /* Set flag we're disabled */
return (FALSE);
}
/**************************************************************************\
**
** PROC NAME: DriverEnableInterrupt
**
** This routine will enable the adapters ability to
** interrupt the host.
**
** Parameters: IN DRIVER_DATA *driverData
**
** driverData - Pointer to HSM's adapter data space
**
** Return Value: 0 = successful
** 1 = unsuccessful
**
** See Also: DriverDisableInterrupt
**
\**************************************************************************/
void DriverEnableInterrupt (DRIVER_DATA *driverData)
{
#ifdef OUT_CHAR
NiosDebugCharOut ('}');
#endif /* OUT_CHAR */
driverData->inDriverDisable = 0; /* Clear ints disable flag */
/*
** If we have an interrupt pending, this output to eisaSystemDoorbellStatus
** will clear it, which will cause a spurious interrupt.
**
** Best to just re-enable the adapters interrupts and if one is pending then
** we will re-enter or interrupt routine to deal with it and not miss it and
** hence no spurious interrupts.
*/
Out8 (driverData->busTag, driverData->eisaSystemDoorbellEnable, 1);
}
/**************************************************************************\
**
** PROC NAME: WaitForEvent
**
** This routine sits around and waits for either the event
** to occur or the timeout to occur.
**
** Parameters: IN DRIVER_DATA *driverData
**
** driverData - Pointer to HSM's adapter data space
**
** Return Value: 0 = successful
** 1 = unsuccessful
**
** See Also:
**
\**************************************************************************/
UINT32 WaitForEvent (
DRIVER_DATA *driverData,
void *port,
UINT8 type,
UINT32 timeout)
{
UINT32 ccode;
//JCJ 20-Aug-1997 SPD# 159385 Wait loop has been modified to a simple counter
// based one from a timer based loop. Because we
// can't let other process to run at this time.
do
{
timeout--;
switch (type)
{
case WAIT_BYTE_SET:
if (ccode = (UINT32) In8 (driverData->busTag, port))
{
return (ccode);
}
break;
case WAIT_BYTE_CLEAR:
if (!(ccode = (UINT32) In8 (driverData->busTag, port)))
{
return (ccode);
}
break;
case WAIT_FIRMWARE:
ccode = In32 (driverData->busTag, port);
if (ccode == FIRMWARE_RUNNING)
{
return (ccode);
}
break;
case WAIT_TIMEOUT:
break;
}
}while(timeout);
return 0;
}