! Disq IO procedures for Fred-Machine Filestore ! Version for M2294N drive - 1024*16*32*512 !This version logs interrupts per transfer %option "-nocheck-noline-nostack-nodiag-low" %include "inc:util.imp" %externalroutinespec pdate ! Configuration parameters %constinteger lbps = 9; ! log(bytes per sector) %constinteger bps = 1< ! Unit Status ! SEL | SEN | WPR | AMF | RDY | ONC | SER | FLT ! Controller Commands %constinteger clear done = 8 %constinteger mute srq = 4 %constinteger clear fifo = 2 %constinteger reset = 1 %constinteger specify = 16_20 %constinteger sense int = 16_10 %constinteger sense unit = 16_30 %constinteger detect error = 16_40 %constinteger recalibrate = 16_50 %constinteger seek = 16_60 %constinteger format = 16_70 %constinteger verify format = 16_80 %constinteger read format = 16_90 !constinteger read bad data = 16_a0 %constinteger read data = 16_b0 %constinteger write data = 16_f0 %constinteger verify data = 16_e0 !constinteger check data = 16_c0 !constinteger scan data = 16_d0 %constinteger blank=' ' %owninteger action=blank, state=blank, wrong=0 %routine parameter(%integer x) nec data = x %end %integerfn result %result = nec data %end %routinespec intwait %routine wait(%integer mask,target) %cycle ipt = ipt+1 intwait %returnif nec csr&mask=target nec csr = clear done %repeatuntil kicked#0 state = state&16_ffff00ff+'#'<<8 %signal 9 %end %routine controller wait(%integer bc) state = 'CW+ ' bcr = bc board control = bc wait(128,0) board control = normal bcr = normal state = 'CW- ' %end %integerfn drive wait(%integer drive) %integer i state = 'DW+0'+drive %cycle bcr = intenable board control = intenable wait(16,16) nec csr = sense int controller wait(intenable) i = result %exitif i&7=drive wrong = wrong+1 %repeat state = 'DW-0'+drive %result=i %end %integerfn unit status(%integer drive) action = 'UST ' nec csr = sense unit+drive controller wait(intenable) action = blank %result = result<<8 %end %routine initialise controller %integer i,dtl=16_8000+bps action = 'INIT' bcr = board reset board control = board reset %for i=1,1,10000 %cycle; %repeat bcr = normal board control = normal %for i=1,1,10000 %cycle; %repeat parameter(16_40); !Mode parameter(dtl>>8); !DTLH parameter(dtl); !DTLL parameter(tpc-1); !ETN parameter(spt-1); !ESN parameter(16); !GPL2 parameter(10); !MGPL1 action = 'SPEC' nec csr = specify controller wait(intenable) action = 'POLL' i = drive wait(7) action = blank %end %owninteger ec=0,fec=0; ! Error count, Fatal error count %ownintegerarray curcyl(0:maxdrive) = -1(*) %owninteger curdrive = -1 %owninteger drive,cylinder,track,sector,disqaddress,errorcode %routine restore %integer x action = 'RST ' nec csr = recalibrate+drive x = drive wait(drive) action = blank %end %routine position head %integer x parameter(cylinder>>8) parameter(cylinder) action = 'SEK ' nec csr = seek+drive x = drive wait(drive) action = blank %end %routine fail(%integername lives,%integer code,operation) %owninteger e=0,f=0 ec = ec+1; e = e+1 pdate; printstring("*** Disk error "); printsymbol(operation) write(disqaddress>>lbps,6); printsymbol('b') write(cylinder,3); printsymbol('c') write(track,2); printsymbol('t') write(sector,2); printstring("s ") %unless code=-1 %start code = unit status(code&7)+code phex(code) printstring(" cb") %if code&16_80000000#0 printstring(" rrq") %if code&16_08000000#0 printstring(" ier") %if code&16_04000000#0 printstring(" nci") %if code&16_02000000#0 printstring(" drq") %if code&16_01000000#0 printstring(" enc") %if code&16_00800000#0 printstring(" ovr") %if code&16_00400000#0 printstring(" der") %if code&16_00200000#0 printstring(" eqc") %if code&16_00100000#0 printstring(" nr") %if code&16_00080000#0 printstring(" nd") %if code&16_00040000#0 printstring(" nwr") %if code&16_00020000#0 printstring(" mdm") %if code&16_00010000#0 printstring(" sel") %if code&16_00008000#0 printstring(" sen") %if code&16_00004000#0 printstring(" wpr") %if code&16_00002000#0 printstring(" rdy") %if code&16_00000800#0 printstring(" onc") %if code&16_00000400#0 printstring(" ser") %if code&16_00000200#0 printstring(" flt") %if code&16_00000100#0 printstring(" sen") %if code&16_00000080#0 printstring(" rc") %if code&16_00000040#0 printstring(" ser") %if code&16_00000020#0 printstring(" eqc") %if code&16_00000010#0 printstring(" nr") %if code&16_00000008#0 %finish errorcode = code lives = lives-1 initialise controller; restore; position head newline %andreturnunless lives<=0 fec = fec+1 printstring(" - fatal"); newline %signal 9 %if lives=0 %end %routine bulk move (%integer bytes,from,to) !Assume bytes is multiple of 4 and not more than 256k bytes = bytes>>1-1 {was bytes>>2-1} *move.l from,a0 *move.l to,a1 *move.l bytes,d0 loop: *move.w (a0)+,(a1)+ {was move.l} *dbra d0,loop %end %routine copy from(%integer userbuffer,bytes) bulkmove(bytes,userbuffer,disqbuffer) %unless userbuffer=disqbuffer %end %routine copy to(%integer userbuffer,bytes) bulkmove(bytes,disqbuffer,userbuffer) %unless userbuffer=disqbuffer %end %routine do(%integer op,bytes,da,ub) %integer target,sectors,max,size,lives=3 %integer st,h,f,c,t,s,n %cycle sectors = bytes>>lbps disqaddress = da sector = da>>lbps track = sector//spt cylinder = track//tpc drive = cylinder//cpd sector = rem(sector,spt) track = rem(track,tpc) cylinder = rem(cylinder,cpd) max = spt-sector; !Disallow head crossing max = 4096>>lbps %if max>4096>>lbps; !(Disk buffer size restriction) sectors = max %if sectors>max size = sectors<>8); !LCNH parameter(cylinder); !LCNL parameter(track); !LHN parameter(sector); !LSN parameter(sectors); !NSEC action = 'DMA ' neccsr = op+drive %if op=readdata %start controllerwait(dmain+intenable) %else controllerwait(dmaout+intenable) %finish action = blank st = neccsr; st = result<<16+st<<24 h = result; f = result; c = result; c = result+c<<8 t = result; s = result; n = result copyto(ub,size) %if op=readdata target = rem(track+(sector+sectors)//spt,tpc) target = (target!!t)!(track!!h)!f!n target = target!(rem(sector+sectors,spt)!!s) target = target!((cylinder+(track+(sector+sectors)//spt)//tpc)!!c) %if target#0 %or st&16_efff0000#16_40000000 %start ! %if op=writedata %then printsymbol('W') %c ! %elseif op=readdata %then printsymbol('R') %c ! %elseif op=verifydata %then printsymbol('V') %c ! %else printsymbol('?'); space ! fail(lives,st,'T') %if op = read data %then fail(lives, st, 'R') %c %else %if op = write data %then fail(lives, st, 'W') %c %else %if op = verify data %then fail(lives, st, 'V') %c %else fail(lives, st, '?') %if target#0 %start printstring("H="); write(h,0); printstring(" F="); write(f,0) printstring(" C="); write(c,0); printstring(" T="); write(t,0) printstring(" S="); write(sector,0); printstring(" N="); write(n,0) newline %finish %continue %finish ub = ub+size; da = da+size; bytes = bytes-size %repeatuntil bytes=0 %end %constinteger dwrite=1,dread=2,dverify=4 %integerfn xtransfer(%integer func,bytes,disqaddr,%integername buf) %constinteger signbit = \((-1)>>1) %integer lives=0 %onevent 9 %start kicked = 0 %and curdrive = -1 %unless kicked=0 lives = lives-1 %result = signbit!errorcode %finish fail(lives,-1,'A') %andresult = -1 %unless disqaddr&(1<maxipt minipt = ipt %if ipt>i&255) %for i = 24,-8,0 %end %externalroutine show disq status pdate printstring("Disk status: Co="); write(count,0) printstring(" By="); write(xn,0) printstring(" Bl="); write(xa>>9,0) %unless xa&511=0 %start printsymbol('.'); write(xa&511,0) %finish printstring(" Bu="); phex(xm) printstring(" Op="); write(xf,0) printstring(" BCR="); phex4(board control) printstring(" SB="); phex4(bcr) printstring(" CSR="); phex2(nec csr) newline pdate pw(action); pw(state); printstring(" Wrong="); write(wrong,0) printstring(" min/max/ipt: "); write(minipt,0) write(maxipt,1); write(ipt,1); newline; minipt=16_7fffffff; maxipt = 0 %end %externalroutine kick disq kicked = 1 interrupt register = 1 %end %externalintegermap transfer(%integer f,n,a,%integername m) %owninteger started=0 started = 1 %and startup %if started=0 %if count=0 %start pdate; printstring("*** Disq request while driver busy"); newline %while count=0 %cycle; %repeat %finish count = 0; xm = addr(m); xa = a; xn = n; xf = f accepted = 0 %cycle interrupt register = 1 %result == count %unless accepted=0 %repeat %end %endoffile