%include "INC:UTIL.IMP"
%include "DISQIO.INC"
%externalroutinespec show disq status

%constinteger track size = 32
%constinteger blocks = 823 * 10 * 32
%constinteger limit = 50 000

%owninteger t0
%ownintegerarray b(0 : 32 * 128) = 16_AAAAAAAA (*)

%externalroutine pdate
%integer d,h,m,s,ms=cputime-t0
  s = ms//1000; ms = rem(ms,1000)
  m = s//60; s = rem(s,60)
  h = m//60; m = rem(m,60)
  d = h//24; h = rem(h,24)
  write(d,0) %unless d=0
  write(h,2) %unless h=0
  write(m,2)
  write(s,2)
  write(ms,3)
  space
%end

%integerfn do read(%integer start, blocks)
   %integername x
   %integer wanted, c
try again:
      wanted = blocks << 9
      c = limit
      x == transfer(D write ! D verify, wanted, start << 9, b(0))
      c = c - 1 %while x = 0 %and c > 0
      %if c <= 0 %start
         printstring("Disc timeout");  newline
         show disq status
         -> try again
      %else %unless x = wanted
         %result = -1
      %finish
      c = limit
      x == transfer(D read ! D verify, wanted, start << 9, b(0))
      c = c - 1 %while x = 0 %and c > 0
      %if c <= 0 %start
         printstring("Disc timeout");  newline
         show disq status
         -> try again
      %else %if x = wanted
         %result = 0
      %else
         %result = -1
      %finish
%end

%routine error(%integer block)
   %owninteger errors = 0
      errors = errors + 1
      printstring("Error ");  write(errors, 0)
      printstring(": unable to access block ");  write(block, 0)
      newline
      select output(3)
      printstring("Error ");  write(errors, 0)
      printstring(": unable to access block ");  write(block, 0)
      newline
      select output(0)
%end

%routine try one(%integer block)
   %integer x
write(block,7);newline
      x = do read(block, 1)
      error(block) %if x # 0
%end          

%routine try several(%integer start, blocks)
   %integer i, x
write(start,7;blocks,3);newline
!     %if start & (16 * 32 - 1) = 0 %start
!        pdate
!        printstring("Cylinder ")
!        write(start >> 9, 0)
!        newline
!     %finish
      x = do read(start, blocks)
      %return %if x = 0
{}printsymbol(7)
      try one(i) %for i = start, 1, start + blocks - 1
%end

%begin
   %constinteger chunk = track size; !16
   %integer i
   %string(255)log
      log = cliparam
      log = "BAD.DAT" %if log=""
      open output(3, log)
      select output(3)
      t0 = cputime
      printstring("Bad block run starting at ")
      pdate; newline
      select output(0)
      try several(i, chunk) %for i = 0, chunk, blocks - chunk
      select output(3)
      printstring("Bad block run finished at ")
      pdate; newline
      close output
      select output(0)
%end %of %program
