program EthSpd;

uses
  Crt,
  NumToStr,
  CoBase,
  CoEthDef,
  CoEth01;


const

{$IFDEF VERMC}
  IoBase        = $2300;
{$ENDIF}
{$IFDEF VERPC}
  IoBase        = $300;
{$ENDIF}

  MaxBuffSize   = 128;

type

  TTestProcedure = function ( ADev: PCoDevice ): Boolean;



  procedure RunTest( AIoBase: Word; ATestProc: TTestProcedure );
  var
    Status    : TCoStatus;
    Dev       : PCoDevice;
    StartTime : TCoTime;
    StopTime  : TCoTime;
  begin
    Status := CoCreateDevice( 'ETH01', '', '', nil, Dev );

    if Status = CST_SUCCESS then
    begin

      Status := Dev^.CoSetOption( DEV_CLASS_NIC, COPT_ETH01_IOBASE,
                  @AIoBase, SizeOf( AIoBase ), 0, nil );

      if Status = CST_SUCCESS then
      begin

        Status := Dev^.CoBind( nil, 0, nil );

        if Status = CST_SUCCESS then
        begin
          StartTime := CoGetTime;

          WriteLn( 'Test running...' );

          if Assigned( ATestProc ) then ATestProc( Dev );

          StopTime  := CoGetTime;

          Write( 'Test stopped after ' );

          WriteLn( CoTimeDistMs(StopTime,  StartTime), 'ms' );

          Status := Dev^.CoUnbind( 0, nil );

          if Status <> CST_SUCCESS then
          begin
            WriteLn( 'CoUnbind() failed: ', Dev^.CoStatusToStr( Status ) );
          end;

          CoReleaseDevicePtr( Dev );
        end
        else begin
          WriteLn( 'CoBind() failed: ', Dev^.CoStatusToStr( Status ) );
          CoReleaseDevicePtr( Dev );
        end;

      end
      else begin
        WriteLn( 'CoSetOption() [IOBASE] failed: ',
          Dev^.CoStatusToStr( Status ) );
        CoReleaseDevicePtr( Dev );
      end;

    end
    else begin
      WriteLn( 'CoCreateDevice() failed: ', CoStatusToStr( Status ) );
    end;

  end;



  function  SendTestProc( ADev: PCoDevice ): Boolean; far;
  const
    Address : TEthAddress =
      ( Size     : SizeOf( TEthAddress );
        Mac      : (Bytes: ( $12, $34, $56, $78, $89, $AB ) ); { jakakoli blbost }
        Format   : ETH_FORMAT_ETHII;
        Protocol : $CDEF
      );


    MaxPasses = 1024;

  var
    Buffer  : array[0..MaxBuffSize - 1] of Byte;
    Status  : TCoStatus;
    Cnt     : Word;
  begin
    WriteLn( 'Sending ', MaxPasses, ' x ', MaxBuffSize, ' bytes');


    for Cnt := 1 to MaxPasses do
    begin

      Status := ADev^.CoSendBufferTo( @Buffer, SizeOf( Buffer ), 0,
                                      @Address, nil );


      if Status <> CST_SUCCESS then
      begin
        WriteLn( 'CoSendBufferTo() failed: ', ADev^.CoStatusToStr( Status ) );
        Exit;
      end;

    end;

  end;



  function  SendTestProcOvlp( ADev: PCoDevice ): Boolean; far;
  const
    Address : TEthAddress =
      ( Size     : SizeOf( TEthAddress );
        Mac      : (Bytes: ( $12, $34, $56, $78, $89, $AB ) ); { jakakoli blbost }
        Format   : ETH_FORMAT_ETHII;
        Protocol : $CDEF
      );


    MaxPasses = 1024;

  var
    Buffer  : array[0..MaxBuffSize - 1] of Byte;
    Status  : TCoStatus;
    Cnt     : Word;

    Ovlp1   : TOverlapped;
    Ovlp2   : TOverlapped;
    Ovlp3   : TOverlapped;
  begin
    WriteLn( 'Sending 2 x', MaxPasses, ' x ', MaxBuffSize, ' bytes -- Overlapped');


    FillChar( Ovlp1, SizeOf( Ovlp1 ), 0 );
    FillChar( Ovlp2, SizeOf( Ovlp2 ), 0 );
    FillChar( Ovlp3, SizeOf( Ovlp2 ), 0 );

    for Cnt := 1 to MaxPasses do
    begin


      Status := ADev^.CoGetIOResult( @Ovlp3, COF_WAIT );


      Status := ADev^.CoSendBufferTo( @Buffer, SizeOf( Buffer ), 0,
                                      @Address, @Ovlp3 );



      Status := ADev^.CoSendBufferTo( @Buffer, SizeOf( Buffer ), 0,
                                      @Address, @Ovlp1 );


      Status := ADev^.CoGetIOResult( @Ovlp2, COF_WAIT );

      if Status <> CST_SUCCESS then
      begin
        WriteLn( 'CoSendBufferTo() failed: ', ADev^.CoStatusToStr( Status ) );
        Exit;
      end;


      Status := ADev^.CoSendBufferTo( @Buffer, SizeOf( Buffer ), 0,
                                      @Address, @Ovlp2 );


      Status := ADev^.CoGetIOResult( @Ovlp1, COF_WAIT );

      if Status <> CST_SUCCESS then
      begin
        WriteLn( 'CoSendBufferTo() failed: ', ADev^.CoStatusToStr( Status ) );
        Exit;
      end;



    end;

  end;


var

  OldExitProc : Pointer;

  procedure MyExitProc; far;
  begin
    if ExitCode <> 0 then
    begin
      WriteLn( 'ExitCode: ', ExitCode, ' Address: ', PtrToStr( ErrorAddr ) );
      repeat until False;
    end;
    ExitProc := OldExitProc;
  end;


begin

  OldExitProc := ExitProc;
  ExitProc := @MyExitProc;

  RunTest( IoBase, SendTestProcOvlp );

  repeat until False;
end.