***************************************************************** * * * 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 ; index equ 010h trkzro equ 004h intrqa equ 001h intrqb equ 004h lhsdenb equ 90dh lhddenb equ 80ch lhsdena equ 111h lhddena equ 010h 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 than 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. jnc wrstrs ; Loop until not busy. wrstrd mov a,m rar ; Now do it again. Not sure why jc wrstrd ; two trips are needed. mov a,m 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. Loop until not busy. jnc wsicms wsicmd ldax d rar ; Why do it twice? I dunno. 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