.z80 .lall title 'TEAC tape unit diagnostic' ;**************************************************** ;** ;** teac tape drive diag for ampro ;** ;** by: Barry Harding ;** date: 10/27/86 ;**************************************************** false equ 0 true equ not false boot equ 0 bdos equ 5 tapid equ 040h cr equ 0dh lf equ 0ah MAIN:: ;********************************* ; print sign on ;********************************* main1:: ld de,sign ld c,09h call bdos ;********************************* ; cmd loop ;********************************* mloop:: ld de,msg1 ;print help msg ld c,9 call bdos ;********************************* ; get cmd char ;********************************* ld c,1 call bdos ;********************************* ; do command ;********************************* cp 't' ;test ready jr z,testr cp 'T' ;test ready jr z,testr cp 's' ;drive sens jp z,sens cp 'S' ;drive sens jp z,sens cp 'r' ;rewind drive jp z,rewind cp 'R' ;rewind drive jp z,rewind cp 'i' ;read blk jp z,read cp 'I' ;read blk jp z,read cp 'o' ;write blk jp z,write cp 'O' ;write blk jp z,write cp 'p' ;prewind tape jp z,prewind cp 'P' ;prewind tape jp z,prewind cp 'e' ;erase tape jp z,extend cp 'E' ;erase tape jp z,extend cp 'f' ;wrt file mark jp z,filem cp 'F' ;wrt file mark jp z,filem cp 'b' ;skip # blks jp z,blocks cp 'B' ;skip # blks jp z,blocks cp 'n' ;skip # files jp z,nextf cp 'N' ;skip # files jp z,nextf cp 'l' ;wrt # blks jp z,lwrite cp 'L' ;wrt # blks jp z,lwrite cp 'v' ;read # blks jp z,lread cp 'V' ;read # blks jp z,lread cp 'c' ;warm boot jp z,boot cp 'C' ;warm boot jp z,boot jp main1 ;unknown so print help ;********************************* ; test if drive ready ;********************************* testr:: call wready ;is drv ready push af ld de,msg2 ld c,9 call bdos pop af push af call error1 pop af or a jr z,isread ;********************************* ; drive not ready ;********************************* ld de,notread ld c,9 call bdos jp mloop ;********************************* ; drive is ready ;********************************* isread:: ld de,isok ld c,9 call bdos jp mloop ;********************************* ; ask number of blocks to skip ;********************************* blocks: ld de,blknum call print ;display question call inhexw ;input hex number push af ld de,crlf call print ;end with cr lf pop af or a ;if no hex input then do not ;do skip just return jp z,mloop ld a,l ld (blks),a call blkspac ;do the skip jp mloop ;********************************* ; skip files ;********************************* nextf:: ld de,blknum1 call print ;display question call inhexw ;get answer push af ld de,crlf ;do cr lf call print pop af or a ;if no hex just return jp z,mloop ld a,l ld (blks1),a call blkspc1 ;do file skip jp mloop ;********************************* ; do sens status ;********************************* sens:: ld de,crlf call print call werror cp 1 jr z,senserr call dispsens jp mloop senserr:: ld de,err1 ld c,9 call bdos jp mloop ;********************************* ; rewind tape ;********************************* rewind:: ld de,remsg ;ask question call print ld de,inbuf ld c,0ah call bdos ;get text respons ld a,(chin) cp 'y' jr z,imed cp 'Y' jr z,imed cp 'q' jp z,mloop cp 'Q' jp z,mloop ;********************************* ; do not return imed (wait for rewind completion) ;********************************* xor a ld (imdre),a jr re1 ;********************************* ; do return imed ;********************************* imed:: ld a,1 ld (imdre),a re1:: call drewind ;do the rewind jp z,mloop ld de,reerr call print jp mloop ;********************************* ; erase tape ;********************************* extend:: ld de,eremsg ;ask question call print ld de,inbuf ld c,0ah call bdos ;get respons ld a,(chin) cp 'y' jr z,eimed cp 'Y' jr z,eimed cp 'q' jp z,mloop cp 'Q' jp z,mloop ;********************************* ; do not return until done ;********************************* xor a ld (eimdre),a jr ere1 ;********************************* ; do return before done ;********************************* eimed:: ld a,1 ld (eimdre),a ere1:: call derase ;do the erase jp z,mloop ld de,eeerr call print jp mloop ;********************************* ; wrt file mark ;********************************* filem: call dfilem jp z,mloop ld de,feerr call print jp mloop ;********************************* ; read a blk ;********************************* read:: ld hl,dbuff call wread jp z,mloop ld de,readerr call print jp mloop ;********************************* ; read # blks ;********************************* lread:: ld de,numsg ;ask how many blks call print call inhexw ;get respons push hl pop bc or a jr nz,lrlop ld bc,2000h ;dedualt to 0x2000 lrlop: push bc ld hl,dbuff call wread ;read 1 blk pop bc jp nz,lerr1 push bc ld de,cro call print pop bc push bc push bc pop hl call error2 ;print current blk # pop bc dec bc ld a,b ;dec and loop on next blk or c jr nz,lrlop jp mloop ;********************************* ; read blk error ;********************************* lerr1: ld de,readerr call print jp mloop ;********************************* ; wrt a blk ;********************************* write:: ld hl,dbuff call wwrite jp z,mloop ld de,wrterr call print jp mloop ;********************************* ; wrt # blks ;********************************* lwrite:: ld de,numsg ;ask how many call print call inhexw ;get respons push hl pop bc or a jr nz,lwlop ;no input then ld bc,2000h ;default lwlop: push bc ;loop on # blks ld hl,dbuff call wwrite ;do 1 blk pop bc jp nz,lwerr1 push bc ld de,cro call print pop bc push bc push bc pop hl call error2 ;get blk # pop bc dec bc ld a,b or c jr nz,lwlop jp filem ;write file mark lwerr1: ld de,wrterr ;loop wrt error call print jp mloop ;********************************* ; prewind tape ;********************************* prewind:: ld de,premsg ;ask qust call print ld de,inbuf ld c,0ah call bdos ;get respons ld a,(chin) cp 'y' jr z,pimed cp 'Y' jr z,pimed cp 'q' jp z,mloop cp 'Q' jp z,mloop xor a ;do not return until done ld (pimdre),a jr pre1 pimed:: ld a,1 ;return imead ld (pimdre),a pre1:: call dprewind ;do the work jp z,mloop ld de,preerr call print jp mloop ;********************************* ; all thats fit to print ;********************************* numsg: db cr,lf,' number of blocks ?$' cro: db cr,'$' blknum: db cr,lf,'number of blocks to skip ?$' blknum1: db cr,0AH,'number of file marks to skip ?$' wrterr:: db cr,lf,'write error',cr,lf,'$' readerr:: db cr,lf,'read error',cr,lf,'$' eeerr:: db cr,lf,'erase error',cr,lf,'$' feerr:: db cr,lf,'write file mark error',cr,lf,'$' reerr:: db cr,lf,'rewind error',cr,lf,'$' remsg:: db cr,lf,'return from rewind imed y/n/q $' eremsg:: db cr,lf,'return from erase imed y/n/q $' premsg:: db cr,lf,'return from prewind imed y/n/q $' preerr:: db cr,lf,'prewind error',cr,lf,'$' msg1:: db cr,lf,'CMD>$' msg2: db cr,lf,'READY STATUS---> $' msg3: db ' valid$' msg4: db ' filemark$' msg5: db ' eom$' msg6: db ' no-error$' msg7: db ' no-cassette$' msg8: db ' med-error$' msg9: db ' hardware-error$' msg10: db ' illegal-request$' msg11: db ' unit-attention$' msg12: db ' data-protect$' msg13: db ' no-data$' msg14: db ' volume-overflow$' msg15: db ' stall$' msg16: db ' hole$' msg17: db ' parity$' msg20: db ' cld$' msg21: db ' wpt$' msg22: db ' bom$' msg23: db ' run$' msg24: db ' strm$' msg25: db 'error count $' msg26: db 'repos count $' msg27: db 'track $' msg28: db 'address $' err1:: db 'sens error',cr,lf,'$' sign:: db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf db 'TEAC TAPE TESTER V1.0',cr,lf db 'By: Barry Harding',cr,lf,lf db 'T - test drive ready',cr,lf db 'S - sens status',cr,lf db 'R - rewind',cr,lf db 'I - read tape block',cr,lf db 'O - write tape block',cr,lf db 'P - prewind tape',cr,lf db 'E - erase tape',cr,lf db 'F - wrt file mark',cr,lf db 'B - blks to skip',cr,lf db 'N - files to skip',cr,lf db 'L - write 2000 blk tape',cr,lf db 'V - werify 2000 blk tape',cr,lf db 'C - exit to cpm' crlf:: db cr,lf,'$' notread:: db ' <--- TAPE NOT READY',cr,lf,'$' isok:: db ' <--- TAPE IS READY',cr,lf,'$' ;********************************* ; bdos buffered key input ;********************************* inbuf:: db 80 db 00 chin:: ds 83 ;********************************* ; tape xfer buffer ;********************************* dbuff:: ds 512*20 ;********************************* ; scsi status ;********************************* wstat:: db 00h ;********************************* ; display sens data ;********************************* dispsens:: ld hl,endstat ld a,(hl) ;get valid push hl call error1 pop hl bit 7,(hl) jr z,noval ld de,msg3 call print noval: ld de,crlf call print inc hl ld a,(hl) push hl call error1 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 pop hl bit 7,(hl) jr z,nofmk ld de,msg4 call print nofmk: bit 6,(hl) jr z,noeom ld de,msg5 call print noeom: ld a,(hl) and 0fh cp 0 jr nz,notsen ld de,msg6 call print notsen: cp 2 jr nz,notcass ld de,msg7 call print notcass: cp 3 jr nz,nomed ld de,msg8 call print nomed: cp 4 jr nz,nohard ld de,msg9 call print nohard: cp 5 jr nz,noill ld de,msg10 call print noill: cp 6 jr nz,noatt ld de,msg11 call print noatt: cp 7 jr nz,noprot ld de,msg12 call print noprot: cp 8 jr nz,nonodat ld de,msg13 call print nonodat: cp 0dh jr nz,noover ld de,msg14 call print noover: ld de,crlf call print inc hl ld a,(hl) push hl call error1 ;byte 3 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 ;byte 4 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 ;byte 5 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 ;byte 6 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 ;byte 7 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 pop hl bit 2,(hl) jr z,nosta ld de,msg15 call print nosta: bit 1,(hl) jr z,nohol ld de,msg16 call print nohol: bit 0,(hl) jr z,nopar ld de,msg17 call print nopar: ld de,crlf call print ld de,crlf call print inc hl ld a,(hl) push hl call error1 pop hl ld de,crlf call print inc hl ld a,(hl) push hl call error1 pop hl bit 7,(hl) jr z,nocld ld de,msg20 call print nocld: bit 6,(hl) jr z,nowpt ld de,msg21 call print nowpt: bit 5,(hl) jr z,nobom ld de,msg22 call print nobom: bit 4,(hl) jr z,norun ld de,msg23 call print norun: bit 3,(hl) jr z,nostrm ld de,msg24 call print nostrm: ld de,crlf call print ld de,msg25 call print inc hl ld d,(hl) inc hl ld e,(hl) push hl push de pop hl call error2 pop hl ld de,crlf call print ld de,msg26 call print inc hl ld d,(hl) inc hl ld e,(hl) push hl push de pop hl call error2 pop hl ld de,crlf call print ld de,msg27 call print inc hl ld a,(hl) push hl call error1 pop hl ld de,crlf call print ld de,msg28 call print inc hl ld d,(hl) inc hl ld e,(hl) push de pop hl call error2 ld de,crlf call print ret ;********************************* ; ; print string ; ;********************************* print:: ld c,9 push hl push af call bdos pop af pop hl ret ;********************************* ; ; inhexw ; ; input 4 hex chars ; ; hl = number ; a = # of chars inputed ; ;********************************* ccoun:: db 00h inhexw:: ld a,0 ld (ccoun),a ld hl,0 inlop:: push hl ld c,01h call bdos pop hl cp '0' jr c,donehi cp '9'+1 jr nc,alphi innum:: sub '0' add hl,hl add hl,hl add hl,hl add hl,hl add a,l ld l,a ld a,(ccoun) inc a ld (ccoun),a cp 4 jr c,inlop ret alphi:: cp 'a' jr c,donehi cp 'f'+1 jr nc,donehi sub 'a'-0ah add hl,hl add hl,hl add hl,hl add hl,hl add a,l ld l,a ld a,(ccoun) inc a ld (ccoun),a cp 4 jr c,inlop ret donehi:: ld a,(ccoun) ret ;********************************* ; ; error ; ; de = msg to output ; a = number to output ; ; error1 ; ; a = number to output ; ; error2 ; ; hl = number to output ; ;********************************* error:: push af ld c,9 call bdos pop af error1:: push af rrca rrca rrca rrca call hexot pop af hexot:: and 0fh add a,'0' cp '9'+1 jr c,prt add a,07h prt:: ld c,02h ld e,a call bdos ret error2: ld a,h push hl call error1 pop hl ld a,l call error1 ret ;********************************* ; ; wready ; ;********************************* wready:: ld hl,rdycmd ld de,dbuff ld a,tapid call scsi and 3h ret rdycmd:: db 00h db 00h db 00h db 00h db 00h db 00h ;********************************* ; ; rewind ; ;********************************* drewind:: ld hl,rwdcmd ld de,dbuff ld a,tapid call scsi and 3h ret rwdcmd:: db 01h imdre: db 00h db 00h db 00h db 00h db 00h ;********************************* ; ; blkspac ; ;********************************* blkspac:: ld hl,blkcmd ld de,dbuff ld a,tapid call scsi and 3h ret blkcmd:: db 011h db 00h db 00h db 00h blks: db 00h db 00h ;********************************* ; ; blkspac ; ;********************************* blkspc1:: ld hl,blkcmd1 ld de,dbuff ld a,tapid call scsi and 3h ret blkcmd1: db 011h db 01h db 00h db 00h blks1: db 00h db 00h ;********************************* ; ; erase ; ;********************************* derase:: ld hl,eracmd ld de,dbuff ld a,tapid call scsi and 3h ret eracmd:: db 02h eimdre: db 00h db 00h db 00h db 00h db 00h ;********************************* ; ; dfilem ; ;********************************* dfilem:: ld hl,wfmcmd ld de,dbuff ld a,tapid call scsi and 3h ret wfmcmd:: db 010h db 00h db 00h db 00h db 01h db 00h ;********************************* ; ; prewind ; ;********************************* dprewind:: ld hl,prwdcmd ld de,dbuff ld a,tapid call scsi and 3h ret prwdcmd:: db 01bh pimdre: db 00h db 00h db 00h db 03h db 00h ;********************************* ; ; wread ; ;********************************* wred:: db 08h db 01h db 0 db 0 db 20 db 0 wread:: ld hl,wred ld de,dbuff ld a,tapid call scsi errd:: and 03h ;Was there an error ret xor a ret ;********************************* ; ; werror ; ;We still seem to have control over the scsi ;port so just return error code ; ;Get error status from scsi port ;********************************* werror:: ld hl,statcmd ;This is comp of cmd 3 ld de,endstat ld a,tapid call scsi and 03h jr nz,wferror ;Get error status from scsi port ld hl,astatcmd ;This is comp of cmd 3 ld de,aendstat ld a,tapid call scsi and 03h jr nz,wferror xor a ret statcmd:: db 03h db 00h db 00h db 00h db 9 db 00h astatcmd:: db 06h db 00h db 00h db 00h db 9 db 00h endstat:: db 0 ;valid db 0 ;fill db 0 ;sense db 0 ;info msb db 0 ;info db 0 ;info db 0 ;info lsb db 0 ;fill db 0 ;hardware aendstat:: db 0 ;valid db 0 ;fill db 0 ;sense db 0 ;info msb db 0 ;info db 0 ;info db 0 ;info lsb db 0 ;fill db 0 ;hardware ;********************************* ; ; wferror ; ;********************************* wferror:: xor a inc a ret ;********************************* ; ; wwrite ; ;********************************* wwrite:: ld hl,wwrt ld de,dbuff ld a,tapid call scsi erwrt:: and 03h ;Was there an error ret wwrt:: db 0ah db 01h db 00h db 00h db 20 db 00h ncrcsd equ 20h ncrodr equ 20h ncricr equ 21h ncrmr equ 22h ncrtcr equ 23h ncrcsbs equ 24h ncrser equ 24h ncrbsr equ 25h ncrsds equ 25h ncridr equ 26h ncrsdtr equ 26h ncrrpi equ 27h ncrsdir equ 27h ncrdack equ 28h ;********************************* ; ; scsi ncr interface ; ;entry: ; a = target address ; hl = point to scsi cmd ; de = point to data block ;exit: ; a = 0 ok (sets zero) ; a = 0ffh scsi timeout ; a = teac error ;********************************* scsi:: ld (target),a ;save scsi device id ;save block pointers cmd/data ld (cmd.ptr),hl ;save cmd ld (dat.ptr),de ;save data ;do the IO call select ;start io ld a,(status) ;get exit status or a ret ;********************************* ; ;start IO here ; ;This is a state machine which is driven ;by the NCR chip. We could be here for a ;short period or for ever depending on the ;SCSI chip ; ;clear NCRs idea of the scsi state ;********************************* select:: xor a out (ncricr),a ;state of buss out (ncrtcr),a ;what buss should be cleararbit: xor a ;clear ncr mode out (ncrmr),a in a,(ncrrpi) ;reset ncr interrupts ld a,(target) ;put address on buss out (ncrodr),a in a,(ncricr) ;turn on data buss or 01h out (ncricr),a ld a,05h ;put select on buss out (ncricr),a ld bc,6000h ;delay untill busy stim: in a,(ncrcsbs) ;check for busy and 040h ;mask busy jp nz,selectok dec c jp nz,stim dec b jp nz,stim xor a ;buss timeout out (ncrodr),a dec a ld (status),a jp alldone selectok: xor a alldone: ;check for timeout error ld b,a ;save status ld a,01h out (ncricr),a xor a out (ncricr),a ;clear data buss ld a,b or a ret nz dec a ld (status),a ld a,06h ;set dma mode and mointer busy out (ncrmr),a scsirdy: in a,(ncrbsr) ;check ncr status after select and 10h ;check for interrupt jr nz,scsiint in a,(ncrcsbs) and 20h ;check for scsi req jr z,scsirdy jp phase ;go to state look up ;********************************* ;this is the interrupt code ;********************************* scsiint: xor a out (ncricr),a ;free data buss in a,(ncrbsr) ;check for interrupt and 0ch jr nz,scsiexit ;********************************* ;this is the start of the code that switch phases ;********************************* phase: xor a out (ncrmr),a in a,(ncrrpi) ;reset ints ld a,06h out (ncrmr),a ;set dma and mointer busy in a,(ncrcsbs) ;update phase and 1ch ;mask used bits rra ld e,a rra out (ncrtcr),a ;update expected phase ld d,0 ;look up phase and jump to it ld hl,phasetable add hl,de ld a,(hl) inc hl ld h,(hl) ld l,a ld d,40h jp (hl) phasetable: dw phase0 dw phase1 dw phase2 dw phase3 dw phase4 dw phase5 dw phase6 dw phase7 phase0: ld hl,(dat.ptr) ;data out phase ld e,1 jp wscsi phase1: ld hl,(dat.ptr) ;data in phase ld e,1 jp rscsi phase2: ld hl,(cmd.ptr) ;command out phase ld e,1 jp wscsi phase3: ld hl,status ;status in phase ld e,1 jp rscsi phase7: ld hl,message ;message phase ld e,1 jp rscsi phase4: ;bad phases phase5: phase6: scsiexit: xor a out (ncrtcr),a out (ncrmr),a in a,(ncrrpi) ret ;general scsi write code wscsi: ld a,01h ;assert data buss out (ncricr),a ld c,ncrdack out (ncrsds),a ;start dma wscsi1: in a,(ncrbsr) ;check for dma req ld b,a and d jr z,wscsi2 ;no dma now ld b,e ;do io otir jp wscsi1 wscsi2: ld a,b ;check for interrupt and 10h jp z,wscsi1 jp scsiint rscsi: ld c,ncrdack ;general scsi read out (ncrsdir),a ;start dma read rscsi1: in a,(ncrbsr) ;wait for dma ld b,a and d jr z,rscsi2 ;no dma now ld b,e ;do the io inir jp rscsi1 rscsi2: ld a,b ;check for interrupt and 10h jp z,rscsi1 ;no ints now jp scsiint target: db 0 status: db 0 message: db 0 cmd.ptr: dw 0 dat.ptr: dw 0 end MAIN