! Ambit disk controller test program

%option "-low-nocheck-nostack-nodiag"
%include "inc:util.imp-nolist"

%recordformat adf(%bytearray b(1:8) %or %byte drive,head,cyll,cylh,sector)
%recordformat cof(%byte sd,sh,snh,scl,sch,ss,sspt,
                        dd,dh,dnh,dcl,dch,ds,dspt,
                        nl,nm,nh)

%constbyte abort=1,init=2,init1=7,
           readdisc=16_21,writedisc=16_22,readid=16_23,
           drivestatus=16_25,format=16_27,seek=16_28,
           readbuffer=16_41,writebuffer=16_42

%recordformat diskf(%readonly %volatile %byte diskr %orc
                    %writeonly %byte diskw, w1,w2,w3)
%constinteger dw3 = 255!!16_00,dw2=255!!16_ff,dw1=255!!16_7f
@16_ed0000 %writeonly%record(diskf)disk
%ownrecord(adf)address
%ownbytearray buffer(1:512)
%owninteger hard=0,soft=0,data=0
%owninteger comtime=0,exetime=0
%owninteger ta0=0,ta1=0,txf=0,tff=0,t00=0,tiw=0

%bytefn command(%byte c)
%owninteger initialised=0,inted=0
%integer tt,t,i

  %routine arm
    disk_w3 = dw3
    disk_w2 = dw2
    disk_w1 = dw1
  %end

  %routine dint
    *movem.l d0-d7/a0-a6,-(sp)
    inted = 1
    *movem.l (sp)+,d0-d7/a0-a6
    *rte
  %end

  %routine wait
  %integer i
    %for i = 1,1,50 %cycle
    %repeat
  %end

  %routine log(%integername x)
  %integer now
    now = cputime
    x = now-t+x; t = now
  %end

  *lea dint,a0
  *move.l a0,16_106c

  tt = cputime; t = tt
  %if initialised=0 %start
    disk_diskw = 0; initialised = 1
  %finish
  %cycle
    i = disk_diskr
  %repeatuntil i=16_a0
  log(ta0)
  disk_diskw = c
  %cycle
    i = disk_diskr
  %repeatuntil i=16_a1
  log (ta1)
  disk_diskw = 255
  wait
  %if c = readid %or c = drivestatus %start
    address_b(i) = disk_diskr %for i = 1,1,8
  %elseif c&16_20#0
    disk_diskw = address_b(i) %for i = 1,1,8
  %elseif c = readbuffer
    buffer(i) = disk_diskr %for i = 1,1,512
  %elseif c = writebuffer
    disk_diskw = buffer(i) %for i = 1,1,512
  %finish
  log (txf)
  disk_diskw = 255
!  %if c=readdisc %or c=writedisc %start
    inted = 0
    arm
    %cycle
    %repeatuntil inted#0
    log(tiw)
!  %else
!    wait
!  %finish
  %cycle
    i = disk_diskr
  %repeatuntil i=16_FF
  log (tff)
  disk_diskw = 254
  %cycle
    i = disk_diskr
  %repeatuntil i&128=0
  log(t00)
%if inted=0 %then printsymbol('N') %else printsymbol('Y')
  c = disk_diskr
  disk_diskw = 0
  comtime = cputime-tt+comtime
  hard = hard+1 %if c&16_40#0
  soft = soft+1 %if c&16_60=16_20
  %result = c
%end

 %constinteger sectors=16,tracks=11,cylinders=754 {Fujitsu M2243AS
{%constinteger sectors=16,tracks=4, cylinders=640 {Rodime RO202E
%constinteger gap=3

%routine do init
%ownbytearray p(1:16)=
255,0,0,0,0,0,4,(cylinders-1)&255,(cylinders-1)>>8,0,0,0,0,0,0,0
%integer i
  buffer(i) = p(i) %for i = 1,1,16
  buffer(i) = 0 %for i = 17,1,512
  phex2(command(writebuffer))
  phex2(command(init)); newline
%end

%routine do format
%integer cyl,cyls,head,heads,htemp

  %integerfn formatting increment(%integer separation)
  %integerarray s(0:sectors-1)
  %integer i,j
  %integername p
    s(i) = 0 %for i=0,1,sectors-1
    j = -separation
    %for i=1,1,sectors %cycle
      j = rem(j+separation,sectors); p == s(j)
      %result = -1 %unless p=0; p = i
    %repeat
    %result = rem(s(1)-s(0)+sectors,sectors)
  %end

  %routine setup
  %integer sec=0,inc=0,i
    inc = formatting increment(gap)
    buffer(i) = 0 %for i = 1,1,512
    %for i = 1,1,sectors %cycle
      buffer(i) = sec; sec = rem(sec+inc,sectors)
    %repeat
    phex2(command(writebuffer)); newline
  %end

  address = 0
  address_sector = sectors-1
  prompt("Cyl,cyls,head,heads:")
  read(cyl); read(cyls); read(head); read(heads); htemp = heads
  skipsymbol
  setup
  %cycle
    %cycle
      %if cyl=0 %and cyls=0 %start
        %if head=0 %and heads=0 %start {Entire disk
          address_head = tracks-1+128
          address_cyll = (cylinders-1)&255
          address_cylh = (cylinders-1)>>8
        %else
          address_head = head
          address_cyll = (cylinders-1)&255
          address_cylh = (cylinders-1)>>8+128
        %finish
      %else
        address_head = head
        address_cyll = cyl&255
        address_cylh = cyl>>8
      %finish
      phex4(cyl); space; phex2(head); space
      phex2(command(format)); newline
      head = head+1; heads = heads-1
    %repeatuntil heads<=0
    head = head+heads
    heads = htemp
    head = head-heads
    cyl = cyl+1; cyls = cyls-1
  %repeatuntil cyls<=0
%end

%routine generate(%integer pattern)
%integer i
%switch sw(0:24)
  pattern = rem(pattern,50)
  ->sw(pattern>>1)
sw(1):sw(2):sw(3):sw(4):sw(5):sw(6):sw(7):sw(8):
  pattern = pattern&1+1<<(pattern>>1)
sw0:sw(0):
  pattern = \pattern %if pattern&1#0
  pattern = pattern>>1
  buffer(i) = pattern %for i = 1,1,512
  %return
sw(9):sw(10):sw(11):sw(12):sw(13):sw(14):sw(15):sw(16):
  pattern = \pattern %if pattern&1#0
  pattern = pattern>>1
  %for i = 1,1,512 %cycle
    buffer(i) = pattern
    pattern = pattern<<1&511; pattern = pattern+1 %if pattern&256#0
  %repeat
sw(17):sw(18):sw(19):sw(20):sw(21):sw(22):sw(23):sw(24):
  pattern = \pattern %if pattern&1#0
  pattern = pattern>>1&255
  %for i = 1,1,512 %cycle
    buffer(i) = pattern
    pattern = pattern+256 %if pattern&1#0; pattern = pattern>>1
  %repeat
%end

%routine verify(%integer pat)
%bytearray was(1:512)
%integer e=0,i
  was(i) = buffer(i) %for i = 1,1,512
  generate(pat)
  %for i = 1,1,512 %cycle
    %if was(i)#buffer(i) %start
      e = e+1
      %if 0<e<=16 %start
        printstring("Data at"); write(i-1,3)
        printstring(" is "); phex2(was(i))
        printstring(" should be "); phex2(buffer(i)); newline
      %finish
    %finish
    data = data+e
  %repeat
  %if e>1 %start
    write(e,3); printstring(" errors"); newline
  %finish
%end

%routine do test
%integer patt,pinc,times

  %routine zap
  %integer i
    %if times<0 %start
      newline
      %for i = 1,1,512 %cycle
        phex4(i) %and printsymbol(':') %if i&15=1
        space; phex2(buffer(i)); newline %if i&15=0
      %repeat
      newline
    %finish
    buffer(i) = buffer(i)!!255 %for i = 1,1,512
  %end

  prompt("Pattern,inc,times:"); read(patt); read(pinc); read(times)
  skipsymbol
  %while times#0 %cycle
    generate(patt)
    phex2(command(writebuffer))
    zap
    phex2(command(readbuffer)); newline
    verify(patt)
    patt = patt+pinc
    %if times<0 %then times = times+1 %else-
    times = times-1
  %repeat
%end

%routine errorlog
  %if hard#0 %start
    printstring(" H="); write(hard,0)
  %finish
  %if soft#0 %start
    printstring(" S="); write(soft,0)
  %finish
  %if data#0 %start
    printstring(" D="); write(data,0)
  %finish
  newline
%end

%routine do write
%integer block,inc,patt,pinc,blocks,c,h,s
  prompt("Pattern,inc:"); read(patt); read(pinc)
  prompt("Block,inc,blocks:"); read(block); read(inc); read(blocks)
  skipsymbol
  blocks = sectors*tracks*cylinders %if blocks=0
  %while blocks>0 %cycle
    generate(patt)
    s = rem(block,sectors*tracks*cylinders)
    write(s,6); space
    h = s//sectors; s = rem(s,sectors)
    c = h//tracks;  h = rem(h,tracks)
    address = 0
    address_cylh = c>>8
    address_cyll = c&255
    address_head = h
    address_sector = s
    printsymbol('w'); phex4(c); space; phex2(h); space; phex2(s); space
    phex2(command(writebuffer))
    phex2(command(writedisc))
    errorlog
    block = block+inc; patt = patt+pinc
    blocks = blocks-1
  %repeat
%end

%routine do read
%integer block,inc,patt,pinc,blocks,c,h,s
  prompt("Pattern,inc:"); read(patt); read(pinc)
  prompt("Block,inc,blocks:"); read(block); read(inc); read(blocks)
  skipsymbol
  blocks = sectors*tracks*cylinders %if blocks=0
  %while blocks>0 %cycle
    s = rem(block,sectors*tracks*cylinders)
    write(s,6); space
    h = s//sectors; s = rem(s,sectors)
    c = h//tracks;  h = rem(h,tracks)
    address = 0
    address_cylh = c>>8
    address_cyll = c&255
    address_head = h
    address_sector = s
    printsymbol('r'); phex4(c); space; phex2(h); space; phex2(s); space
    phex2(command(readdisc))
    phex2(command(readbuffer))
    errorlog
    verify(patt)
    block = block+inc; patt = patt+pinc
    blocks = blocks-1
  %repeat
%end

%begin
%integer sym,t
  do init
  %cycle
    prompt("t/e/f/r/w:")
    readsymbol(sym)
    t = cputime
    sym = sym!32
    %exitif sym='e'
    %if sym='f' %start
      do format
    %elseif sym='t'
      do test
    %elseif sym='r'
      do read
    %elseif sym='w'
      do write
    %finish
    exetime = cputime-t+exetime
  %repeat
  set terminal mode (0)
  write(comtime,0); printsymbol('/')
  write(exetime,0); newline
  printstring("A0 A1 XF FF 00:")
  write(ta0,1); write(ta1,1); write(txf,1); write(tff,1); write(t00,1)
  write(ta0+ta1+txf+tff+t00,8); errorlog
  write(tiw,0); newline
%endofprogram
