uses
  Crt;

const

  regBSR      = $0E; { Bank select register                      R/W (2B) }

  { Register bank 0 }

  regTCR      = $00; { Transmition control register              R/W (2B) }
  regEPHSR    = $02; { EPH status register                       R/O (2B) }
  regRCR      = $04; { Receive control register                  R/W (2B) }
  regECR      = $06; { Counter register                          R/O (2B) }
  regMIR      = $08; { Memory information register               R/O (2B) }
  regMCR      = $0A; { Memory Configuration register   +0 R/W +1 R/O (2B) }

  { Register bank 1 }

  regCR       = $00; { Configuration register                    R/W (2B) }
  regBAR      = $02; { Base address register                     R/W (2B) }
  regIAR      = $04; { Individual address register               R/W (6B) }
  regGPR      = $0A; { General address register                  R/W (2B) }
  regCTR      = $0C; { Control register                          R/W (2B) }

  { Register bank 2 }

  regMMUCR    = $00; { MMU command register                      W/O (1B) }
  regAUTOTX   = $01; { AUTO TX start register                    R/W (1B) }
  regPNR      = $02; { Packet number register                    R/W (1B) }
  regARR      = $03; { Allocation result register                R/O (1B) }
  regFIFO     = $04; { FIFO ports register                       R/O (2B) }
  regPTR      = $06; { Pointer register                          R/W (2B) }
  regDATA     = $08; { Data register                             R/W (4B) }
  regIST      = $0C; { Interrupt status register                 R/O (1B) }
  regACK      = $0C; { Interrupt acknowledge register            W/O (1B) }
  regMSK      = $0D; { Interrupt mask register                   R/W (1B) }

  { register bank 3 }

  regMT       = $00; { Multicast table                           R/W (8B) }
  regMGMT     = $08; { Management interface                      R/W (2B) }
  regREV      = $0A; { Revision register                         R/W (2B) }
  regERCV     = $0C; { Early RCV register                        R/W (2B) }


  { bity status hodnoty prijmuteho paketu }

  bitTOOSHORT    = $0400;
  bitTOOLNG      = $0800;
  bitODDFRM      = $1000;
  bitBADCRC      = $2000;

  { bity registru TCR }

  bitFDSE        = $8000;
  bitETENTYPE    = $4000;
  bitEPHLOOP     = $2000;
  bitSTPSQET     = $1000;
  bitFDUPLX      = $0800;
  bitMONCSN      = $0400;
  bitNOCRC       = $0100;
  bitPADEN       = $0080;  { Zarovnavani odesilanych ramcu na 64 B }
  bitTXPEN       = $0008;
  bitFORCOL      = $0004;
  bitLOOP        = $0002;
  bitTXENA       = $0001;

  { bity registru EPHSR}

  bitTXUNRN      = $8000;
  bitLINKOK      = $4000;
  bitCTRROL      = $1000;
  bitEXCDEF      = $0800;
  bitLOSTCARR    = $0400;
  bitLATCOL      = $0200;
  bitWAKEUP      = $0100;
  bitTXDEFR      = $0080;
  bitLTXBRD      = $0040;
  bitSQET        = $0020;
  bit16COL       = $0010;
  bitLTXMULT     = $0008;
  bitMULCOL      = $0004;
  bitSNGLCOL     = $0002;
  bitTXSUC       = $0001;

  { bity registru RCR }
  bitSOFTRST     = $8000;
  bitFILTCAR     = $4000;
  bitSTRIPCRC    = $0200;
  bitRXEN        = $0100;
  bitALMUL       = $0004;
  bitPRMS        = $0002;
  bitRXABORT     = $0001;

  { bity registru PTR }

  bitRCV         = $8000;
  bitAUTOINCR    = $4000;
  bitREAD        = $2000;
  bitETEN        = $1000;
  bitAUTOTX      = $0800;


  { bity registru FIFO }

  bitREMPTY      = $80;
  bitTEMPTY      = $80;


  { MMUCR, prikazy MMU }

  mmuNOOP        = $00;
  mmuRESET       = $40;
  mmuRELEASE     = $A0;
  mmuTXALLOC     = $20;
  mmuTXRESET     = $E0;
  mmuTXREMOVETOP = $60;
  mmuTXENQUEUE   = $C0;
  mmuRXREMRELTOP = $80;
  mmuRXREMOVETOP = $70;

  mmuBUSY        = $01;


  { bity regitru CTR }

  bitSTORE       = $0001;
  bitRELOAD      = $0002;
  bitEEPSEL      = $0004;

  { interupt bity }

  intRCV         = $01;
  intTX          = $02;
  intALLOC       = $08;
  intRXOVRN      = $10;


{-------------------------------
{ BufferToPort
{---
{ Zapis bufferu na port
{---
}

procedure BufferToPort( PortIdx: Word; Buff: Pointer; Size: Word ); assembler;
asm
        MOV    CX, Size
        JCXZ   @@1
        PUSH   DS
        LDS    SI, Buff
        MOV    DX, PortIdx
        REP    OUTSB
        POP    DS
@@1:
end;

{-------------------------------
{ PortToBuffer
{---
{ Cteni z portu do bufferu
{---
}

procedure PortToBuffer( PortIdx: Word; Buff: Pointer; Size: Word ); assembler;
asm
        MOV    CX, SIZE
        JCXZ   @@1
        LES    DI, Buff
        MOV    DX, PortIdx
        REP    INSB
@@1:
end;

function  MemCmp( ABuff1, ABuff2: Pointer; ASize: Word ): Boolean;
  assembler;
asm
        MOV   AX, 1
        MOV   CX, ASize
        JCXZ  @@1
        PUSH  DS
        LDS   SI, ABuff1
        LES   DI, ABuff2
        REPE  CMPSB
        JE    @@2             { data jsou shodne => Z=1 }
        XOR   AX, AX
  @@2:
        POP   DS
  @@1:
end;


procedure WriteLanMemory( IoBase: Word; Page: Byte; Buffer: Pointer; Size: Word );
begin
  Port[ IoBase + regBSR ] := 2;
  Port[ IoBase + regPNR ] := Page;
  PortW[ IoBase + regPTR ] := bitAUTOINCR; { PTR = 0 }
  BufferToPort( Iobase + regData, Buffer, Size );
end;



procedure ReadLanMemory( IoBase: Word; Page: Byte; Buffer: Pointer; Size: Word );
begin
  Port[ IoBase + regBSR ] := 2;
  Port[ IoBase + regPNR ] := Page;
  PortW[ IoBase + regPTR ] := bitAUTOINCR or bitREAD; {PTR = 0}
  PortToBuffer( IoBase + regData, Buffer, Size );
end;

function  AllocLanPages( IoBase: Word; Size: Word ): Byte;
begin
  { Zadost o alokaci paketu }

  Port[ IoBase + regBSR ] := 2; { Banka 2 }

  Port[ IoBase + regMMUCR ] := mmuTXALLOC or (Size shr 8);

  while (Port[ IoBase + regIST ] and intALLOC = 0) do { nic };

  { Alokace se zdarila }
  AllocLanPages := Port[ IoBase + regARR ];
end;


procedure LanReset( IOBase: Word );
begin
  { SW reset radice }

  Port [ IoBase +  regBSR ] := 0;        { Banka 0 }
  PortW[ IoBase +  regRCR ] := bitSOFTRST;
  PortW[ IoBase +  regRCR ] := $0000;
end;

procedure RunTest( IoBase: Word );
type
  TTestBuffer = array[0..1023] of Byte;
var
  TestBuffW : TTestBuffer;
  TestBuffR : TTestBuffer;

  I         : Integer;

  Pass      : Longint;
  Errors    : Longint;

  Page      : Byte;
begin

  Pass     := 0;
  Errors   := 0;

  ClrScr;

  LanReset( IoBase );

  Page := AllocLanPages( IoBase, SizeOf( TestBuffW ) );

  repeat

    GotoXY( 1, 1 );

    WriteLn( 'Pass: ', Pass: 8, ' Errors: ', Errors );

    for I := Low(TTestBuffer) to High( TTestBuffer ) do
    begin
      TestBuffW[ I ] := Byte( Byte(Pass) + I );
    end;

    WriteLanMemory( IoBase, Page, @TestBuffW, SizeOf( TestBuffW ) );

    ReadLanMemory( IoBase, Page, @TestBuffR, SizeOf( TestBuffR ) );

    if not MemCmp( @TestBuffW, @TestBuffR, SizeOf( TestBuffW ) ) then
    begin
      Inc( Errors );

      GotoXY( 1, 2 );

      for I := Low(TTestBuffer) to High(TTestBuffer) do
      begin
        if I mod 64 = 0 then WriteLn;

        if TestBuffW[I] = TestBuffR[I] then
        begin
          Write( '-' );
        end
        else
          Write( 'x' );

      end;
    end;

    Inc( Pass );

  {$ifdef DOS}
  until Keypressed;
  {$endif}
  {$ifdef MCP}
  until False;
  {$endif}

end;


begin



  RunTest( $300 );

end.





