***************************************************************** * * * Disk Format Program for Disk Jockey 2d controller. * * version 5.21 last modified 1 May 85 glh/w6bsk * * added format-system-tracks-only feature * ***************************************************************** title '*** format program for cp/m ver. 2.0 ***' org 100h revnum equ 521 ; revision number times 10 bdos equ 5 ; cp/m entry point wboot equ 0 ; warm boot entry origin equ 0e000h ; Start of firmware rom diskio equ origin+3f8h ; UART inverted data port datreg equ diskio+7 ; 1791 data register drvsel equ diskio+1 ; UART inverted status/function cstall equ diskio+3 ; Stall register: dummy call cmdreg equ diskio+4 ; 1791 controller status/command dside equ 008h ; Double-sided flag unloadb equ 00fh ; Unload command for b version wtcmd equ 0f4h ; Wait command sicmd equ 059h ; Step-in one track command immirq equ 0d0h ; Immediate interrupt request unloada equ 018h ; Unload command for A version restor equ 009h ; Restore command mask index equ 010h ; Polarity inversion mask trkzro equ 004h ; Track 0 mask lhsdenb equ 90dh ; Head load mask B model s.d. lhddenb equ 80ch ; Head load mask B model d.d. lhsdena equ 111h ; Head load mask A model s.d. lhddena equ 010h ; Head load mask A model d.d. acr equ 00dh alf equ 00ah start lxi sp,stack ; Set the local stack lhld origin+7 ; Load contents of E007,008 inx h ; HL = E0D8 mov a,m ; A = F9 lxi h,stdvsl+1 ; Set pointer and get ready lxi d,4 ; to move ahead 4 cells. mov m,a ; Save F9 in STDVSL+1 xri 3 ; Convert F9 to FA dad d ; and store this value in mov m,a ; location STBITS+1 dad d ; and in location GTSTAT+1 mov m,a lxi d,smessg ; Display the signon message call pbuff crok lxi d,dmessg ; Ask for drive desired and call pbuff ; input it. call rbuff cpi 'N' ; Ask for new parameters Š jz crok sta letter ; Save drive id for exit routine sui 'A' ; and verify legal drive request. jp notlow inputb lxi d,bmessg ; Bad drive request call pbuff ; try again. jmp crok notlow cpi 4 ; Verify drive is in legal range jp inputb ; and continue. sta drvno ; Store drive as converted binary fmtsiz lxi d,denmsg ; Select drive density message call pbuff call rbuff cpi 'N' ; Reset parameters if N jz crok sui '1' ; else strip ascii bias and jp sizchk ; verify legal request sizerr lxi d,bmessg ; Not acceptable, redo. call pbuff jmp fmtsiz setsys mvi a,2 ; Load count of 2 into SYSTRK sta systrk ; area - default is all tracks jmp sendi sizchk cpi 4 ; Verify density request is in jnc sizerr ; legal range (1-4) sta newsize ; Save the density request sysonl lxi d,tmessg ; Now ask if all tracks or system call pbuff ; tracks only call rbuff cpé  'Y§  » Ù wilì  reseô  SYSTRË  value¬ jz setsys ; anything else leaves default. sendi lxi d,imessg ; Ask for disk insertion in lxi h,jmessg ; desired drive. call sendmp getin2 call rbuff ; Get input and check it cpi 'N' ; for new params request jz crok proced lxi d,acralf ; Get the drive number and call pbuff ; put it in C. Load the lda drvno ; drive select mask in A, mov c,a ; and rotate the select mask mvi a,177q ; the required amount to qloop rlc ; generate the command needed dcr c ; to select the proper drive. jp qloop ; Mask off undesired bits and ani 3fh sta select ; save for track routine. call stdvsl Š call model lxi b,lhsdena ; This garbage is to ensure that jz prep ; the right disk jockey version lxi b,lhsdenb ; is used. prep mov a,b call stbits ; Set up the disk controller mov a,c call stbits lxi h,cmdreg ; Point to the command port and mvi m,immirq ; load an immediate interrupt mvi a,40h ; request. Then do a short, simple wirqd dcr a ; timing loop to allow settling. jnz wirqd mov a,m rar ; Get atatus and test for busy: jc notrdy ral ral ; Test ready flag: jc notrdy lxi d,wmessg ; Load Drive-protect message ral ; just in case and test for jc notrdyx ; protected drive. lxi d,0 ; All ok, go ahead. Get the call gtindx ; index pulse and then check ixloop call gtstat ; status byte for index marker. ani index ; Mask for index bit and if found xra b ; continue. If not found, then jnz dorest ; update trip counter and try dcx d ; again. Give up after count mov a,d ; exceeded. ora e jnz ixloop notrdy lxi d,rmessg ;not ready message notrdyx xchg lxi d,amessg call sendmp call unload jmp sendi ;back for more input dorest mvi m,restor ; Load restore command and dump wrstrs mov a,m ; in command port. Then get status rar ; byte and test for busy flag. If jnc wrstrs ; not busy loop until it is. wrstrd mov a,m ; Get the status byte again and rar ; keep checking until the disk is jc wrstrd ; not busy. As soon as the disk is mov a,m ; unbuay, load the status byte and ani trkzro ; verify track 0 flag. Must be at jz notrdy ; track 0 or error exists. lxi b,sdlist ; Since track 0 must always be lxi h,dlist ; single density, load the SD call ovlay ; overlays into the data tables. lxi b,l128 lxi h,slist call ovlay Š mvi a,'*' ; Tell everyone that a track is call pchar ; being written. Then find the calì  indexð  »  indeø  hole¬  seô  thå  tracë mvi h,0 ; counter initially to 0, and do call track ; the track 0 formatting. lxi d,table ; Point to overlay table, and lda newsize ; get the desired density. Use add a ; this as an offset into the table jz findix ; and proceed to set up the mov l,a ; necessary overlays for the mvi h,0 ; density requested. dad d mov c,m inx h mov b,m lxi h,slist call ovlay lxi b,ddlist lxi h,dlist call ovlay calì  modeì »  Thió ió morå garbagå tï  ensurå lxi b,lhddena ; the proper DJ board id. jz loadd lxi b,lhddenb loadd mov a,b call stbits mov a,c call stbits findix call indexp ; Find the index pulse and mvi h,1 ; update the track count to 1. tkstep mvi a,'*' ; Tell a track being written and call pchar ; then do the track format. lxi d,cmdreg mvi a,sicmd ; Step in one track stax d wsicms ldax d ; Load the status byte and test rar ; busy flag. If not busy, loop jnc wsicms ; until it is. wsicmd ldax d ; Then keep checking the status rar ; byte for not busy until done. jc wsicmd call track ; Do the actual track write. mov h,d ; Update the track count inr h ; and test for done. mvi a,77 systrk equ $-1 cmp h jnz tkstep ; If not, then prep the disk drive call unload ; else finished. Unload the heads, lxi d,fmessg ; say finished, ask if nore, etc. call pbuff call rbuff cpi 'F' ; Format another disk? jz crok jmp wboot ; All done, go home. Š sendmp push h ; Save second half of message call pbuff ; Display the first half lda letter ; Display the insert (drive) call pchar ; value pop d ; Finish the message. pbuff mvi c,9 jmp bdos ; Simple and primitive call rbuff lxi d,inbufx ; Point to the input message mvi c,10 ; buffer and read from kbrd. call bdos lda inbufx+1 ; Get character count and test ana a ; for empty buffer. mvi a,acr ; Load c/r and return if no rz ; input present. lda inbuf ; else get the buffer contents cpi 'a' ; and convert to upper case. This rc ; is a dumb way to do it. cpi 'z'+1 rnc sui 40q ret pchar push h push b push d push psw ; Standard read-me routine mov e,a mvi c,2 call bdos pop psw pop d pop b pop h ret inbufx db 10,0 inbuf db 0,0,0,0,0,0,0,0,0,0 stdvsl sta diskio+1 ; Set DJ function register ret stbits sta diskio+2 ; Set DJ drive control port ret gtstat lda diskio+2 ; Read DJ status port ret model lda diskio-4 ; DJ version id mask cpi (ret) ; C9 = A 00 = B ret unload call model ; This routine is for setting Š mvi a,unloada ; proper model values, A or B jz stbits mvi a,unloadb jmp stbits gtindx call model ; Set proper inversion value mvi b,0 ; to correspond with DJ board rz ; in use. mvi b,index ret indexp call gtindx ; Get the correct polarity mask windxh call gtstat ; and then load status byte. ani index ; Mask for index flag and XOR xra b ; with polarity mask. Loop in jz windxh ; this routine until index found. windxl call gtstat ; Reload the status byte and ani index ; mask for index flag. Loop until xra b ; the flag goes away (end of index jnz windxl ; hole seen) ret indxw call gtindx ; If in index window, wait until jmp windxl ; window past. table dw l128 ; 128 byte table address dw l256 ; 256 byte table address dw l512 ; 512 byte table address dw l1024 ; 1k byte table address track lda select ; Get the requested drive and call stdvsl ; dump it in the function port. xra a ; Start with side 0 forced. sta sideno ; Save the side number and call wtrack ; do the actual track write. call gtstat ; On return test for double- ani dside ; sided disk. If single then rnz ; done. Else set up to write inr a ; the second side. sta sideno ; Flag side 1 (second side) lda select ; Reselect the drive ani 357q ; and set in double-sided call stdvsl ; command. call indxw ; Wait for track start and then xchg ; do a track write. wtrack lxi d,datreg ; Point to disk data port and mvi l,1 ; set initial sector = 1. lxi b,4e50h ; 1 = FF28 2 = 4e50 ovld1 equ $-2 ; 3 = 4e50 4 = 4e50 mvi a,wtcmd ; Issue a write track command sta cmdreg ; Type III xchg ; Adjust the pointers wtl1 mov m,b ; and write the index mark dcr c ; preamble field. jnz wtl1 Š lxi b,0ch ; 1 = 0006 2 = 000C ovld2 equ $-2 ; 3 = 000C 4 = 000C wtl2 mov m,b ; Write the index mark zero dcr c ; leader field jnz wtl2 ovld3 mvi m,0f6h ; Special double-density mvi m,0f6h ; clock and data mark mvi m,0f6h ; field wtl3 mvi m,0fch ; Index mark id cell lxi b,4e32h ; 1 = FF1A 2 = 4E32 ovld4 equ $-2 ; 3 = 4E32 4 = 4E32 wtl4 mov m,b ; Write the sector mark dcr c ; preamble field jnz wtl4 sloop lxi b,0ch ; 1 = 0006 2 = 000C ovld5 equ $-2 ; 3 = 000C 4 = 000C wtl5 mov m,b ; Write the sector mark zero dcr c ; leader field jnz wtl5 ovld6 mvi m,0f5h ; Special double density mvi m,0f5h ; clock/data mark mvi m,0f5h wtl6 mvi m,0feh ; Sector start mark mov m,d ; Track number mvi m,0 ; Side number sideno equ $-1 mov m,e ; Sector number mvi m,1 ; 1 = 00 2 = 01 (DENSITY) ovls1 equ $-1 ; 3 = 02 4 = 03 mvi m,0f7h ; CRC data bytes inr e ; Update sector count lxi b,4e16h ; 1 = FF0B 2 = 4E16 ovld7 equ $-2 ; 3 = 4E16 4 = 4E16 wtl7 mov m,b ; Sector mark dcr c ; postamble field jnz wtl7 lxi b,0ch ; 1 = 0006 2 = 000C ovld8 equ $-2 ; 3 = 000C 4 = 000C wtl8 mov m,b ; Data mark zero dcr c ; leader field jnz wtl8 ovld9 mvi m,0f5h ; Special double density mvi m,0f5h ; clock/data mark mvi m,0f5h wtl9 mvi m,0fbh lxi b,0e540h ; 1 = E520 2 = E540 ovls2 equ $-2 ; 3 = E580 4 = E500 wtl10 mov m,b ; Write first quadrant of dcr c ; sector data jnz wtl10 ; All E5, of course mvi c,40h ; 1 = 20 2 = 40 ovls3 equ $-1 ; 3 = 80 4 = 00 wtl11 mov m,b ; Write second quadrant of dcr c ; sector data jnz wtl11 Š mvi c,40h ; 1 = 20 2 = 40 ovls4 equ $-1 ; 3 = 80 4 = 00 wtl12 mov m,b ; Write third quadrant of dcr c ; sector data jnz wtl12 mvi c,40h ; 1 = 20 2 = 40 ovls5 equ $-1 ; 3 = 80 4 = 00 wtl13 mov m,b ; Write final quadrant of dcr c ; sector data jnz wtl13 mvi m,0f7h ; Write CRC data bytes mvi a,27 ; 1 = 1B 2 = 1B 3 = 10 4 = 09 ovls6 equ $-1 ; Last sector+1 value lxi b,4e36h ; 1 = FF1B 2 = 4E36 ovls7 equ $-2 ; 3 = 4E6A 4 = 4E74 wtl14 mov m,b ; Write data postamble field dcr c jnz wtl14 cmp e ; Do last-sector written test jnz sloop ; and loop if not. wtl15 mov m,b ; Last sector written. Fill up dcr c ; the remaining cells to the jnz wtl15 ; index hole. wtl16 mov m,b dcr c jnz wtl16 wtl17 mov m,b dcr c jnz wtl17 ret * On entry, HL has ovly table address, BC has density table. ovlay mov a,m ;length of list push h ;save list ptr lxi h,wtrack ;overlay area xthl ; recover pointer mvi d,0 ovlay1 inx h ;increment pointer mov e,m ;get offset xthl ;exchange pointers dad d ;add the offset push psw ;save length count ldax b ;get replacement data mov m,a ;do the replacement inx b ;next replacement data pop psw ;recover length count dcr a ;decrement xthl ;exchange pointers jnz ovlay1 pop h ;adjust stack ret * the lists below represents the distances * between successive locations of the wtrack Š* routine that are to be overlaid in order * that the same routine will serve to format * different sized and density diskette * sector formats dlist db 18 ;length of list db ovld1-wtrack db 1 db ovld2-ovld1-1 db ovld3-ovld2 db 1 db 1 db ovld4-ovld3-2 db 1 db ovld5-ovld4-1 db ovld6-ovld5 db 1 db 1 db ovld7-ovld6-2 db 1 db ovld8-ovld7-1 db ovld9-ovld8 db 1 db 1 slist db 9 ;list length db ovls1-wtrack db ovls2-ovls1 db 1 db ovls3-ovls2-1 db ovls4-ovls3 db ovls5-ovls4 db ovls6-ovls5 db ovls7-ovls6 db 1 * overlay data for single density * formatted diskettes sdlist dw 0ff28h db 6 jmp wtl3 dw 0ff1ah db 6 jmp wtl6 dw 0ff0bh db 6 jmp wtl9 * overlay data for double density * formatted diskettes ddlist dw 4e50h db 0ch mvi m,0f6h Š db 36h dw 4e32h db 0ch mvi m,0f5h db 36h dw 4e16h db 0ch mvi m,0f5h db 36h * overlay data for single density * 26 sectors/track 128 byte sectors l128 db 0 dw 0e520h db 20h db 20h db 20h db 27 dw 0ff1bh * overlay data for double density * 26 sectors/track 256 byte sectors l256 db 1 dw 0e540h db 40h db 40h db 40h db 27 dw 4e36h * overlay data for double density * 15 sectors/track 512 byte sectors l512 db 2 dw 0e580h db 80h db 80h db 80h db 16 dw 4e6ah * overlay data for double density * 8 sectors/track 1024 byte sectors l1024 db 3 dw 0e500h db 0 db 0 db 0 db 9 dw 4e74h amessg db acr,alf Š db 'Drive $' rmessg db ' is not ready.$' wmessg db ' is write protected.$' bmessg db acr,alf db 'Improper response.$' dmessg db acr,alf db 'Select drive (a,b,c,or d): $' smessg db 'Disk Jockey 2d disk format program' db ' revision ' db '0'+revnum/10,'.','0'+(revnum mod 10) db acr,alf db 'Type "^c" to return to cp/m, "n" to restart.$' imessg db acr,alf db 'Insert a write enabled diskette in drive $' jmessg db acr,alf db 'close the drive door and then press return: $' fmessg db acr,alf db 'Function complete.' db acr,alf db 'Type return to return to CP/M, or f to format another: $' denmsg db acr,alf db 'Select a sector size:' db acr,alf db ' 1) 128 byte single density.' db acr,alf db ' 2) 256 byte double density.' db acr,alf db ' 3) 512 byte double density.' db acr,alf db ' 4) 1024 byte double density.' db acr,alf db 'Sector size: $' tmessg db acr,alf db ' Format system tracks only? (y/n): $' acralf db acr,alf,'$' letter db 0 drvno db 0 select db 0 newsize db 0 ds 50 stack equ $ end