***************************************************************** * * * Disk Jockey 2D firmware revision 3.1 and 4.0 * * By George Morrow * * * * The following firmware is loaded into memory and then moved * * into the controller ram. * * * ***************************************************************** origin equ $-400h rom equ origin ram equ origin+400h IO EQU ROM+3f8h UDATA EQU IO DCMD EQU IO+1 DSTAT EQU DCMD DREG EQU IO+2 USTAT EQU DREG CMDREG EQU IO+4 CSTAT EQU CMDREG TRKREG EQU IO+5 SECREG EQU IO+6 DATREG EQU IO+7 * * RCMD EQU 200Q WCMD EQU 240Q HEAD EQU 4 LOAD EQU 20Q DENSTY EQU 1 ULOAD EQU 30Q RSTBIT EQU 4 ACCESS EQU 2 READY EQU 40Q INDEX EQU 20Q RACMD EQU 304Q CLRCMD EQU 320Q SVCMD EQU 35Q SKCMD EQU 30Q HCMD EQU 11Q ISTAT EQU 4 OSTAT EQU 10Q DSIDE EQU 10Q TZERO EQU 4 MDINT EQU 3 LIGHT EQU 36Q NOLITE EQU 76Q * * DBOOT JMP BOOT TERMIN JMP origin+3 TRMOUT JMP origin+6 TKZERO JMP HOME TRKSET JMP SEEK SETSEC JMP SECSET SETDMA JMP DMA DREAD JMP READ DWRITE JMP WRITE SELDRV JMP DRIVE TPANIC JMP origin+1eh TSTAT JMP origin+21h DMAST JMP DMSTAT STATUS JMP DISKST DSKERR JMP ROM+52Q SETDEN JMP DENFIX SETSID JMP SIDEFX * * BOOT mov a,c sta disk sta bdisk mvi a,7fh dsrt rlc dcr c jp dsrt sta drvsel sta bdrvsel call fixio lda io-4 ;Test for Model A or B cpi (ret) jz modela lxi d,origin lxi h,ram mvi c,boot-dboot ;Copy prom jump table into ram call modelm mvi a,7fh call sdsel mvi a,clrcmd sta cmdreg lda bdrvsel ori 60h ani 7fh call sdsel mvi a,9h call scbits mvi a,(jz) sta indx1 sta indx3 mvi a,(jnz) sta indx2 call measur xchg shld btimer lxi d,btble lxi h,origin+7e3h mvi c,23 modelm ldax d mov m,a inx d inx h dcr c jnz modelm ret btble db 0 btimer dw 1800h,0 db 8,0 bdrvsel db 7eh bdisk db 0,8,0,9,0ffh,9,0ffh,9,0ffh,9,0ffh,9,0,1,0 fixio LHLD ROM+7 ;find the 2nd INX H ; byte of input routine LXI D,4 ;offset MOV A,M ;get addr of USTAT LXI H,SDSEL+1 ;I/O routines MOV M,A ;store USTAT addr DAD D ;increment mem addr MOV M,A ;store USTAT addr DAD D ;increment mem addr XRI 3 ;switch the addr MOV M,A ;store DSTAT addr DAD D ;increment mem addr MOV M,A ;store DATAT addr DAD D ;increment mem addr MOV M,A ;store DSTAT addr ret modela mvi a,3 call scbits MVI A,CLRCMD ;1791 reset STA CMDREG ; command lda drvsel ;initialize 1791 call sdsel ; control bits call measur xchg SHLD TIMER RET * * DISKST LDA SECREG ;get current MOV B,A ; sector no in B LDA TRKREG ;get current MOV C,A ; track no in C LDA DCREG ;get current CMA ; density in ANI 1 ; the msb RRC ;position MOV D,A ;save in D LDA SIDE ;put the RLC ; side RLC ; select RLC ; flag ADD D ; in bit MOV D,A ; position 6 LDA SECLEN ;put the RLC ; sector length RLC ; code Ð bits ADD D ; 2 & 3 MOV D,A LDA CDISK ;put the current ADD D ; disk no in bits RET ; 0 & 1 * * DMSTAT PUSH H ;save the H-L pair LHLD DMAADR ;H-L pain MOV B,H ;move the DMA MOV C,L ;addr to B-C POP H ;recover H-L RET * * DRIVE MVI A,374Q ;test for the ADD C ; new drive number MVI A,20Q ;less than 4 RC MOV A,C ;store the new STA DISK ;drive in DISK RET * * DMA LXI H,ROM ;test the call neghl lxi d,8 dad d DAD B ; DMA address JNC DMASET ; for conflict LXI H,RAM ; with the I/O call neghl DAD B ; on the DJ/2D JC DMASET ;controller STC MVI A,20Q RET neghl mov a,h cma mov h,a mov a,l cma mov l,a inx h ret DMASET MOV H,B ;get the DMA addr MOV L,C ;to the H-L par SHLD DMAADR ;store XRA A ;clear the error RET ; flag and return * * HOME call hdload ;load the head rc ;not ready error call hentry ;move the head PUSH PSW ;save the flags SBB A ;update the STA TRACK ; track sta trkreg ; registers xra a ;set the not sta tzflag ; verified flag JMP LEAVE+1 ;unload the head HENTRY XRA A ;update STA HDFLAG ; flags LXI H,0 ;time out constant MVI A,HCMD ;do the home CALL CENTRY ; command ANI TZERO ;track zero bit RNZ STC ;error flag RET * * SECSET XRA A ;test for ORA C ; sector zero STC ;error flag RZ MOV A,C ;test for CPI 27 ; sector CMC ;too large RC STA SECTOR ;save RET * * SEEK MOV A,C ;test for CPI 77 ; track CMC ; too large RC STA TRACK ;save RET * * issue sta ecount+1 ;update count call measur ;find the index mvi c,1 ;start w/sector 1 isloop mov a,c ;initialize the sta secreg ; sector register lda sector ;test for cmp c ; target sector rz mvi a,rcmd ;do a fake call comand ; read command jc pleave ;abort on error inr c ;increment sector no. jmp isloop comndp sta cmdreg ;do the command mov c,b ;initialize block count lxi d,datreg ;data register lhld dmaadr ;transfer address ret write CALL PREP ;prepare for write jc leave ;abort operation wrentry mvi a,wcmd ;start a write call comndp ; sector operation wrloop mov a,m ;load 1st byte of data inx h ;advance pointer stax d ;write 1st byte of data mov a,m ;load 2nd byte of data inx h ;advance pointer stax d ;write 2nd byte of data mov a,m ;load 3rd byte of data inx h ;advance pointer stax d ;write 3rd byte of data dcr c ;reduce block count mov a,m ;load 4th byte of data inx h ;advance pointer stax d ;write 4th byte of data jnz wrloop ;write next 4 bytes lxi h,wrentry ;return entry address jmp cbusy read call prep ;prepare for read jc leave ;abort operation rdentry mvi a,rcmd ;start a read call comndp ; sector operation rdloop ldax d ;read 1st byte mov m,a ;store 1st byte inx h ;advance pointer ldax d ;read 2nd byte mov m,a ;store 2nd byte inx h ;advance pointer ldax d ;read 3rd byte mov m,a ;store 3rd byte inx h ;advance pointer dcr c ;reduce block count ldax d ;read 4th byte mov m,a ;store 4th byte inx h ;advance pointer jnz rdloop ;read next 4 bytes lxi h,rdentry ;return entry address CBUSY push h ;save return address lxi h,cstat ;wait for the 1791 call busy ; to finish command ani 137Q ;error bit mask jz leave-1 ; test cpi 10h ;premature interrupt jnz pleave ;other error type lda ecount ;decrement error dcr a ; count number 1 jm stest ;hard interrupt error sta ecount ;update count ret ;do operation over stest lda ecount+1 ;decrement error dcr a ; count number 2 jp issue ;issue a command mvi a,10h ;irrecoverable error pleave stc ;error flag pop h ;adjust the stack LEAVE PUSH PSW ;save the flags LDA DCREG ;1791 control bits XRI LOAD ;toggle the CALL SCBITS ; head load bits POP PSW ;recover the flags RET * * PREP CALL HDLOAD ;load the head RC ;disk not ready? LDA TRKREG ;get the old trk INR A ;test for head CZ HENTRY ; not calibrated rc ;seek error? LXI H,TRKREG ;present trk LDA TRACK ;the new track CMP M ;test for head motion INX H ;advance to the INX H ; data register MOV M,A ;save the new trk MOV A,C ;turn off data CALL SCBITS ; access control bit JZ TVERFY ;test for seej XRA A ;force a read STA HDFLAG ; header operation CALL LDSTAT ;get the ANI DSIDE ; double RAR ; RAR ; flag RAR ; to do 3 ms ADI SKCMD ; step operation LXI H,0 ;do a seek CALL CENTRY ; command JC SERROR ;seek error? TVERFY LDA HDFLAG ;get the force ORA A ; verify track flag JNZ CHKSEC ;no seek & head OK MVI B,2 ;verify retry no SLOOP MVI A,SVCMD ;do a verify CALL COMAND ; command ANI 231Q ;error bit mask mov d,a ;save JZ RDHDR ;no error LDA DCREG ;1791 control reg XRI DENSTY ;flip the density bit STA DCREG ;update XRI ACCESS CALL SCBITS ;change density DCR B ;dec retry count JNZ SLOOP ; and try again mov a,d ;restore error bits SERROR stc ;error flag push psw ;save the status call hentry ;seek to track 0 pop psw ;recover errors ret RDHDR MVI B,12Q ;number of retrys RHLOOP LXI D,DATREG ;data register LXI H,TRACK+1 ;storage area MVI A,RACMD ;do the read STA CMDREG ; header command RHL1 LDAX D ;get a data byte MOV M,A ;store in memory INR L ;inc mem pointer JNZ RHL1 ;test for more data LXI H,CSTAT ;wait for 1791 CALL BUSY ;to finish cmd ORA A ;test for errors JZ CHKSEC ;transfer OK? DCR B ;dec retry count JNZ RHLOOP ;test for JMP SERROR ; hard error CHKSEC LDA SECLEN ;get the sector MOV C,A ; size and setup MVI B,0 ; the offset LXI H,STABLE ;sec size tbl DAD B ;add the offset LDA SECTOR ;get the sector MOV B,A ;save in B ADD M ;compare w/table entry MVI A,20Q ;error flag RC ;error return MOV A,B ;save the sector STA SECREG ; in sector reg mvi a,40q ;128 byte sector lxi h,505h ;initialize shld ecount ; error counts SZLOOP DCR C ;reduce size count MOV b,a ;sector size to b rm ;return on minus ral ;double the count ora a ;clear the carry JMP SZLOOP * * SIDEFX MOV A,C ;get the side bit ANI 1 ;trim excess bits RAL ;move the bit RAL ; to the side RAL ; select bit RAL ; position STA SIDE ;save RET TOEND * * DS 300h-TOEND+DBOOT-66Q DS 25Q * * STACK * * STABLE DB 345Q DB 345Q DB 360Q DB 367Q * * ecount dw 0 ;error count cells TIMER DW 3000h ;head load time DMAADR DW 200Q ;dma address HDFLAG DB 0 ;read header flag DRVSEL DB 376Q ;drive select constant DISK DB 0 ;new drive CDISK DB 10Q ;current drive TZFLAG DB 0 ;track zero indicator D0PRAM DB 3 ;drive 0 parameters D0TRK DB 377Q ;drive 0 track no D1PRAM DB 3 ;drive 1 parameters D1TRK DB 377Q ;drive 1 track no D2PRAM DB 3 ;drive 2 parameters D2TRK DB 377Q ;drive 2 track no D3PRAM DB 3 ;drive 3 parameters D3TRK DB 377Q ;drive 3 track no DCREG DB 3 ;current parameters SIDE DB 0 ;new side select SECTOR DB 3 ;new sector TRACK DB 0 ;new track TRKNO DB 0 ;disk SIDENO DB 0 ; sector SECTNO DB 0 ; header SECLEN DB 0 ; data CRCLO DB 0 ; buffer CRCHI DB 0 * * HDLOAD LXI H,DISK MOV C,M ;new disk no to C INX H MOV E,M ;current disk to E MOV M,C ;update current disk INX H ;addr of disk table MOV A,E ;test for CMP C ; disk change MOV A,M ;head load flag MVI M,HEAD ;update head load INX H ;addr of disk table JZ HDCHK ;no disk change? PUSH H ;save table address MVI D,0 ;set up the MOV B,D ; offset address DAD D ;get the current DAD D ; disk parameters LDA DCREG ;save the MOV M,A ;density info INX H ;current track LXI D,TRKREG LDAX D ;get current trk MOV M,A ;save POP H ;recover tbl addr DAD B ;add the DAD B ; offset MOV A,M ;get control bits STA DCREG ;update DCREG INX H ;get the old MOV A,M ;track number STAX D ;and update 1791 MVI A,177Q ;disk select bits DSROT RLC ;rotate to DCR C ; select the JP DSROT ; proper drive STA DRVSEL ;save XRA A ;force head load HDCHK CALL LOADS ;test for ANA M ; head loaded STA HDFLAG ;save the head PUSH PSW ; loaded status LDA DRVSEL ;get current drive MOV C,A ;save LDA SIDE ;get current side CMA ;and merge ANA C ; with drive select CALL SDSEL ;select drive & side LDA DCREG ;1791 control bits MOV C,A ;save LDA TRACK ;get the new trk SUI 1 ;force single SBB A ; density DCR A ; if track = 0 CMA ;compliment ORA C ;merge w/control bits MOV M,A ;set 1791 control XRI ACCESS ;toggel access bit MOV C,A ;save PREP routine POP PSW ;head load status JNZ RDYCHK ;conditionally PUSH H ; wait for head LHLD TIMER ; load time out TLOOP DCX H ;count down MOV A,H ; 40 ms for ORA L ; head load JNZ TLOOP ; time out POP H ;disk status addr RDYCHK MOV A,M ;test for ANI READY ; disk ready RZ UNLOAD LDA DCREG ;force a ORI ULOAD ; head MOV M,A ; unload MVI A,200Q ;set disk STC ; not ready RET ; error flag * * COMAND LHLD TIMER ;get index count DAD H ; and multiply DAD H ; by four CENTRY XCHG ;save in D-E pair LXI H,CSTAT ;issue command MOV M,A ;to the 1791 NBUSY MOV A,M ;wait RAR ; for the JNC NBUSY ; busy flag BUSY MOV A,M ;test for RAR ; device busy MOV A,M ;restore status RNC ;return if not busy DCX D ;test for MOV A,D ; two disk ORA E ; revolutions JNZ BUSY ;47 machine cycles mov e,m ;save error code PUSH H ;save cmd address INX H ;track register MOV D,M ;save present track xthl ;recover cmd reg. push d ;save status xchg ;adjust registers call loads ;get control reg LDA DCREG ;1791 control bits xri RSTBIT ;reset the 1791 mov m,a ; controller to xri rstbit ; clear fault xchg ;adjust registers stax d ;start controller MVI M,CLRCMD ;force an interrupt pop d ;recover status POP H ;recover track reg mov m,d ;restore track mov a,e ;restore error code STC ; error flag RET * * MEASUR LXI D,0 ;initialize count CALL LOADS ;status port MVI C,INDEX ;index bit flag INDXHI MOV A,M ;wait for ANA C ; index indx1 JNZ INDXHI ; pulse low INDXLO MOV A,M ;wait for ANA C ; index indx2 JZ INDXLO ; pulse high INDXCT INX D ;advance count XTHL ;four XTHL ; dummy XTHL ; instructions XTHL ; for delay MOV A,M ;wait ANA C ; for next indx3 JNZ INDXCT ; low index RET ;98 machine cycles * * DENFIX MOV A,C ;trim excess ANI 1 ; bits, CMA ; compliment MOV B,A ; B and save LXI H,DISK ;new disk MOV E,M ;get disk no MVI D,0 ;offset addr INX H ;current disk MOV A,M ;move to ACC XRA E ;compare w/new PUSH PSW ;save status INX H ;disk table INX H ; address DAD D ;add the DAD D ;offset MOV A,M ;get parameters ORI 1 ;mask off density ANA B ;set new density MOV M,A ;update POP PSW ;check for nd=cd RNZ ;new disk not old MOV A,M ;update CDISK STA DCREG ; also RET * * SDSEL STA DREG ;drive select reg RET LUSTAT LDA USTAT ;UART status reg RET SCBITS STA DCMD ;1791 control reg RET LDSTAT LDA DSTAT ;drive status reg RET LOADS LXI H,DSTAT ;drive status reg RET end