home *** CD-ROM | disk | FTP | other *** search
- /*
- $Module NX.C$
-
- Copyright 1990
- By NetFRAME Systems Inc.
- Sunnyvale, California U.S.A.
-
- $Author: Karl S. Johnson $
- $Date: 03 Apr 1990 11:54:02 $
- $Revision: 1.2 $
-
- $Description$
- This is a NetWare Loadable Module to measure network performance.
- $EndDescription$
-
-
- Revision History
- $Log: H:/386/NLMS/DX/SRC/VCS/NX.C $
- *
- * Rev 1.2 03 Apr 1990 11:54:02 Karl S. Johnson
- * Recode scheduler in exerciser routine to clean up and to go to
- * sleep when there is nothing to do.
- *
- * Rev 1.1 02 Apr 1990 17:15:32 Karl S. Johnson
- * Various changes to make it work the first time on System Pro and NetFRAME
- *
- * Rev 1.0 21 Mar 1990 10:48:46 Walter A. Wallach
- * Initial revision.
- *
- */
- #include "procdefs.h"
- #include "ecb.h"
- #include "loader.h"
- #include "lanconf.h"
- #include "random.h"
- #define MAX_DEVICES 16
- #define MAX_SENDS_PER_DEVICE 32
- #define DEVICES_PER_PAGE 10
- #define NX_PRIORITY 50
- #define NX_SIGNATURE "NX TEST PACKET"
-
- #define STACK_SIZE 2048*16
- #define _UNUSED(x) if (0) if (x)
-
- extern LONG NumberOfPollingLoops, MaximumNumberOfPollingLoops;
-
- LONG NXUpdateInterval;
- ScreenStruct *nXerciseScreen;
- int DeviceCount = 0;
- BYTE *stack; /* NX Monitor Stack */
- LONG stackSize;
- BYTE *NXStack = NULL; /* NX Exerciser Stack */
- LONG NXActualStackSize;
- LONG nXerciseModuleHandle;
- LONG ServerProcessPriority = 50;
- LONG NXMonitorProcessID = 0;
- LONG NXerciseProcessID = 0;
- LONG NXChunksPerIO;
- LONG NXMaxSendsPerDevice;
- LONG NXSleeping = 0;
- LONG NXWakeRequested = 0;
- char NXMonitorStatus = 'I'; /* Possible Status I=Initializing R=Running P=Pending Stop S=Stopped */
- eventcontrolblock *ECBList = NULL;
- struct DeviceData
- {
- int OutstandingIOs;
- int Index;
- int BoardNumber;
- int RecieverRegistered;
- LONG Random;
- BYTE ActivityType; /* 'T' = Transmit 'R' = Recieve 'B' = Both */
- BYTE Name[80];
- } Device[MAX_DEVICES];
-
- /* NOTE: In order to prevent overflow of certain performance counters, byte
- counts are maintained in units of 64 bytes (1 * 2^6) called "Chunks".
- To convert Chunks to Kilobytes divide by 16.
- */
- #define CHUNK_SIZE 64
- #define CHUNK_TO_KB 16
- #define MAX_PACKET_CHUNKS ( 1500 / CHUNK_SIZE )
- struct PerformanceData
- {
- LONG TotalReceivesCompleted;
- LONG TotalChunksReceived;
- LONG CurrentReceivesCompleted;
- LONG CurrentChunksReceived;
- LONG TotalSendsCompleted;
- LONG TotalChunksSent;
- LONG CurrentSendsCompleted;
- LONG CurrentChunksSent;
- } Performance[MAX_DEVICES];
-
- struct PerformanceData Aggregate;
- int AggregateOutstandingIOs = 0;
-
- int BoardToDeviceIndex[MAX_DEVICES];
-
- BYTE CommonBuffer[2000];
- /* debug */
- eventcontrolblock *SendECB[MAX_DEVICES*32];
- LONG SendECBCount= 0;
- /* debug */
-
- void
- NXSendCompletion( eventcontrolblock *currentECB );
-
- LONG
- NXReceiveCompletion( eventcontrolblock *currentECB );
-
- void
- MakeDeviceDescription( LONG BoardNumber, BYTE *buffer);
-
- void
- NXercise();
-
- void
- NXMonitor();
-
- /* LSL Interface routines */
- LONG CLSLRegisterPreScanStack( int BoardNumber,
- int HandlerProcedure(),
- int ControlProcedure() );
-
- LONG CLSLDeRegisterPreScanStack( int BoardNumber );
-
- void *CLSLGetECB();
-
- void CLSLReturnECB( void *ECB );
-
- extern NXReceiveDone();
- extern NXSendDone();
- extern NXControl();
-
- LONG
- StartProcedure(
- LONG moduleHandle,
- ScreenStruct *initializationErrorScreen,
- BYTE *commandLine,
- BYTE *loadDirectoryPath,
- LONG unitializedDataLength,
- LONG fileHandle,
- LONG (*ReadRoutine)(LONG handle, LONG offset, BYTE *buffer, LONG length),
- LONG customDataOffset,
- LONG customDataSize)
- {
- static BYTE nXerciseScreenName[] = "NX Screen";
- int i;
- BYTE *Token;
- _UNUSED(commandLine);
- _UNUSED(loadDirectoryPath);
- _UNUSED(unitializedDataLength);
- _UNUSED(fileHandle);
- _UNUSED(ReadRoutine);
- _UNUSED(customDataOffset);
- _UNUSED(customDataSize);
-
- for (Token = commandLine; *Token != '\000'; Token++)
- {
- if (*Token == 'D') EnterDebugger();
- }
-
- for ( i = 0; i < MAX_DEVICES; i++ ) BoardToDeviceIndex[i] = -1;
-
- CSetB( 0, CommonBuffer, sizeof( CommonBuffer ) );
- CStrCpy( CommonBuffer, NX_SIGNATURE );
-
- stack = GetNonMovableMemory(STACK_SIZE, &stackSize);
- if (stack == NULL)
- {
- OutputToScreen(initializationErrorScreen,
- "NX: Unable to get memory for stack\r\n");
- goto Error0;
- }
-
- nXerciseModuleHandle = moduleHandle;
- if (OpenScreen(nXerciseScreenName, &nXerciseScreen) != 0)
- {
- OutputToScreen(initializationErrorScreen,
- "NX: Unable to open NX screen\r\n");
- goto Error1;
- }
-
- /* The variable stackSize contains the amount of memory actually
- allocated for the stack, so use it instead of STACK_SIZE.*/
-
- /* this should be the last thing we do */
- NXMonitorProcessID = CCreateProcess(NX_PRIORITY, NXMonitor,
- stack + stackSize, stackSize, "NXMon");
- while ( NXMonitorStatus == 'I') CRescheduleLast();
- switch ( NXMonitorStatus)
- {
- case 'R':
- break;
- case 'S':
- default:
- OutputToScreen( systemConsoleScreen,
- "Failed to start NX monitor process\r\n" );
- goto Error3;
- }
- return (0);
-
- /* Error Recovery */
- Error3:
- CloseScreen(nXerciseScreen);
- Error1:
- ReturnNonMovableMemory(stack);
- Error0:
- return (-1);
- }
-
- void ExitProcedure(void)
- {
- int i;
- eventcontrolblock *ECBp;
-
- if ( NXMonitorProcessID != 0 ) CDestroyProcess( NXMonitorProcessID );
-
- if ( NXMonitorStatus != 'S' ) /* if not already stopped - stop */
- {
- NXMonitorStatus = 'S';
- while ( AggregateOutstandingIOs != 0 ) CRescheduleLast();
- if ( NXerciseProcessID != 0 ) CDestroyProcess( NXerciseProcessID );
- }
-
- CloseScreen( nXerciseScreen );
-
- for (i=0; i < DeviceCount; i++)
- {
- if ( Device[i].RecieverRegistered )
- {
- CLSLDeRegisterPreScanStack (Device[i].BoardNumber);
- }
- while ( ECBList != NULL )
- {
- ECBp = ECBList;
- ECBList = ECBp->RLink;
- /* debug */ if ( (LONG)ECBList == 0xFFFFFFFF ) EnterDebugger();
- /* Return the ECB to the OS */
- CLSLReturnECB( ECBp );
- }
- }
- if ( NXStack != NULL ) ReturnNonMovableMemory( NXStack );
- ReturnNonMovableMemory( stack );
-
- }
-
- void NXExit(void)
- {
- KillMe((struct LoadDefinitionStructure *)nXerciseModuleHandle);
-
- /* Sleep forever until the exit procedure kills this process */
- for (;;)
- CSleepUntilInterrupt();
- }
-
- void
- NXMonitor()
- {
- long int LStatus;
- int DeviceIndex;
- LONG MaxPage;
- LONG CurrentPage;
- LONG FirstDevice;
- LONG LastDevice;
- LONG StartTime;
- LONG IntervalStartTime;
- LONG ElapsedSeconds;
- LONG IntervalSeconds;
- LONG Tenths;
- LONG utilization;
- LONG BytesPerIO;
- LONG DeviceID;
- LONG UpdateTicks;
- eventcontrolblock *ECBp;
- int i;
- LONG chunks;
- LONG packets;
- BYTE Answer;
- BYTE Dummy;
- BYTE buffer[200];
-
- RandomNumberCount = sizeof( RandomNumber ) / 4;
- /* Activate our screen */
- Enable();
- ActivateScreen(nXerciseScreen);
-
- /* Tell NXLoad we are Running */
- NXMonitorStatus = 'R';
-
- /* Ask for packet size */
- InputFromScreen( nXerciseScreen,
- "RF",
- 2,
- 2,
- buffer,
- 0L,
- TRUE,
- "F",
- "Packet Length Type [F=Fixed R=Random]? " );
- if ( buffer[0] == 'F' || buffer[0] == 'f' )
- {
- PromptForUnsignedNumber( nXerciseScreen,
- &BytesPerIO,
- CHUNK_SIZE,
- MAX_PACKET_CHUNKS * CHUNK_SIZE,
- 10L,
- 0L,
- TRUE,
- 64L,
- "Bytes per packet [%d:%d]? ",
- CHUNK_SIZE,
- MAX_PACKET_CHUNKS * CHUNK_SIZE );
- NXChunksPerIO = ( BytesPerIO + ( CHUNK_SIZE / 2 )) / CHUNK_SIZE;
- if ( ( NXChunksPerIO * CHUNK_SIZE ) != BytesPerIO )
- {
- OutputToScreen( nXerciseScreen,
- "Closest packet size avaiable %d selected\n\r",
- NXChunksPerIO * 64 );
- }
- }
- else
- {
- NXChunksPerIO = 0;
- }
-
- /* Ask for queue depth */
- PromptForUnsignedNumber( nXerciseScreen,
- &NXMaxSendsPerDevice,
- 1L,
- MAX_SENDS_PER_DEVICE,
- 10L,
- 0L,
- TRUE,
- 3L,
- "Number of concurrent sends to queue per device [1-%d]? ",
- MAX_SENDS_PER_DEVICE);
-
- /* Ask for update interval */
- PromptForUnsignedNumber( nXerciseScreen,
- &NXUpdateInterval,
- 1L,
- 60L,
- 10L,
- 0L,
- TRUE,
- 5L,
- "Screen update interval in seconds [1-60]? ");
- ConvertSecondsToTicks( NXUpdateInterval, 0L, &UpdateTicks );
-
- /* Ask for selections or go */
- DeviceCount = 0;
- for (DeviceID = 0; DeviceID < MAX_DEVICES; DeviceID++)
- {
- /* test for presence of device */
- if ( MLIDLoadedHandleTable[DeviceID] == 0 ) continue;
-
- MakeDeviceDescription( DeviceID, Device[DeviceCount].Name);
- LStatus = PromptForYesOrNo( nXerciseScreen,
- 0L,
- TRUE,
- "\r\nExercise %s ?",
- Device[DeviceCount].Name );
- if ( LStatus )
- {
- /* Build map to map board number to device array index */
- BoardToDeviceIndex[DeviceID] = DeviceCount;
-
- InputFromScreen( nXerciseScreen,
- "TRB",
- 2,
- 2,
- buffer,
- 0L,
- TRUE,
- "B",
- "Device Activity [T=Transmit R=Recieve B=Both]? " );
-
- Device[DeviceCount].Index = DeviceCount;
- Device[DeviceCount].BoardNumber = DeviceID;
- Device[DeviceCount].ActivityType = buffer[0];
- Device[DeviceCount].Random = 0;
- Device[DeviceCount].OutstandingIOs = 0;
- Device[DeviceCount].RecieverRegistered = 0;
-
- if ( Device[DeviceCount].ActivityType != 'T' ) /* Recieving ? */
- {
- /* Register stack */
- if ( CLSLRegisterPreScanStack( DeviceID, NXReceiveDone, NXControl ) == 0 )
- {
- Device[DeviceCount].RecieverRegistered = 1;
- }
- else
- {
- OutputToScreen( nXerciseScreen, "NX Could not register PreScan reciever for device\r\n");
- }
- }
- if ( Device[DeviceCount].ActivityType != 'R' ) /* Transmitting? */
- {
- for ( i = 0; i < NXMaxSendsPerDevice; i++ )
- {
- /* Get an ECB for sending from the OS */
- while ( ( ECBp = CLSLGetECB() ) == NULL )
- {
- /*
- OutputToScreen( nXerciseScreen, "NX Could not get a send ECB - trying again\r\n");
- */
- Delay ( 5 );
- }
-
- /* debug */
- SendECB[SendECBCount] = ECBp;
- SendECBCount++;
- /* debug */
- /* Link the ECB into the available queue for the device*/
- ECBp->RLink = ECBList;
- ECBList = ECBp;
- /* debug */ if ( (LONG)ECBList == 0xFFFFFFFF ) EnterDebugger();
- /* Setup the send ECB */
- ECBp->RESRAddress = (LONG)&NXSendDone;
- ECBp->RLogicalID = 0;
- ECBp->RImmediateAddress[0] = 0xff;
- ECBp->RImmediateAddress[1] = 0xff;
- ECBp->RImmediateAddress[2] = 0xff;
- ECBp->RImmediateAddress[3] = 0xff;
- ECBp->RImmediateAddress[4] = 0xff;
- ECBp->RImmediateAddress[5] = 0xff;
- ECBp->RSocket = 0;
- ECBp->RPacketLength = 0;
- ECBp->RFragmentCount = 1;
- ECBp->RPacketOffset = (LONG)CommonBuffer;
- ECBp->RPacketSize = 0;
- }
- }
- /* Clear performance information */
- Performance[DeviceCount].TotalReceivesCompleted = 0;
- Performance[DeviceCount].TotalChunksReceived = 0;
- Performance[DeviceCount].CurrentReceivesCompleted = 0;
- Performance[DeviceCount].CurrentChunksReceived = 0;
- Performance[DeviceCount].TotalSendsCompleted = 0;
- Performance[DeviceCount].TotalChunksSent = 0;
- Performance[DeviceCount].CurrentSendsCompleted = 0;
- Performance[DeviceCount].CurrentChunksSent = 0;
-
- DeviceCount++;
- }
- }
- /* Zero aggregate preformance numbers */
-
- Aggregate.TotalReceivesCompleted = 0;
- Aggregate.TotalChunksReceived = 0;
- Aggregate.CurrentReceivesCompleted = 0;
- Aggregate.CurrentChunksReceived = 0;
- Aggregate.TotalSendsCompleted = 0;
- Aggregate.TotalChunksSent = 0;
- Aggregate.CurrentSendsCompleted = 0;
- Aggregate.CurrentChunksSent = 0;
- AggregateOutstandingIOs = 0;
-
- /* Make sure at least one Device is selected */
-
- if ( DeviceCount < 1 )
- {
- OutputToScreen( nXerciseScreen,
- "No Devices selected\r\n" );
- Delay( 91 );
- NXExit();
- }
-
- /* Start NXercise */
- NXStack = GetNonMovableMemory( STACK_SIZE,
- &NXActualStackSize );
- if ( NXStack == NULL)
- {
- OutputToScreen ( nXerciseScreen,
- "Insufficient memory to start NX subprocess\r\n");
- Delay( 91 );
- NXExit();
- }
- NXerciseProcessID = CCreateProcess( NX_PRIORITY - 1,
- NXercise,
- NXStack + NXActualStackSize,
- NXActualStackSize,
- "NXerci");
- /* Compute pages of displays */
- MaxPage = ( DeviceCount / DEVICES_PER_PAGE ) + 1;
- CurrentPage = 1;
- /* Clear the Screen and setup the title */
- ClearScreen( nXerciseScreen );
- PositionOutputCursor( nXerciseScreen, 0, 0 );
- OutputToScreen( nXerciseScreen,
- "NetFRAME Network Test with %d Sends queued per device Page %d of %d",
- NXMaxSendsPerDevice,
- CurrentPage,
- MaxPage );
-
- /* Note the starting time for later computations */
- StartTime = CurrentTime;
-
- while (1)
- {
- /* Sleep for update interval */
- IntervalStartTime = CurrentTime;
- Delay( UpdateTicks );
- /* Test for keyboard key */
- if ( CheckKeyStatus( nXerciseScreen ) )
- {
- /* Get the key and process it */
- GetKey( nXerciseScreen, &Dummy, &Answer, &Dummy, &Dummy, 0L );
- if ( Answer == 'Q' || Answer =='q' )
- {
- PositionOutputCursor( nXerciseScreen, 24, 0 );
- LStatus = PromptForYesOrNo( nXerciseScreen,
- 0L,
- TRUE,
- "Exit Network Exerciser? " );
- if ( LStatus )
- {
- NXMonitorStatus = 'P';
- }
- }
- else
- {
- if ( Answer > '0' && Answer <= '9' )
- {
- i = Answer - '0';
- if ( i <= MaxPage )
- {
- CurrentPage = i;
- ClearScreen( nXerciseScreen );
- PositionOutputCursor( nXerciseScreen, 0, 0 );
- OutputToScreen( nXerciseScreen,
- "NetFRAME Network Test with %d Sends queued per device Page %d of %d",
- NXMaxSendsPerDevice,
- CurrentPage,
- MaxPage );
- }
- else RingTheBell();
- }
- else RingTheBell();
- }
- }
- /* Test for requested stop */
- if ( NXMonitorStatus == 'P' )
- {
- while ( AggregateOutstandingIOs != 0 ) CRescheduleLast();
- if ( NXerciseProcessID != 0 )
- {
- CDestroyProcess( NXerciseProcessID );
- NXerciseProcessID = 0;
- }
- NXMonitorStatus = 'S'; /* Say we are stopped */
- ReturnNonMovableMemory( NXStack );
- NXStack = NULL;
- NXExit();
- }
- /* Compute and display the numbers */
- ConvertTicksToSeconds( ( CurrentTime - StartTime ),
- &ElapsedSeconds,
- &Tenths );
- ConvertTicksToSeconds( ( CurrentTime - IntervalStartTime ),
- &IntervalSeconds,
- &Tenths );
- /* Update cumulative statistics */
- for ( DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++ )
- {
- chunks = Performance[DeviceIndex].CurrentChunksSent;
- Performance[DeviceIndex].TotalChunksSent += chunks;
- Aggregate.CurrentChunksSent += chunks;
- packets = Performance[DeviceIndex].CurrentSendsCompleted;
- Performance[DeviceIndex].TotalSendsCompleted += packets;
- Aggregate.CurrentSendsCompleted += packets;
- chunks = Performance[DeviceIndex].CurrentChunksReceived;
- Performance[DeviceIndex].TotalChunksReceived += chunks;
- Aggregate.CurrentChunksReceived += chunks;
- packets = Performance[DeviceIndex].CurrentReceivesCompleted;
- Performance[DeviceIndex].TotalReceivesCompleted += packets;
- Aggregate.CurrentReceivesCompleted += packets;
- }
- /* Now roll up the aggregate totals */
- Aggregate.TotalChunksSent += Aggregate.CurrentChunksSent;
- Aggregate.TotalChunksReceived += Aggregate.CurrentChunksReceived;
- Aggregate.TotalSendsCompleted += Aggregate.CurrentSendsCompleted;
- Aggregate.TotalReceivesCompleted += Aggregate.CurrentReceivesCompleted;
-
- PositionOutputCursor( nXerciseScreen, 1, 0 );
- OutputToScreen( nXerciseScreen, "%s\r\n%s\n\r",
- " Device Cur. Send Cur. Recv. Ave. Send Ave. Recv.",
- " Name KB/s Pkt/s KB/s Pkt/s KB/s Pkt/s KB/s Pkt/s" );
- /* 99999 99999 99999 99999 99999 99999 99999 99999 */
- FirstDevice = ( CurrentPage - 1 ) * DEVICES_PER_PAGE;
- /* note - LastDevice is really last Device index (0 based) plus 1) */
- if ( CurrentPage == MaxPage )
- {
- LastDevice = DeviceCount;
- }
- else
- {
- LastDevice = CurrentPage * DEVICES_PER_PAGE;
- }
- for ( DeviceIndex = FirstDevice; DeviceIndex < LastDevice; DeviceIndex++ )
- {
- OutputToScreen( nXerciseScreen, "%-20.20s ", Device[DeviceIndex].Name );
- OutputToScreen( nXerciseScreen, "%5d %5d %5d %5d %5d %5d %5d %5d\r\n",
- ( Performance[DeviceIndex].CurrentChunksSent / CHUNK_TO_KB ) / IntervalSeconds,
- ( Performance[DeviceIndex].CurrentSendsCompleted ) / IntervalSeconds,
- ( Performance[DeviceIndex].CurrentChunksReceived / CHUNK_TO_KB ) / IntervalSeconds,
- ( Performance[DeviceIndex].CurrentReceivesCompleted ) / IntervalSeconds,
- ( Performance[DeviceIndex].TotalChunksSent / CHUNK_TO_KB ) / ElapsedSeconds,
- ( Performance[DeviceIndex].TotalSendsCompleted ) / ElapsedSeconds,
- ( Performance[DeviceIndex].TotalChunksReceived / CHUNK_TO_KB ) / ElapsedSeconds,
- ( Performance[DeviceIndex].TotalReceivesCompleted ) / ElapsedSeconds);
- }
-
- /* Aggregate numbers */
- OutputToScreen( nXerciseScreen, "\r\n" );
- OutputToScreen( nXerciseScreen, "%-20.20s "," All Devices" );
- OutputToScreen( nXerciseScreen, "%5d %5d %5d %5d %5d %5d %5d %5d\r\n",
- ( Aggregate.CurrentChunksSent / CHUNK_TO_KB ) / IntervalSeconds,
- ( Aggregate.CurrentSendsCompleted ) / IntervalSeconds,
- ( Aggregate.CurrentChunksReceived / CHUNK_TO_KB ) / IntervalSeconds,
- ( Aggregate.CurrentReceivesCompleted ) / IntervalSeconds,
- ( Aggregate.TotalChunksSent / CHUNK_TO_KB ) / ElapsedSeconds,
- ( Aggregate.TotalSendsCompleted ) / ElapsedSeconds,
- ( Aggregate.TotalChunksReceived / CHUNK_TO_KB ) / ElapsedSeconds,
- ( Aggregate.TotalReceivesCompleted ) / ElapsedSeconds);
- OutputToScreen( nXerciseScreen, "\r\n" );
-
- /* Utilization */
- utilization = 100 - ((NumberOfPollingLoops * 100 +
- (MaximumNumberOfPollingLoops >> 1)) / MaximumNumberOfPollingLoops);
- OutputToScreen( nXerciseScreen, "Server utilization %6d%%\r\n", utilization);
-
- /* Instructions */
- OutputToScreen( nXerciseScreen, "Q to quit or page number to view\n\r" );
-
- /* Zero current counts */
- for ( DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++ )
- {
- Performance[DeviceIndex].CurrentReceivesCompleted = 0;
- Performance[DeviceIndex].CurrentChunksReceived = 0;
- Performance[DeviceIndex].CurrentSendsCompleted = 0;
- Performance[DeviceIndex].CurrentChunksSent = 0;
- }
- Aggregate.CurrentReceivesCompleted = 0;
- Aggregate.CurrentChunksReceived = 0;
- Aggregate.CurrentSendsCompleted = 0;
- Aggregate.CurrentChunksSent = 0;
-
- }
- }
-
- void
- NXercise()
- {
- int Length;
- LONG LStatus;
- int CurrentDevice = 0;
-
- LONG SendCount = 0;
- LONG BackToBackSends = 0;
- register eventcontrolblock *ECBp;
- register struct DeviceData *DeviceP;
- struct DeviceData *LastDeviceP;
- struct DeviceData *WrapDeviceP;
-
- DeviceP = &Device[0];
- WrapDeviceP = &Device[DeviceCount];
- LastDeviceP = &Device[0];
-
- while (1)
- {
- if ( NXMonitorStatus != 'R' ) /* If not running go to sleep forever */
- /* and wait to be destroyed */
- {
- while (1) CSleepUntilInterrupt();
- }
-
- if ( DeviceP->ActivityType != 'R' ) /* if T or B */
- {
- if ( DeviceP->OutstandingIOs < NXMaxSendsPerDevice )
- {
- BackToBackSends++;
- SendCount++;
-
- /* Start another IO */
- if ( NXChunksPerIO == 0 )
- {
- /* Random Length Packets */
-
- Length = ( ( RandomNumber[DeviceP->Random] % ( MAX_PACKET_CHUNKS - 1 ) ) + 1 ) * CHUNK_SIZE ;
- DeviceP->Random++;
- if ( DeviceP->Random == RandomNumberCount )
- DeviceP->Random = 0;
- }
- else
- {
- Length = NXChunksPerIO * CHUNK_SIZE;
- }
-
- /* Build a physical I/O request */
- ECBp = ECBList;
- ECBList = ECBp->RLink;
- /* debug */ if ( (LONG)ECBList == 0xFFFFFFFF ) EnterDebugger();
- /* debug */
- {
- int BAD, i;
- BAD = -1;
- for ( i = 0; i < SendECBCount; i++ )
- {
- if ( SendECB[i] == ECBp )
- {
- BAD = 0;
- break;
- }
- }
- if ( BAD ) EnterDebugger();
- BAD = -1;
- if ( ECBList != NULL )
- {
- for ( i = 0; i < SendECBCount; i++ )
- {
- if ( SendECB[i] == ECBList )
- {
- BAD = 0;
- break;
- }
- }
- if ( BAD ) EnterDebugger();
- }
- };
- /* debug */
- ECBp->RPacketLength = Length;
- ECBp->RPacketSize = Length;
- ECBp->RFragmentCount = 1;
- ECBp->RBoardNumber = DeviceP->BoardNumber;
- ECBp->RESRBXValue = DeviceP->Index;
- DeviceP->OutstandingIOs++;
- AggregateOutstandingIOs++;
- /* Send the ECB */
- LStatus = CLSLSendPacket( ECBp );
- if ( LStatus != 0 )
- {
- OutputToScreen( nXerciseScreen, "Send failed - Status 0x%x" );
- DeviceP->OutstandingIOs--;
- AggregateOutstandingIOs--;
- }
- }
- }
- /* Look at the next device */
- DeviceP++;
- if ( DeviceP == WrapDeviceP ) /* Have all devices been tried */
- {
- DeviceP = &Device[0]; /* Wrap the device pointer */
- if ( SendCount == 0 ) /* Was anything send on this pass? */
- {
- Disable(); /* No, Nothing could be sent */
- NXSleeping = -1; /* Going to sleep */
- CSleepUntilInterrupt();
- NXSleeping = 0; /* Now awake */
- NXWakeRequested = 0;
- Enable();
- BackToBackSends = 0; /* Note we have taken a break */
- }
- else
- { /* Yes, Something was sent - keep going */
- SendCount = 0;
- }
- }
- if ( BackToBackSends == 20 ) /* Do we need to take a break? */
- {
- CRescheduleLast(); /* Give someone else a chance */
- BackToBackSends = 0; /* Note we have taken a break */
- }
- }
- }
-
- void
- NXSendCompletion( eventcontrolblock *currentECB )
- {
- int i;
- int chunks;
- register eventcontrolblock *ECBp;
-
- /* debug */
- int BAD = -1;
- for ( i = 0; i < SendECBCount; i++ )
- {
- if ( SendECB[i] == currentECB )
- {
- BAD = 0;
- break;
- }
- }
- if ( BAD ) EnterDebugger();
- /* debug */
-
- i = currentECB->RESRBXValue;
- chunks = ( currentECB->RPacketLength ) / CHUNK_SIZE;
- /* Update individual device counts */
- Performance[i].CurrentSendsCompleted++;
- Performance[i].CurrentChunksSent += chunks;
-
- /* Put the request back on the send queue for the device */
- --AggregateOutstandingIOs;
- --Device[i].OutstandingIOs;
- ECBp = ECBList;
- ECBList = currentECB;
- /* debug */ if ( (LONG)ECBList == 0xFFFFFFFF ) EnterDebugger();
- currentECB->RLink = ECBp;
- if ( NXSleeping && (!NXWakeRequested) )
- {
- NXWakeRequested = -1;
- CRescheduleFromInterrupt(NXerciseProcessID);
- }
- }
-
- LONG
- NXReceiveCompletion( eventcontrolblock *currentECB )
- {
- int i;
- int chunks;
- /* the board number to device index should be computed here */
- i = BoardToDeviceIndex[currentECB->RBoardNumber];
- if ( i != -1 ) /* Do we know about this board? */
- {
- chunks = ( currentECB->RPacketLength ) / CHUNK_SIZE;
-
- /* Update individual device counts */
- Performance[i].CurrentReceivesCompleted++;
- Performance[i].CurrentChunksReceived += chunks;
-
- /* Now return the receive ECB back to the pool if it's a NX packet */
- if ( CStrCmp( (void *)currentECB->RPacketOffset, NX_SIGNATURE ) == 0 )
- {
- CLSLReturnECB( (void *)currentECB );
- return ( 0 ); /* Don't try to route the packet */
- }
- }
- return ( 1 ); /* Attempt to route the packet to a protocol stack */
- };
-
- void
- MakeDeviceDescription(
- LONG boardNumber,
- BYTE *buffer)
- {
- struct DriverConfigurationStructure *lanInfo;
- BYTE *ptr;
- lanInfo = MLIDConfigurationTable[boardNumber];
- ptr = buffer;
- /* LAN name */
- sprintf(ptr, "%S", MLIDLoadedHandleTable[boardNumber]->LDFileName);
- while (*ptr != '.' && *ptr != 0) ptr++;
- *ptr++ = ' ';
-
- *ptr++ = '[';
-
- if (PS2Flag)
- {
- /* slot */
- sprintf(ptr, "slot=%x ", lanInfo->DSlot);
- ptr = ptr + CStrLen(ptr);
- }
- else
- {
- /* IO ports */
- if (lanInfo->DIOPortsAndRanges[1] > 0) /* using IO port 0 */
- {
- sprintf(ptr, "port=%x ", lanInfo->DIOPortsAndRanges[0]);
- ptr = ptr + CStrLen(ptr);
- }
- if (lanInfo->DIOPortsAndRanges[3] > 0) /* using IO port 1 */
- {
- sprintf(ptr, "port=%x ", lanInfo->DIOPortsAndRanges[2]);
- ptr = ptr + CStrLen(ptr);
- }
-
- /* memory addresses */
- if (lanInfo->DMemoryDecodeAndLength[0].LANMemoryAddress > 0) /* using memory 0 */
- {
- sprintf(ptr, "mem=%x ",
- lanInfo->DMemoryDecodeAndLength[0].LANMemoryAddress);
- ptr = ptr + CStrLen(ptr);
- if (lanInfo->DMemoryDecodeAndLength[1].LANMemoryAddress > 0) /* using memory 1 */
- {
- sprintf(ptr, "mem=%x ", lanInfo->DMemoryDecodeAndLength[1].LANMemoryAddress);
- ptr = ptr + CStrLen(ptr);
- }
- }
-
- /* interrupts */
- if (lanInfo->DIntLine[0] != 0xff) /* first interrupt */
- {
- sprintf(ptr, "int=%x ", lanInfo->DIntLine[0]);
- ptr = ptr + CStrLen(ptr);
- if (lanInfo->DIntLine[1] != 0xff) /* second interrupt */
- {
- sprintf(ptr, "int=%x ", lanInfo->DIntLine[1]);
- ptr = ptr + CStrLen(ptr);
- }
- }
-
- /* DMA channels */
- if (lanInfo->DDMALine[0] != 0xff) /* first DMA */
- {
- sprintf(ptr, "dma=%x ", lanInfo->DDMALine[0]);
- ptr = ptr + CStrLen(ptr);
- if (lanInfo->DDMALine[1] != 0xff) /* second DMA */
- {
- sprintf(ptr, "dma=%x ", lanInfo->DDMALine[1]);
- ptr = ptr + CStrLen(ptr);
- }
- }
- }
- *(ptr - 1) = ']';
- }
-