
    /* Common Include Module for RSP and Transient MPMSTAT */


$include(comlit.lit)

dcl buff(128) byte external;

mon1:
  procedure (func,info) external;
    dcl func byte;
    dcl info address;
  end mon1;

mon2:
  procedure (func,info) byte external;
    dcl func byte;
    dcl info address;
  end mon2;

mon3:
  procedure (func,info) address external;
    dcl func byte;
    dcl info address;
  end mon3;

mon4:
  procedure (func,info) pointer external;
    dcl func byte;
    dcl info address;
  end mon4;

dcl screenwidth lit '80',
    lparen byte data ('['),
    rparen byte data (']'),
    dummy  lit '0';

$include(mdsat.lit)
$include(proces.lit)
$include(sd.lit)
$include(qd.lit)
$include(ccb.lit)
$include(flag.lit)

dcl pd$pointer pointer;  /* double word bases for MP/M-86 data structures */
dcl pd$ptr structure(
  offset word,
  segment word) at (@pd$pointer);
dcl pd based pd$pointer pd$structure;

dcl qd$pointer pointer;
dcl qd$ptr structure(
  offset word,
  segment word) at (@qd$pointer);
dcl qd based qd$pointer qd$structure;

dcl md$pointer pointer;
dcl md$ptr structure(
  offset word,
  segment word) at (@md$pointer);
dcl md based md$pointer md$structure;

dcl ms$pointer pointer;
dcl ms$ptr structure(
  offset word,
  segment word) at (@ms$pointer);
dcl ms based ms$pointer ms$structure;
 
dcl sat$pointer pointer;
dcl sat$ptr structure(
  offset word,
  segment word) at (@sat$pointer);
dcl sat based sat$pointer sat$structure;

dcl flag$pointer pointer;
dcl flag$ptr structure(
  offset word,
  segment word) at (@flag$pointer);
dcl flag based flag$pointer flag$structure;

dcl ccb$pointer pointer;
dcl ccb$ptr structure (
  offset word,
  segment word) at (@ccb$pointer);
dcl ccb based ccb$pointer ccb$structure;

/*dcl lst$pointer pointer;
  dcl lst$ptr structure (
    offset word,
    segment word) at (@lst$pointer);
  dcl lst based lst$pointer lst$structure;*/


/* BDOS Calls */

  reboot:
    procedure;
      call mon1(0,0);
    end reboot;

  conin:
    procedure byte;
      return(mon2(1,0));
    end conin;

  co:
    procedure (char);
      dcl char byte;
      call mon1 (2,char);
    end co;

  print$buffer:
    procedure (bufferadr);
      dcl bufferadr address;
      call mon1 (9,bufferadr);
    end print$buffer;

  read$buffer:
    procedure (bufferadr);
      dcl bufferadr address;
      call mon1 (10,bufferadr);
    end read$buffer;

  get$version:
    procedure word;
      return mon3(12,0);
    end get$version; 

  terminate:
    procedure;
      call mon1(143,0);
    end terminate;

  get$sysdat:
    procedure pointer;
      return mon4(154,0);
    end get$sysdat;

  /* XDOS Function Definitions */

  dcl	qmake		lit	'134';
  dcl   qopen           lit     '135';
  dcl	qread		lit	'137';
  dcl	dispatch	lit	'142';
  dcl	setprior	lit	'145';
  dcl	condetach	lit	'147';
  dcl	setdefcon	lit	'148';


/* utility functions */

  crlf:
    procedure;
      call co (0DH);
      call co (0AH);
    end crlf;

  dcl hex$digit (*) byte data ('0123456789ABCDEF');

  display$hex$byte:
    procedure (value);
      dcl value byte;
      call co (hex$digit(shr(value,4)));
      call co (hex$digit(value mod 16));
    end display$hex$byte;
 
  display$hex$word:
    procedure (value);
      dcl value word;
      call display$hex$byte (high(value));
      call display$hex$byte (low (value));
    end display$hex$word;

  display$text:			/* does byte at a time console write */
    procedure (count,source);	/* from possibly another segment */ 
      dcl count byte;
      dcl source pointer;
      dcl char based source byte;
      dcl src$ptr structure(
        offset word,
	segment word) at (@source);	
      dcl i byte;

      if count = 0 then
        do while char <> '$';
	  call co (char and 7fh);
          src$ptr.offset = src$ptr.offset + 1;
        end; 
      else
        do i = 1 to count;
          call co (char and 7fh);
          src$ptr.offset = src$ptr.offset + 1;
        end;

    end display$text;

  dcl link$list (64) word; /* used by display$links & display$memory */

  display$links:
    procedure (title$adr,root$offset,dis$con,init$col);
      dcl dis$con boolean;	/* Print linked list of PDs starting with */
      dcl count byte;		/* root$offset.  Print title if not dummy */
      dcl init$col byte;	/* display console number if dis$con = true */
      dcl title$adr address;	/* First line starts on column init$col    */
      dcl root$offset address;
      dcl char based title$adr byte;
      dcl col byte;			/* column number relative to 1 */

      dcl (n,k) byte;

      if title$adr <> dummy then
	do;
	call crlf;
        call print$buffer (title$adr);
	col = screenwidth + 1;			/* start new line */
	end;
      else
	col = init$col;	/* initial column position from calling procedure */
      n = -1;
      disable;  /* critical section required to obtain list */
      pd$ptr.offset = root$offset;
        do while (pd$ptr.offset <> 0) and (n <> 63);
          link$list(n := n + 1) = pd$ptr.offset;
          pd$ptr.offset = pd.link;
        end;
      call mon1 (dispatch,0);  /* enable interrupts by dispatching */
      if n = - 1 then return;
      do k = 0 to n;
        pd$ptr.offset = link$list(k);
        if col > screenwidth - 13 then	/* 13 chars could be used already */
        do;
          call crlf;
          col = 1;
        end;
        call co (' ');				/* 13 characters for pd */
        call display$text (pnamsiz,@pd.name);
        if pd.mem <> 0ffh and dis$con then	/* display console number ? */
        do;
          call co (lparen);
          call display$hex$byte(pd.cns);	/* prints 2 chars */
          call co (rparen);
        end;
	else
	  call print$buffer(.('    $'));	/* not printing console # */
        col = col + 13;				/* but pad to make things */
      end;					/* line up		  */
    enable;
    end display$links;

  display$config:
    procedure;
      dcl count byte, qsize word;

      call print$buffer(.('Number of Physical Consoles = $'));
      call display$hex$byte (sd.ncns);
      call print$buffer(.(0dh,0ah,'Number of Virtual Consoles = $'));
      call display$hex$byte (sd.nccb - (sd.nlst + sd.ncns));
      call print$buffer (.(0dh,0ah,'Number of List Devices = $'));
      call display$hex$byte (sd.nlst);

      call print$buffer (.(0dh,0ah,'Number of Free Process Descriptors = $'));
      pd$ptr.offset = sd.pul;
      count = 0;
      do while pd$ptr.offset <> 0;
          count = count + 1; 
          pd$ptr.offset = pd.link;
      end;
      call display$hex$byte(count);

      call print$buffer (.(0dh,0ah,'Number of Free Memory Descriptors = $'));
      md$ptr.offset = sd.mdul;
      count = 0;
      do while md$ptr.offset <> 0;
          count = count + 1; 
          md$ptr.offset = md.link;
      end;
      call display$hex$byte (count);

      call print$buffer(.(0dh,0ah,'Number of Free Queue Control Blocks = $'));
      qd$ptr.offset = sd.qul;
      count = 0;
      do while qd$ptr.offset <> 0;
          count = count + 1; 
          qd$ptr.offset = qd.link;
      end;
      call display$hex$byte (count);

      call print$buffer(.(0dh,0ah,'Free Queue Buffer Area = $'));
      md$ptr.offset = .sd.qmau(0);
      sat$ptr.segment = md.start;
      sat$ptr.offset = size(sat); 
      qsize = 0;
      do while sat.start <> 0;         /* byte offset for q buffer area */
           if sat.num$allocs = 0 then
              qsize = qsize + sat.len;
          sat$ptr.offset = size(sat) + sat$ptr.offset;
      end;
      call display$hex$word (qsize);

      call print$buffer(.(0dh,0ah,'Number of Flags = $'));
      call display$hex$byte (sd.nflags);
      call print$buffer(.(0dh,0ah,'Maximum Paragraphs Per Process = $'));
      call display$hex$word (sd.mmp);
      call crlf;
    end display$config;

  display$ready:
    procedure;
      call display$links (.('Ready Process(es): $'),sd.rlr,true,1);
    end display$ready;

  display$DQ:
    procedure;
      call crlf;
      call print$buffer (.('Process(es) DQing: $'));
      qd$ptr.offset = sd.qlr;
      do while qd$ptr.offset <> 0;
        if qd.dq <> 0 then
        do;
          call print$buffer (.(0DH,0AH,' $'));
          call co(lparen);
          call display$text (8,@qd.name);
          call co(rparen);
          call print$buffer(.('  $'));
          call display$links (dummy,qd.dq,true,14);
        end;
        qdptr.offset = qd.link;
      end;
    end display$DQ;

  display$NQ:
    procedure;

      call crlf;
      call print$buffer (.('Process(es) NQing:','$'));
      qdptr.offset = sd.qlr;
      do while qdptr.offset <> 0;
        if qd.nq <> 0 then
          do;
          call print$buffer (.(0DH,0AH,' $'));
          call co(lparen);
          call display$text (8,@qd.name);
          call co(rparen);
          call print$buffer(.('  $'));
          call display$links (dummy,qd.nq,true,14);
          end;
        qdptr.offset = qd.link;
      end;
    end display$NQ;

  display$delay:
    procedure;
      call display$links (.('Delayed Process(es):$'),sd.dlr,true,1);
    end display$delay;

  display$poll:
    procedure;
      call display$links (.('Polling Process(es):$'),sd.plr,true,1);
    end display$poll;

  display$flag$wait:
    procedure;
      dcl i integer;
      call crlf;
      flag$ptr.offset = sd.flags;
      call print$buffer(.('Process(es) Flag Waiting:$'));
      do i = 0 to signed(sd.nflags - 1);
        if flag.pd < 0FFFEH then
        do;
           call crlf;
           call co (' ');
           call co (' ');
           call display$hex$byte (low(unsign(i)));
           call print$buffer (.(' -       $'));
           call display$links (dummy,flag.pd,true,14);
        end;
        flag$ptr.offset = flag$ptr.offset + size(flag);
      end;
    end display$flag$wait;

  display$flag$set:
    procedure;
      dcl (j,i) byte;
      flag$ptr.offset = sd.flags;
      call crlf;
      call print$buffer (.('Flag(s) Set:$'));
      i = 0;
      j = screenwidth;
      do while i < sd.nflags; 
        if flag.pd = 0fffeh then
          do;
          if j >= screenwidth then
            do;
            call crlf; j = 0;
            end;
          call co (' ');
          call co (' ');
          call display$hex$byte (i);
          j = j + 4;
          end;
        flag$ptr.offset = flag$ptr.offset + size(flag);
        i = i + 1;
      end;
    end display$flag$set;

  display$queues:
    procedure;
      dcl i byte;
      qd$ptr.offset = sd.qlr;
      call print$buffer(.(cr,lf,'Queue(s):$'));
      i = screenwidth;
      do while qd$ptr.offset <> 0;
        if i > screenwidth - 19 then
        do;
          call crlf; i = 0;
        end;
        call co (' ');
        call display$text (8,@qd.name);
        if (qd.flags and qf$mx) and (qd.buffer <> 0) then
          do;
          pdptr.offset = qd.buffer;	/* addr of of owning process */
          call co (lparen);
          call display$text (pnamsiz,@pd.name);
          call co (rparen);
          end;
        else
          call print$buffer(.('          $'));
        qd$ptr.offset = qd.link;
        i = i + 19;
      end;
    end display$queues;

  display$ccb:
    procedure(name,first$ccb,last$ccb);
      dcl name address,
          (i,first$ccb, last$ccb) byte,
          name$offset lit '6';

      if last$ccb - first$ccb = 0 then
          return; 
      ccb$ptr.offset = sd.ccb + size(ccb) * first$ccb;
      call print$buffer (.(0dh,0ah,'Process(es) Attached to $'));
      call print$buffer (name);
      do i = 0 to last$ccb - first$ccb - 1;
        call print$buffer (.(0dh,0ah,' $'));
        call co(lparen);
        call display$hex$byte(i);
        call co(rparen);
        call print$buffer (.('      - $'));
        if ccb.attach = 0 then
          call print$buffer(.('Unattached$'));
        else if ccb.attach = 0ffffh then
        do;
          call print$buffer(.('Control P - Console $'));
          call co(lparen);
          call display$hex$byte(ccb.msource);
          call co(rparen);
        end;
        else
          do;		
	  pd$ptr.offset = ccb.attach;
	  call display$text(pnamsiz,@pd.name);
          end;
      ccb$ptr.offset = ccb$ptr.offset + size(ccb);
      end;
      ccb$ptr.offset = sd.ccb + size(ccb) * first$ccb; 	
      call print$buffer (.(0dh,0ah,'Process(es) Waiting for $'));
      call print$buffer (name);
      do i = 0 to last$ccb - first$ccb - 1;
        if ccb.queue <> 0 then
          do;
          call print$buffer (.(0dh,0ah,' $'));
          call co(lparen);
          call display$hex$byte (i); 
          call co (rparen);
          call print$buffer(.('      -$'));	/* put out 13 chars to */
          call display$links (dummy,ccb.queue,false,13);  /* line up   */
          end;				/* with other PD displays      */
        ccb$ptr.offset = ccb$ptr.offset + size(ccb);
      end;
    end display$ccb;

  display$memory:
    procedure;
      dcl (i,n,col) byte;
      call crlf;
      call print$buffer(.('Memory Partitions:$'));
      call crlf;
      do col = 1 to screen$width / 23;
        call print$buffer(.('Start Length Process | $'));
      end;
      col = screenwidth + 1;	/* force new line */

      n = -1;
      disable;         /* critical section required to obtain list */
      pd$ptr.offset = sd.thrdrt;
        do while (pd$ptr.offset <> 0) and (n <> 63);
          link$list(n := n + 1) = pd$ptr.offset;
          pd$ptr.offset = pd.thread;
        end;
      call mon1 (dispatch,0);  /* enable interrupts by dispatching */
      if n = - 1 then return;

      do i = 0 to n;
        pd$ptr.offset = link$list(i);
        if col > screenwidth - 23 then
        do;
          call crlf; col = 1;
        end;
        if pd.mem <> 0 and pd.mem <> 8 then
          do;
          ms$ptr.offset = pd.mem;
          md$ptr.offset = ms.mau;      /* the mau field of a MS descriptor */
          call display$hex$word(md.start);  /* one or more partitions */
          call print$buffer(.('   $'));     /* described by the MAU   */
          call display$hex$word(md.length);
          call print$buffer(.('  $'));
          call display$text(pnamsiz,@pd.name);
          call print$buffer(.('  $'));
          col = col + 23; 
          end;
      end;       

      md$ptr.offset = sd.mfl;
      do while md$ptr.offset <> 0;		/* don't need critical  */
        if col > screenwidth - 23 then		/* region for MD list - */
          do;					/* they aren't deleted  */ 
          call crlf; col = 0;
          end;
        call display$hex$word (md.start);
        call print$buffer(.('   $'));
        call display$hex$word (md.length);
        call print$buffer(.('  * FREE *  $'));
        md$ptr.offset = md.link;
        col = col + 23;
      end;
    enable;
    end display$memory;

