head     1.1;
access   paws bayes jws larry quist brad;
symbols  ;
locks    ; strict;
comment  @# @;


1.1
date     88.02.04.10.47.35;  author larry;  state tmp;
branches ;
next     ;


desc
@Base file for PWS 3.2 release.

@



1.1
log
@Initial revision
@
text
@$SYSPROG$
$MODCAL$ $UCSD$
$DEBUG OFF$ $RANGE OFF$ $STACKCHECK OFF$
PROGRAM ANALIZER(INPUT,OUTPUT);
$SEARCH 'LANDECS','DUMPER'$
IMPORT SYSGLOBALS,IODECLARATIONS,GENERAL_0,GENERAL_4,ASM,LANDECS,
       SYSDEVS,DUMPER;
CONST
  DUMPLINE = 9;
  MAXLANT  = 64;
TYPE
  LTR_PTR  = ^LANT_REC;
  LANT_REC = RECORD
	       D:LINK_ADDRESS_TYPE;
	       S:LINK_ADDRESS_TYPE;
	       COUNT : INTEGER; { PACKETS }
	     END;
  LTA_ARRAY = ARRAY[0..255,0..255] OF LTR_PTR;
  LTA_TYPE = ^LTA_ARRAY;
  BIGPACK = PACKED ARRAY[1..MAXINT] OF CHAR;
  PERF_REC = RECORD
	       D:LINK_ADDRESS_TYPE;
	       S:LINK_ADDRESS_TYPE;
	       T1:INTEGER;      { TIME OF LAST PACKET }
	       COUNT : INTEGER; { NUMBER OF PACKETS }
	       CUMT  : INTEGER; {SUM OF T1-PREVIOUS T1}
	       T2:INTEGER;      { LAST TIME A PACKET WENT IN OTHER DIR }
	       COUNT2: INTEGER; { TURN AROUND COUNT }
	       CUMT2 : INTEGER; {SUM OF T1-T1 IN OTHER DIRECTION }
	       RETRY : INTEGER; {PACKETS ONE DIRECTION BETWEEN ONE IN OTHER }
	     END;
  STATS_REC = RECORD
		CASE BOOLEAN OF
		FALSE:(PTR    : LAN_STATS_PTR);
		TRUE :(W1:SHORTINT;W2:SHORTINT);
	      END;
  LCL_STATS_TYPE = (LDATAC,RX_QUEUE,RX_QMAX,LDIR,LMC,LBC);

  LAN_PDATA_TYPE = PACKED RECORD
		       REC_TYPE    : BYTE;
		       RET_CODE    : BYTE;
		       SEQUENCE_NO : INTEGER;
		       SESSION  : SHORTINT;
		     END;

  LAN_PAIR_REC = RECORD
		   OWN : BOOLEAN;     { RECORD OWNER SHIP CONTROL }
		   T:INTEGER; { TIME STAMP }
		   SZ:INTEGER;{ PACKET SIZE }
		   CASE INTEGER OF
		   1:(D:LINK_ADDRESS_TYPE;
		      S:LINK_ADDRESS_TYPE);
		   2:(FH:IEEE802_HP_EXT_TYPE; { FRAME HEADER }
		      PD:LAN_PDATA_TYPE);{ PACKET DATA }
		 END;

    BP = ^BUF_INFO_TYPE;
VAR
  ETIME, TTIME, LTIME,
  TDATA, LDATA, MAXBPS : INTEGER;
  TEMP, BADC,MISSC : INTEGER;
  EDATA  : REAL;
  ELTIME,I,J,K : INTEGER;
  BCP,MCP,DIRP,RXQ,RXQM : INTEGER;
  DO_DUMP,DONE : BOOLEAN;
  C,C1     : CHAR;
  POT_SIZE,POT : INTEGER;
  LTP      : INTEGER;
  LTRAFFIC : LTA_TYPE;
  DUMPTYPE : CHAR;
  SM,DM,JM : CHAR;
  SLA,DLA  : LINK_ADDRESS_TYPE;
  DS_PERF  : PERF_REC;
  SD_PERF  : PERF_REC;
  SC       : INTEGER;
  LSTATS   : STATS_REC;
  LSTART_TIME,LLAST : INTEGER;
  LAN_SIZES: ARRAY[LAN_MIN_FRAME_LEN..LAN_MAX_FRAME_LEN] OF INTEGER;
  LAN_STATS: ARRAY[LCL_STATS_TYPE] OF INTEGER;
  ILL      : LCL_STATS_TYPE;
  LAN_TRAFFIC: ARRAY[0..MAXLANT] OF LAN_PAIR_REC;
  LANTP, LANTM : INTEGER;
  BUFFERS  : ARRAY[0..1] OF BP;

  LOGGING  : BOOLEAN;
  DUMPF    : TEXT;
  BUFNUM   : INTEGER;
  TITLE    : BOOLEAN;
  EXIT     : BOOLEAN;
  LAN_INFO : LAN_INFO_PTR;
  OLD_ESC  : INTEGER;
  FP       : FIBP;
  NRXBUFS  : INTEGER;

  PROCEDURE HEXIN(ANYVAR DATA:BIGPACK; PBYTES,NDIGITS:INTEGER);
    VAR REQBYTES,I,ZEROES,DIGIT : INTEGER;
	C : CHAR;
    BEGIN { HEXIN }
      REQBYTES := (NDIGITS DIV 2) + (NDIGITS MOD 2);
      IF PBYTES<REQBYTES THEN ESCAPE(1); { NO ROOM }
      ZEROES := PBYTES-REQBYTES;
      I := 1;
      WHILE I<ZEROES DO BEGIN DATA[I]:=#0; I := I + 1; END;
      WHILE NDIGITS>0 DO
      BEGIN
	READ(C);
	IF (C>='0') AND (C<='9') THEN DIGIT := ORD(C)-ORD('0')
	ELSE
	IF (C>='A') AND (C<='F') THEN DIGIT := ORD(C)-ORD('A')+10
	ELSE
	IF (C>='a') AND (C<='f') THEN DIGIT := ORD(C)-ORD('a')+10
	ELSE DIGIT := -1;
	IF DIGIT>=0 THEN
	BEGIN
	  IF ODD(NDIGITS) THEN
	  BEGIN
	    DATA[I] := CHR(ORD(DATA[I])+DIGIT);
	    I := I + 1;
	  END
	  ELSE DATA[I]:=CHR(DIGIT*16);
	  NDIGITS := NDIGITS-1;
	END;
      END;
    END; { HEXIN }

  PROCEDURE RING_STATS;
    VAR
      RXP1,RXPN: RX_RING_ELT_PTR;
      NUM      : INTEGER;
    BEGIN
      RXP1:= LAN_INFO^.RXR_1; { these references to ring elements will not  }
      RXPN:= LAN_INFO^.RXR_N; { survive changes in lan_info_rec layout }
      NUM := 0;
      REPEAT
	IF NOT RXP1^.OWN THEN NUM := NUM + 1;
	RXP1 := ADDR(RXP1^,SIZEOF(RX_RING_ELT_TYPE));
      UNTIL RXP1=RXPN;
      LAN_STATS[RX_QUEUE]:=NUM;
      IF NUM>LAN_STATS[RX_QMAX] THEN LAN_STATS[RX_QMAX]:=NUM;
    END; { RING_STATS }

  PROCEDURE STATS_ISR(TEMP : ANYPTR);
    VAR
      SIZE : INTEGER;
      LP   : LTR_PTR;
      LV   : SHORTINT;
      L1   : BYTE;
      OK   : BOOLEAN;
    BEGIN
      RING_STATS;
      LLAST := TICKER;  { last time a packet came in }
      SIZE := IOSTATUS(SC,L_GET_FRAME_SIZE);
      LAN_SIZES[SIZE] := LAN_SIZES[SIZE]+1;
      LAN_STATS[LDATAC] := LAN_STATS[LDATAC]+SIZE;
      LP := TEMP;
      L1 := ORD(LP^.D[1]);

      IF NOT ODD(L1) THEN LAN_STATS[LDIR] := LAN_STATS[LDIR]+1
      ELSE
      IF L1=255 THEN LAN_STATS[LBC] := LAN_STATS[LBC]+1
		ELSE LAN_STATS[LMC] := LAN_STATS[LMC]+1;

      WITH LAN_TRAFFIC[LANTP] DO
      BEGIN
	IF OWN THEN
	BEGIN
	  D := LP^.D;
	  S := LP^.S;
	  {FH := BUFPTR.IEE2^;}
	  T := TICKER;
	  SZ:= SIZE;
	  OWN := FALSE;
	  LANTP := (LANTP+1) MOD MAXLANT;
	END
	ELSE LANTM := LANTM + 1;
      END;

      IF LOGGING THEN
      BEGIN
	CASE DUMPTYPE OF
	'D':BEGIN { allow only directed packets }
	      IF ODD(L1) THEN IOCONTROL(SC,L_REJECT_FRAME,0);
	    END;
	'M':BEGIN { allow only mulitcast packets }
	      IF (NOT ODD(L1)) OR (L1=255) THEN
		 IOCONTROL(SC,L_REJECT_FRAME,0);
	    END;
	'B':BEGIN {allow only broadcast packets}
	      IF (L1<>255) THEN IOCONTROL(SC,L_REJECT_FRAME,0);
	    END;
	'P','p':
	    BEGIN
	      IF (DM='=') THEN OK := DLA = LP^.D
			  ELSE OK := TRUE;
	      IF ((JM='&') AND OK) OR
		 ((JM='|') AND NOT OK) THEN
		IF (SM='=') THEN OK := SLA = LP^.S
			    ELSE OK := TRUE;
	      {OK := OK AND (IEEE_HDR_PTR(TEMP)^.DSAP<200);}
	      IF NOT OK THEN IOCONTROL(SC,L_REJECT_FRAME,0);
	    END;
	'Q','q':
	    BEGIN
	      IF NOT
		 (((LP^.S=SD_PERF.S) AND (LP^.S=SD_PERF.D)) OR
		 ((LP^.S=SD_PERF.S) AND (LP^.S=SD_PERF.D)))
		 THEN IOCONTROL(SC,L_REJECT_FRAME,0);
	    END;
	OTHERWISE { allow everything }
	END;
      END
      ELSE IOCONTROL(SC,L_REJECT_FRAME,0); { reject everything }
    END; { STATS_ISR }

  PROCEDURE SETUP;
    VAR N: STRING[255];
	I: INTEGER;
    BEGIN
      WRITE('SELECT CODE TO MONTIOR = '); READLN(SC);
      NRXBUFS := IOSTATUS(SC,L_NUM_RX_BUFS);
      LAN_INFO := ADDR(ISC_TABLE[SC].IO_TMP_PTR^.DRV_MISC);
      WRITE('If no logging file name is given then LOGGING');
      WRITELN(' will not be done');
      WRITE('LOGGING FILE = '); READLN(N);
      N := STRRTRIM(STRLTRIM(N));
      LOGGING := N<>'';
      IF LOGGING THEN
      BEGIN
	REWRITE(DUMPF,N);
	FOR I := 0 TO 1 DO
	BEGIN
	  NEW(BUFFERS[I]);
	  IOBUFFER(BUFFERS[I]^,LAN_MAX_FRAME_LEN);
	END;
	FP := ADDR(DUMPF); { GET FIB POINTER }
      END;
      BUFNUM := 0;
    END; { SETUP }

  PROCEDURE DUMPBUFFERS;
    TYPE
      BUF = PACKED ARRAY [1..LAN_MAX_FRAME_LEN] OF CHAR;
      CB  = ^BUF;
    VAR I,J : INTEGER;
    BEGIN { DUMPBUFFERS }
      WHILE NOT BUFFER_BUSY(BUFFERS[BUFNUM]^) DO
      BEGIN
	I := BUFNUM;
	BUFNUM := 1-BUFNUM;
	TRANSFER(SC,OVERLAP_INTR,TO_MEMORY,BUFFERS[BUFNUM]^,LAN_MAX_FRAME_LEN);
	WITH FP^ DO
	  CALL(AM,FP,WRITEBYTES,CB(BUFFERS[I]^.BUF_EMPTY)^,
				   BUFFERS[I]^.TERM_COUNT,FPOS);
	WRITELN(DUMPF);
      END;
    END; { DUMPBUFFERS }

BEGIN { ANALIZER }
  SD_PERF.D := #0#0#0#0#0#0;
  SD_PERF.S := #0#0#0#0#0#0;
  SD_PERF.T1:= 0;
  SD_PERF.COUNT := 0;
  SD_PERF.COUNT2:= 0;
  SD_PERF.CUMT := 0;
  SD_PERF.CUMT2 := 0;
  SD_PERF.RETRY := 0;
  DS_PERF.D := #0#0#0#0#0#0;
  DS_PERF.S := #0#0#0#0#0#0;
  DS_PERF.T1:= 0;
  DS_PERF.COUNT := 0;
  DS_PERF.COUNT2:= 0;
  DS_PERF.CUMT := 0;
  DS_PERF.CUMT2 := 0;
  DS_PERF.RETRY := 0;

  SETUP;

  NEW(LTRAFFIC);
  FOR I := 0 TO 255 DO
    FOR J:= 0 TO 255 DO LTRAFFIC^[I,J]:=NIL;
  LTP := 0;               { for main program }
  LANTP := 0; LANTM := 0; { for isr }

  FOR I := LAN_MIN_FRAME_LEN TO LAN_MAX_FRAME_LEN DO LAN_SIZES[I]:=0;
  FOR ILL := LDATAC TO LBC DO LAN_STATS[ILL] := 0;
  FOR I := 0 TO MAXLANT DO LAN_TRAFFIC[I].OWN := TRUE; { isr owns all }
  { first chance to set the report type }
  { may need to control filtering in the isr }
      DUMPTYPE:='S'; {default dump type}
      TITLE   := TRUE;
      IF KEYBUFFER^.SIZE<>0 THEN
      BEGIN
	KEYBUFOPS(KGETLAST,C1);
	IF C1=#13 THEN READ(DUMPTYPE)
		  ELSE KEYBUFOPS(KAPPEND,C1);
      END;
      GOTOXY(0,DUMPLINE-1); WRITE(CHR(11));
      IF DUMPTYPE='P' THEN
      BEGIN { read the pattern }
	READ(DM);
	IF DM='=' THEN HEXIN(DLA,6,12);
	READ(JM);
	READ(SM);
	IF SM='=' THEN HEXIN(SLA,6,12);
	DUMPTYPE :='p';
      END;
      IF DUMPTYPE='Q' THEN
      BEGIN { read addresses & init stats }
	HEXIN(SD_PERF.D,6,12);
	SD_PERF.T1:= 0;
	SD_PERF.COUNT := 0;
	SD_PERF.COUNT2:= 0;
	SD_PERF.CUMT := 0;
	SD_PERF.CUMT2:= 0;
	SD_PERF.RETRY := 0;
	READ(JM);
	HEXIN(SD_PERF.S,6,12);
	DS_PERF.T1:= 0;
	DS_PERF.COUNT := 0;
	DS_PERF.COUNT2:= 0;
	DS_PERF.CUMT := 0;
	DS_PERF.CUMT2:= 0;
	DS_PERF.RETRY := 0;
	DS_PERF.D := SD_PERF.S;
	DS_PERF.S := SD_PERF.D;
	DUMPTYPE := 'q';
      END;
   { end of first chance to set the report type }
  { hook into the user isr }
  TRY
    LAN_STATS[RX_QUEUE]:=0; LAN_STATS[RX_QMAX]:=0;
    isc_table[sc].io_tmp_ptr^.user_isr.real_proc := stats_isr;

  IOCONTROL(SC,L_MODE,-32768); { put receiver in promiscuous mode }
  IOCONTROL(SC,L_RECONFIG,1);  { call for re-config }
  IOCONTROL(SC,L_FORCE_INTERUPT,0);  { force card interupt to do re-config }
  LSTATS.W2 := IOSTATUS(SC,L_GET_STATS_LSW); { get address of lstats array }
  LSTATS.W1 := IOSTATUS(SC,L_GET_STATS_MSW);
  IOCONTROL(SC,L_INIT_STATS,0); { clear card statistics }
  LSTART_TIME := TICKER;
  LLAST       := LSTART_TIME;
  RXQ := LAN_STATS[RX_QUEUE];
  RXQM:= LAN_STATS[RX_QMAX];
  GOTOXY(0,1);
  {1}WRITE('GOOD PACKETS = ',LSTATS.PTR^[LRX_NO_ERRORS]);
     BADC := LSTATS.PTR^[LRX_FRAME_ERR]+LSTATS.PTR^[LRX_OFLO_ERR]+
	     LSTATS.PTR^[LRX_CRC_ERR]+LSTATS.PTR^[LRX_OTHER_ERR];
     MISSC:= LSTATS.PTR^[LRX_MISS_ERR];
     WRITELN(' BAD       = ',BADC,' MISSED    = ',MISSC);
     BCP := 0; MCP := 0; DIRP := 0;
  {2}WRITELN('DIRECTED     = ',DIRP,' MULTICAST = ',MCP,' BROADCAST = ',BCP);
  {3}WRITELN('DATA BYTES   = ',LAN_STATS[LDATAC],
	    ' S-D MISSED= ',LANTM);
  {4}WRITELN('SINCE LAST P.= ',(LLAST-TICKER) DIV 2500,' 1/100 sec');
     ELTIME := (LSTART_TIME-TICKER) DIV 250000;
  {5}WRITELN('SAMPLE Bytes = ',0,'/',0:4,' milli secs');
  {6}WRITELN('MAX SMPL BPS = ',0,' RX_QUEUE  = ',RXQ,' MAX = ',RXQM:4,
	     ' of ',NRXBUFS:1);
  {7}WRITELN('ELAPSED SECS = ',ELTIME,' BYTES/SEC.= ',0);
  {8}WRITELN(DUMPTYPE);
  {9}WRITELN;
  {10}WRITELN;
  LDATA := 0;
  LTIME := TICKER;
  MAXBPS := 0;
  POT_SIZE := 1;
  IF LOGGING THEN TRANSFER(SC,OVERLAP_INTR,TO_MEMORY,
			   BUFFERS[BUFNUM]^,LAN_MAX_FRAME_LEN);
  EXIT := FALSE;
  REPEAT
    IF LOGGING THEN DUMPBUFFERS;

    GOTOXY(15,1); WRITE(LSTATS.PTR^[LRX_NO_ERRORS]);
    TEMP :=  LSTATS.PTR^[LRX_FRAME_ERR]+LSTATS.PTR^[LRX_OFLO_ERR]+
	     LSTATS.PTR^[LRX_CRC_ERR]+LSTATS.PTR^[LRX_OTHER_ERR];
    IF TEMP<>BADC THEN
	BEGIN BADC := TEMP; GOTOXY(40,1); WRITE(BADC); END;
    TEMP := LSTATS.PTR^[LRX_MISS_ERR];
    IF TEMP<>MISSC THEN
	BEGIN MISSC := TEMP; GOTOXY(65,1); WRITE(MISSC); END;

    TEMP := LAN_STATS[LDIR];
    IF TEMP<>DIRP THEN
      BEGIN DIRP := TEMP; GOTOXY(15,2); WRITE(DIRP); END;
    TEMP := LAN_STATS[LMC];
    IF TEMP<>MCP THEN
      BEGIN MCP := TEMP; GOTOXY(40,2); WRITE(MCP); END;
    TEMP := LAN_STATS[LBC];
    IF TEMP<>BCP THEN
      BEGIN BCP := TEMP; GOTOXY(65,2); WRITE(BCP); END;

    GOTOXY(15,3); WRITE(LAN_STATS[LDATAC]);

    GOTOXY(15,4); WRITE((LLAST-TICKER) DIV 2500);

    TEMP := LAN_STATS[RX_QUEUE];
    IF (TEMP<>RXQ) OR (RXQM<>LAN_STATS[RX_QMAX]) THEN
    BEGIN RXQ:=TEMP; RXQM := LAN_STATS[RX_QMAX];
	  GOTOXY(40,6); WRITE(RXQ);
	  GOTOXY(59,6); WRITE(RXQM:4);
    END;

    ETIME := (LSTART_TIME-TICKER) DIV 250000;
    IF ELTIME <> ETIME THEN
       BEGIN
	 ELTIME:=ETIME; GOTOXY(15,7); WRITE(ELTIME);
	 GOTOXY(40,7); WRITE(LAN_STATS[LDATAC] DIV ETIME);
	 DO_DUMP := (ELTIME MOD 10)=0;
	 IF DUMPTYPE='q' THEN DO_DUMP := TRUE;
       END;

    TTIME := TICKER;
    TDATA := LAN_STATS[LDATAC];

    ETIME := LTIME-TTIME;
    LTIME := TTIME;

    EDATA := TDATA-LDATA;
    LDATA := TDATA;

    TDATA := ROUND((EDATA * 250000.0) / ETIME);
    IF TDATA>MAXBPS THEN
      BEGIN MAXBPS := TDATA; GOTOXY(15,6); WRITE(MAXBPS); END;

    GOTOXY(15,5); WRITE(TDATA,'/',(ETIME DIV 250):4);

    WHILE NOT LAN_TRAFFIC[LTP].OWN DO
      WITH LAN_TRAFFIC[LTP] DO
      BEGIN
	IF (D=SD_PERF.D) AND (S=SD_PERF.S) THEN
	BEGIN
	  SD_PERF.COUNT := SD_PERF.COUNT + 1;
	  IF SD_PERF.T1<>0 THEN SD_PERF.CUMT  := SD_PERF.CUMT + (SD_PERF.T1-T);
	  SD_PERF.T1:=T;
	  IF DS_PERF.T1<>0 THEN { HAS BEEN A PACKET OTHER DIR }
	    IF DS_PERF.T1<>SD_PERF.T2 THEN { DIFFERENT THAN LAST LOOK }
	    BEGIN
	      SD_PERF.T2 := DS_PERF.T1; { TIME OF REQUEST }
	      SD_PERF.COUNT2 := SD_PERF.COUNT2 + 1;
	      IF SD_PERF.COUNT2>1 THEN
		 SD_PERF.CUMT2 := SD_PERF.CUMT2 + (SD_PERF.T2-T);
	    END
	    ELSE
	    SD_PERF.RETRY := SD_PERF.RETRY+1;
	END;
	IF (D=DS_PERF.D) AND (S=DS_PERF.S) THEN
	BEGIN
	  DS_PERF.COUNT := DS_PERF.COUNT + 1;
	  IF DS_PERF.T1<>0 THEN DS_PERF.CUMT  := DS_PERF.CUMT + (DS_PERF.T1-T);
	  DS_PERF.T1:=T;
	  IF SD_PERF.T1<>0 THEN
	    IF SD_PERF.T1<>DS_PERF.T2 THEN
	    BEGIN
	      DS_PERF.T2 := SD_PERF.T1;
	      DS_PERF.COUNT2 := DS_PERF.COUNT2 + 1;
	      IF DS_PERF.COUNT2>1 THEN
		 DS_PERF.CUMT2 := DS_PERF.CUMT2 + (DS_PERF.T2-T);
	    END
	    ELSE
	    DS_PERF.RETRY := DS_PERF.RETRY+1;
	END;

	I := ORD(D[6]);
	J := ORD(S[6]);
	DONE := FALSE;
	REPEAT
	  IF LTRAFFIC^[I,J]=NIL THEN
	  BEGIN
	    DONE := TRUE;
	    NEW(LTRAFFIC^[I,J]);
	    WITH LTRAFFIC^[I,J]^ DO
	    BEGIN
	      COUNT := 1;
	      D := LAN_TRAFFIC[LTP].D;
	      S := LAN_TRAFFIC[LTP].S;
	    END;
	  END
	  ELSE
	  BEGIN
	    WITH LTRAFFIC^[I,J]^ DO
	    IF (D<>LAN_TRAFFIC[LTP].D) THEN I:= (I+1) MOD 64
	    ELSE
	    IF (S=LAN_TRAFFIC[LTP].S) THEN
	    BEGIN DONE:=TRUE; COUNT := COUNT + 1; END
	    ELSE J := (J+1) MOD 64;
	  END;
	UNTIL DONE;
	OWN := TRUE;
	LTP := (LTP+1) MOD 64;
      END; { WHILE WITH }

    IF DO_DUMP THEN
    BEGIN
      GOTOXY(0,DUMPLINE-1);
      IF KEYBUFFER^.SIZE<>0 THEN
      BEGIN
	KEYBUFOPS(KGETLAST,C1);
	IF C1=#13 THEN BEGIN READ(C);
			     IF C='X' THEN EXIT := TRUE
			     ELSE
			     BEGIN
				DUMPTYPE := C;
				TITLE:=TRUE;
				WRITE(CHR(11));
			     END;
		       END
		  ELSE KEYBUFOPS(KAPPEND,C1);
      END;
      IF DUMPTYPE='P' THEN
      BEGIN { read the pattern }
	READ(DM);
	IF DM='=' THEN HEXIN(DLA,6,12);
	READ(JM);
	READ(SM);
	IF SM='=' THEN HEXIN(SLA,6,12);
	DUMPTYPE := 'p';
      END;
      IF DUMPTYPE='Q' THEN
      BEGIN  { read addresses & init stats }
	HEXIN(SD_PERF.D,6,12);
	SD_PERF.T1:= 0;
	SD_PERF.COUNT := 0;
	SD_PERF.COUNT2:= 0;
	SD_PERF.CUMT := 0;
	SD_PERF.CUMT2:= 0;
	SD_PERF.RETRY := 0;
	READ(JM);
	HEXIN(SD_PERF.S,6,12);
	DS_PERF.T1:= 0;
	DS_PERF.COUNT := 0;
	DS_PERF.COUNT2:= 0;
	DS_PERF.CUMT := 0;
	DS_PERF.CUMT2:= 0;
	DS_PERF.RETRY := 0;
	DS_PERF.D := SD_PERF.S;
	DS_PERF.S := SD_PERF.D;
	DUMPTYPE :='q';
      END;

      IF DUMPTYPE IN ['T','D','M','B','p'] THEN
      BEGIN
	TRY
	  IF TITLE THEN
	  BEGIN
	    GOTOXY(0,DUMPLINE);
	    WRITELN
 ('DESTINATION     SOURCE      COUNT  |DESTINATION     SOURCE      COUNT   ');
	       TITLE := FALSE;
	  END;
	  TEMP := DUMPLINE; J := 0;
	  FOR I := 1 TO 255 DO
	    FOR K := 1 TO 255 DO
	    BEGIN
	      IF LTRAFFIC^[I,K]<>NIL THEN
	      WITH LTRAFFIC^[I,K]^ DO
	      BEGIN
		CASE DUMPTYPE OF
		'T': DO_DUMP := TRUE;
		'D': DO_DUMP := NOT ODD(ORD(D[1]));
		'M': DO_DUMP := ODD(ORD(D[1])) AND (D[1]<>#255);
		'B': DO_DUMP := D[1]=#255;
		'p': BEGIN { PATTERN MATCH }
		       IF (DM='=') THEN DO_DUMP := D=DLA
				   ELSE DO_DUMP := TRUE;
		       IF ((JM='&') AND DO_DUMP) OR
			  ((JM='|') AND NOT DO_DUMP) THEN
			 IF (SM='=') THEN DO_DUMP := S=SLA
				     ELSE DO_DUMP := TRUE;
		     END;
		OTHERWISE DO_DUMP := FALSE;
		END;
		IF DO_DUMP THEN
		BEGIN
		  TEMP := TEMP + 1;
		  IF TEMP>22 THEN
		    BEGIN TEMP :=DUMPLINE+1; J:=J+36; C:='|'; END;
		  IF J>70 THEN ESCAPE(1);
		  GOTOXY(J,TEMP);
		  DUMPADDRESS(D); GOTOXY(J+13,TEMP);
		  DUMPADDRESS(S); GOTOXY(J+26,TEMP);
		  WRITE(COUNT:8);
		END;
	      END;
	    END; { FOR K }
	RECOVER
	  IF ESCAPECODE<>1 THEN ESCAPE(ESCAPECODE);
	DO_DUMP := FALSE;
      END
      ELSE { DUMP SIZES OR PERFORMANCE QUEUE }
      IF (DUMPTYPE='q') THEN
      BEGIN
	IF TITLE THEN
	BEGIN
	  GOTOXY(0,DUMPLINE);
	  WRITELN(
'DESTINATION     SOURCE    COUNT    AVG. TX    RETRYS  EXCGS  AVG TURN ARND'
		);
	  TITLE := FALSE;
	END;

	IF DUMPTYPE='q' THEN
	BEGIN
	  WITH DS_PERF DO
	  BEGIN
	    GOTOXY(0,DUMPLINE+1);
	    DUMPADDRESS(D); GOTOXY(13,DUMPLINE+1);
	    DUMPADDRESS(S); GOTOXY(26,DUMPLINE+1);
	    WRITE(COUNT:6);
	    IF COUNT>1 THEN WRITE((CUMT/(COUNT-1))*4/1000:15:4);
	    WRITE(RETRY:5);
	    WRITE(COUNT2:5);
	    IF COUNT2>1 THEN WRITE((CUMT2/(COUNT2-1))*4/1000:15:4);
	  END;
	  WITH SD_PERF DO
	  BEGIN
	    GOTOXY(0,DUMPLINE+2);
	    DUMPADDRESS(D); GOTOXY(13,DUMPLINE+2);
	    DUMPADDRESS(S); GOTOXY(26,DUMPLINE+2);
	    WRITE(COUNT:6);
	    IF COUNT>1 THEN WRITE((CUMT/(COUNT-1))*4/1000:15:4);
	    WRITE(RETRY:5);
	    WRITE(COUNT2:5);
	    IF COUNT2>1 THEN WRITE((CUMT2/(COUNT2-1))*4/1000:15:4);
	  END;
	END;
      END
      ELSE  { MUST BE SIZES DUMP }
      REPEAT
      TRY
	IF TITLE THEN
	BEGIN
	  GOTOXY(0,DUMPLINE);
	  WRITELN
 ('  SIZE,COUNT| SIZE,COUNT| SIZE,COUNT| SIZE,COUNT| SIZE,COUNT| SIZE,COUNT');
	  TITLE := FALSE;
	END;

	TEMP := DUMPLINE; J := 0; C := ' ';
	I := LAN_MIN_FRAME_LEN;
	REPEAT
	  POT := 0;
	  REPEAT
	    POT := POT + LAN_SIZES[I];
	    I := I + 1;
	  UNTIL (I>LAN_MAX_FRAME_LEN) OR ((I MOD POT_SIZE)=0);
	  IF POT<>0 THEN
	  BEGIN
	    TEMP := TEMP + 1;
	    IF TEMP>24 THEN
	      BEGIN TEMP := DUMPLINE+1; J:=J+12; C:='|'; END;
	    IF J>70 THEN ESCAPE(1);
	    GOTOXY(J,TEMP);
	    WRITE(C,I-POT_SIZE:5,POT:6);
	  END;
	UNTIL I>LAN_MAX_FRAME_LEN;
	DO_DUMP := FALSE;
      RECOVER
	IF ESCAPECODE=1 THEN
	BEGIN
	  IF POT_SIZE=1 THEN POT_SIZE:=5
	  ELSE
	  IF POT_SIZE=5 THEN POT_SIZE:=10
	  ELSE
	  IF POT_SIZE=10 THEN POT_SIZE:=20
			 ELSE POT_SIZE := 25;
	  GOTOXY(0,DUMPLINE+1); WRITE(CHR(11));
	END
	ELSE ESCAPE(ESCAPECODE);
      UNTIL NOT DO_DUMP;
    END;
  UNTIL EXIT;
  ESCAPE(0); { use recover code to clean up }
  recover
    BEGIN
      OLD_ESC := ESCAPECODE;
      isc_table[sc].io_tmp_ptr^.user_isr.dummy_pr := nil;
      IOCONTROL(SC,L_MODE,0); { put receiver in normal mode }
      IOCONTROL(SC,L_RECONFIG,1); { call for re-config }
      IOCONTROL(SC,L_FORCE_INTERUPT,0); { force card interupt to do re-config }
      IF LOGGING THEN CLOSE(DUMPF,'SAVE');
      IF OLD_ESC<>-20 THEN ESCAPE(OLD_ESC);
    END;
END. { ANALIZER }
@
