.comment % ######################################################### # # # Hard Disk Certification or Read Validate # # Program for the Kaypro 10 and the WD 1001 # # and 1002 Winchester Disk Controller. # # # # Copyright (c) 1983 by Non-Linear Systems, Inc. # # No Warranty is made, expressed or implied. # # # # begun 09-Mar-83 # # by Matthew Sherman. # # # #=======================================================# # # # New Improved Version: 2.6 26-Oct-83 # # Current version: 2.5 19-Oct-83 # # New Current Version 2.4 Oct-83 # # Current version: 2.3 06-Mar-83 # # Previous Version: 2.2 20-Apr-83 # # Previous Version: 2.1 19-Apr-83 # # !!! RELEASE VERSION !!! # # Release version: 1.0 20-Apr-83 # # # # Changes, version 2.6 - Recalibrate disk and one # # retry after any error. (P. Whalley) # # Changes, version 2.5 - Added Pass counter and # # added conditional equates for hard disk reset # # logic. (M. Sherman) # # Changes, version 2.4 - Inverted hard disk reset # # logic # # Changes, version 2.3 - Added conditional # # equates for Western Digital 1002 board # # ( one less error status bit to test ) # # and read retry/no read retry. # # Changes: Restructured control section, # # added IF structures and equates for first, # # range selections and auto format, exit. # # ( no keyboard entry required ) ( version 2.2 ) # # -Added one retry on read error. # # ( supposed to fix occasional noise glitch # # problem on read-Xebex controller does this # # automatically, Western Digital does not. ) # # -Error reporting, better handling of multiple # # drives. ( version 2.0 ) # # -Proper disk select, proper handling of # # disk drive cut-out. ( version 1.1 ) # # # ######################################################### % .comment % ######################### # set up module # ######################### % ; ; version number ; vers equ 26 ; ; console i/o equates: ; bdos equ 05 ; bdos entry vector stack equ 0A000h ; stack location lf equ 0ah ; line feed cr equ 0dh ; carriage return esc equ 1bh ; ASCII esc code clears equ 1ah ; clear screen code clreos equ 17h ; clear to end of screen clreol equ 18h ; clear to end of line lodcur equ '=' ; load cursor command offset equ ' ' ; cursor positioning offset wboot equ 0000h ; warm boot entry point ; conditional equates: FALSE equ 0000h ; false condition TRUE equ NOT FALSE AUTOF equ FALSE ; auto format, no keyboard WD1001 equ FALSE ; Western Digital 1001 Disk Controller Board. WD1002 equ TRUE ; Western Digital 1002 Disk Controller Board. RETRY equ FALSE ; one retry on read error CERTIFI equ FALSE ; format and test if true, read only if false INVRES equ TRUE ; inverted hard disk reset if true MULPASS equ FALSE ; multiple passes (forever, actually) ; with pass count and count display. ; auto format equates: firstd equ 01 ; first disk, auto format lastd equ 01 ; last disk, auto format drange equ lastd-firstd ; disk range (number of disks-1) firstc equ 00 ; first cylinder, auto format lastc equ 305 ; last cylinder, auto format crange equ lastc-firstc ; cylinder range (number of cylinders-1) firsth equ 00 ; first head to format lasth equ 03 ; last head to format hrange equ lasth-firsth ; head range (number of heads-1) .Z80 page ; begin set up. ; start: ld sp,stack xor a ld (lstsw),a ; turn off print switch call print ; sign on. db clears db lf,lf,'Kaypro 10 Hard Disk ' IF CERTIFI db 'Certification ' ELSE db 'Read Validate ' ENDIF db 'Program Version ' db vers/10+'0','.',vers mod 10+'0' db cr,lf,'( Copyright (c) 1983 by Non-Linear Systems, Inc. )' db cr,lf IF WD1001 db '(WD1001) ' ENDIF IF WD1002 db '(WD1002) ' ENDIF IF RETRY db 'one read retry on error' ENDIF IF INVRES db ' NEW INTERFACE CARD' ELSE db ' OLD INTERFACE CARD' ENDIF IF MULPASS db ' LOOP FOREVER' ELSE db ' ONE PASS ONLY' ENDIF db 00 IF AUTOF call print db cr,lf,lf,'(Auto Select, disk(s) ' db 00 ld hl,firstd call outdec call print db '-' db 00 ld hl,lastd call outdec call print db ', cylinder(s) ' db 00 ld hl,firstc call outdec call print db '-' db 00 ld hl,lastc call outdec call print db ' head(s) ' db 00 ld hl,firsth call outdec call print db '-' db 00 ld hl,lasth call outdec call print db ' )',cr,lf db 00 ld a,firstd ld (fdsk),a ld a,drange ld (dskrng),a ld hl,firstc ld (fstcyl),hl ld hl,crange ld (cylrng),hl ld a,firsth ld (fhead),a ld a,hrange ld (hrng),a jp cerdsk ELSE gdsks: call print db esc,lodcur,6+offset,offset db 'First disk, last disk? (0-3,0-3)',clreol db cr,lf,' ( or an ESC to quit )' db esc,lodcur,6+offset,33+offset,00 call gettwo ; get two 16 bit numbers jp z,valdsk ; validate numbers, range ld a,(gotc) cp esc jp z,mpexit ; exit, they want to quit. call ientry ; invalid entry jr gdsks mpexit: call print db cr,lf,lf,00 jp wboot ; display invalid entry message at top of screen ; ientry: call print db esc,lodcur,offset,offset db 'Invalid entry',clreol,00 ret ; clear top line ; clrtop: call print db esc,lodcur,offset,offset,clreol,00 ret ; get two 16-bit numbers, return them in hl and de (hl is 1st, de is second) gettwo: xor a ld (rollo),a ; initialize rollover call getnum ret nz ld a,(rollo) or a ret nz ld hl,(number) push hl call getnum ld de,(number) pop hl ret nz ld a,(rollo) or a ret ; get a number getnum: ld hl,numlst ld (hl),'.' inc hl call getinp ret c ; illegal, exit cp ',' jr nz,getnm2 ld a,0ffh or a ret ; illegal, 1st number can't be a comma! getnm2: ld (hl),a ; 1st number inc hl call getinp ret c ; illegal, exit cp ',' jr z,maknum ld (hl),a ; second number inc hl call getinp ret c ; illegal, exit cp ',' jr z,maknum ld (hl),a ; third number inc hl call getinp ret c ; illegal, exit cp ',' jr z,maknum ld (hl),a ; fourth number inc hl call getinp ret c ; illegal, exit cp ',' jr z,maknum ld (hl),a ; fifth number call getinp ret c cp ',' ret nz ; entered more than five numbers, illegal! inc hl jr maknum mul16: or a ret z mul162: add hl,de ret c ; rollover, exit djnz mul162 ret maknum: ld de,0 ld (number),de dec hl ld a,(hl) cp '.' ret z push hl ld de,1 call makit pop hl dec hl ld a,(hl) cp '.' ret z push hl ld de,10 call makit pop hl dec hl ld a,(hl) cp '.' ret z push hl ld de,100 call makit pop hl dec hl ld a,(hl) cp '.' ret z push hl ld de,1000 call makit pop hl dec hl ld a,(hl) cp '.' ret z push hl ld de,10000 call makit pop hl xor a or a ret makit: ld hl,0 ld b,a call mul16 jr c,makite ld de,(number) add hl,de ld (number),hl ret nc makite: ld a,(0ffh) ld (rollo),a ret getinp: push hl push de push bc call getd cp ' ' call nc,putd ; echo it if it isn't a special character pop bc pop de pop hl ld a,(gotc) cp ',' ret z cp cr jr z,ntok sub '0' ret c ; illegal cp 10 jr c,setok scf ret ntok: ld a,',' setok: or a ret invdsk: call print db esc,lodcur,offset,offset db 'Disk numbers too large (0 to 3, please)',clreol,00 jp gdsks d2sml: call print db esc,lodcur,offset,offset db 'Last disk number too small ' db '( greater than or equal to first number, please)',clreol,00 jp gdsks valdsk: push hl push de call clrtop pop de pop hl xor a cp h ; 1st byte better be 0 jp nz,invdsk ; it wasn't cp d ; also should be 0 jp nz,invdsk ; it wasn't ld a,l cp 4 ; better be less than 4 jp nc,invdsk ; it wasn't ld (fdsk),a ld a,e cp l ; better be less than e jp c,d2sml ; it wasn't cp 4 jp nc,invdsk sub l ld (drng),a jp gheads gheads: call print db esc,lodcur,7+offset,offset,clreol db lf,'First head, last head? (0-7,0-7)',clreol db cr,lf,' ( or an ESC to start over )' db esc,lodcur,8+offset,33+offset,00 call gettwo jr z,valhds ld a,(gotc) cp esc jp z,start ; they want to start over call ientry jr gheads valhds: push hl push de call clrtop pop de pop hl xor a cp h jr nz,invhds cp d jr nz,invhds ld a,l cp 8 jr nc,invhds ld (fhead),a ld a,e cp l jr c,h2sml cp 8 jr nc,invhds sub l ld (hrng),a jp gcylnd invhds: call print db esc,lodcur,offset,offset db 'Head numbers too large (0 to 7, please)',clreol,00 jp gheads h2sml: call print db esc,lodcur,offset,offset db 'Last head number too small ' db '(greater than or equal to first number, please)',clreol,00 jp gheads gcylnd: call print db esc,lodcur,9+offset,offset,clreol db lf,'First cylinder, last cylinder? (0-305, 0-305)',clreol db cr,lf,' ( or an ESC to start over )' db esc,lodcur,10+offset,46+offset,00 call gettwo jr z,valcyl ld a,(gotc) cp esc jp z,start ; start over call ientry jr gcylnd valcyl: push hl push de call clrtop pop de pop hl ld a,h cp 01 jr c,valcy2 jr nz,invcyl ld a,l cp 32h jr nc,invcyl valcy2: ld (fstcyl),hl ; first cylinder ld a,d cp 01 jr c,valcy3 jr nz,invcyl ld a,e cp 32h jr nc,invcyl valcy3: ex de,hl or a sbc hl,de jr c,c2sml ld (cylrng),hl jp cerdsk invcyl: call print db esc,lodcur,offset,offset db 'Cylinder numbers too large ' db '(0 to 305, please)',clreol,00 jp gcylnd c2sml: call print db esc,lodcur,offset,offset db 'last cylinder number smaller than first cylinder number' db clreol,00 jp gcylnd ENDIF .comment % ######################################### # # # Main Program Control Module # # # ######################################### % cerdsk: call print db esc,lodcur,11+offset,offset,clreol,lf,00 ld a,(fdsk) ld (diskno),a ld a,(drng) ld (dskrng),a ; all control routines have ld a,(fhead) ; resetable parameters ld (headno),a call hdcres ; reset controller, select drive. if mulpass ld hl,0 ld (pascnt),hl ; initialize pass counter call print db esc,'B','7' ; turn on status line preservation db 00 pfloop: call print db cr,clreol db 00 ld a,(fdsk) ld (diskno),a ld a,(drng) ld (dskrng),a ; all control routines have ld a,(fhead) ; resetable parameters ld (headno),a call dsppas ; display pass count call fmtdsk ld hl,(pascnt) inc hl ld (pascnt),hl jr pfloop ; pass forever loop endif call fmtdsk jp cfexit ; format a range of disk drives. ; entry parameters: first disk in diskno, ; number of additional disks in dskrng. ; exit parameters: none. ; registers affected: all ; fmtdsk: ld hl,(fstcyl) ld (fcyl),hl ld hl,(cylrng) ld (crng),hl call hdseld ; select controller, select drive, ; restore drive call fmtcyl ld a,(dskrng) or a ret z dec a ld (dskrng),a ld a,(diskno) inc a ld (diskno),a jr fmtdsk fmtcyl: ld a,(fhead) ld (headno),a ld a,(hrng) ld (hcount),a call fmthds ; go do each head ld hl,(crng) ld a,h or l ret z dec hl ld (crng),hl ld hl,(fcyl) inc hl ld (fcyl),hl ; go on to next jr fmtcyl ; cylinder... fmthds: call fmttrk ld a,(hcount) or a ret z dec a ld (hcount),a ld a,(headno) inc a ld (headno),a jr fmthds .comment % ################################################# # # # Track Format and Certification Module # # # ################################################# % .comment % ######################################################### # # # equate tables for the Western Digital # # Winchester Controller and the Kaypro 10 # # # ######################################################### % ; port/register equates wdbase equ 80h ; base address for the controller wddata equ wdbase+0 ; data register wderr equ wdbase+1 ; error register (read) wdpcmp equ wdbase+1 ; write precomp. register (write) wdscnt equ wdbase+2 ; sector COUNT (read/write) wdsnum equ wdbase+3 ; sector NUMBER (read/write) wdclow equ wdbase+4 ; low byte, cylinder number (r/w) wdchi equ wdbase+5 ; high byte, cylinder number (r/w) wdsdh equ wdbase+6 ; Size/Drive/Head (r/w) wdsts equ wdbase+7 ; status register wdcmd equ wdbase+7 ; command register ; masks, select information crcdat equ 00h ; crc in data field mask eccdat equ 80h ; ecc in data field mask sec256 equ 00h ; 256 byte sector mask sec512 equ 20h ; 512 byte sector mask sec128 equ 60h ; 128 byte sector mask dsel00 equ 00h ; drive 0 select mask, dsel01 equ 08h ; drive 1, dsel02 equ 10h ; drive 2, dsel03 equ 18h ; drive 3. hsel00 equ 00h ; head 0 select mask, hsel01 equ 01h ; head 1, hsel02 equ 02h ; head 2, hsel03 equ 03h ; head 3, hsel04 equ 04h ; head 4, hsel05 equ 05h ; head 5, hsel06 equ 06h ; head 6, hsel07 equ 07h ; head 7. hicmsk equ 03h ; high cylinder mask ; status masks ; status register bsymsk equ 80h ; busy mask, bsybit equ 7 ; busy bit ready equ 40h ; selected drive ready line. wrtflt equ 20h ; write fault mask scmplt equ 10h ; seek complete datreq equ 08h ; data request corerr equ 04h ; corrected error hderr equ 01h ; error occured ; error register bbdet equ 80h ; bad block detect uncerr equ 40h ; uncorrectable error crcerr equ 20h ; crc error - ID field idnf equ 10h ; ID not found abocmd equ 04h ; aborted command tr0err equ 02h ; track 0 error damnf equ 01h ; DAM not found ; commands: hdrstr equ 10h ; restore command, 35.0 uS step rate. seek30 equ 06h ; 3.0 ms seek rate hdseek equ 76h ; seek command, 3.0 ms hdread equ 20h ; read, i/o mode, single, no ecc returned. hdwrte equ 30h ; write, ditto. hdfmtt equ 50h ; format track. mulbit equ 04h ; multiple read/write longbt equ 02h ; long read/write ; KayPro operational equates bitport equ 14h ; system bit port hdcmsk equ 11111101b ; hard disk controller reset bit(s) mask invmsk equ 00000010b ; hard disk controller isolate bit(s) mask if invres hdcsel equ 00000000b ; hd controller select mask reshdc equ 00000010b ; hard disk controller reset mask else hdcsel equ 00000010b reshdc equ 00000000b endif whdsel equ eccdat+sec512 ; error correction, 512 byte sectors msecfmt equ 17 ; 17 sectors formatted, 0-16 maxsec equ 16 ; 16 sectors used, 0-15 lndzne equ 229 ; landing zone hdssiz equ 512 ; sector size fmttrk: call print db cr,'Validating',00 call dspdch ; display drive, cylinder and head call oprint ; operator interrupt? ld a,2 ; set retry counter to 2. ld (rtrycnt),a xfmttrk: IF CERTIFI push bc ; save registers. push de push hl ENDIF ld hl,(fcyl) ld a,l ; select track out (wdclow),a ld a,h out (wdchi),a ; initialize buffer ld de,fmtbuf ; initialize buffer ld hl,fmttbl ld bc,0200h ldir IF CERTIFI call fmttr2 ; format it and hderr+corerr ; any error-correctable or not pop hl ; restore registers. pop de pop bc jp z,certify ; if no errors, then goto certify. call hdcres ; home disk. ld a,(rtrycnt) ; decrement retry counter and loop if not zero. dec a ld (rtrycnt),a jr nz,xfmttrk call fmterr ; call error handler. jp certify ; set up sector registers fmttr2: ld a,0 ; first sector out (wdsnum),a ld a,msecfmt ; sector count out (wdscnt),a ; issue format command ld a,hdfmtt out (wdcmd),a ; output buffer to controller ld hl,fmtbuf ld bc,0000h+wddata ; b=count, c=data port otir otir call busy ret ; write track, excluding previously noted bad sectors wrttrk: ld hl,fmtbuf in a,(wdclow) xor a out (wdsnum),a out (wdscnt),a ld e,msecfmt wrtlp3: ld a,(hl) or a jr nz,wrtlp2 ld a,hdwrte out (wdcmd),a wrtlp: push hl ld hl,wrtbuf ld bc,0080h otir otir call busy pop hl inc hl inc hl and hderr+corerr+wrtflt jr z,wrtlp2 ld (hl),80h call wrterr wrtlp2: dec e ret z in a,(wdclow) in a,(wdsnum) inc a out (wdsnum),a jr wrtlp3 wrtlp4: inc hl inc hl jr wrtlp3 cert1: ld a,2 ; set retry counter to 2. ld (rtrycnt),a xcert1: ld a,0 ; clear error flag. ld (errflag),a push bc ; save registers. push de push hl call wrttrk pop hl ; restore registers. pop de pop bc ld a,(errflag) ; if no errors, then goto vrfyx. or a jr z,vrfyx call hdcres ; home disk. ld a,(rtrycnt) ; decrement retry counter and loop if not zero. dec a ld (rtrycnt),a jr nz,xcert1 vrfyx: call verify ld hl,wrtbuf ld b,00 ret certify:call vrfyx ; verify format swrt1: ld (hl),0b6h ; B6D data pattern inc hl ld (hl),0dbh inc hl ld (hl),06dh inc hl djnz swrt1 call cert1 swrt2: ld (hl),0b6h ; B6D9 data pattern inc hl ld (hl),0d9h inc hl djnz swrt2 call cert1 swrt3: ld (hl),0 ; 0000 data pattern inc hl ld (hl),0 inc hl djnz swrt3 call cert1 swrt4: ld (hl),0aah ; AAAA data pattern inc hl ld (hl),0aah inc hl djnz swrt4 call cert1 swrt5: ld (hl),00h ; 00AA data pattern inc hl ld (hl),0aah inc hl djnz swrt5 call cert1 swrt8: ld (hl),0a0h ; A0A0 data pattern inc hl ld (hl),0a0h inc hl djnz swrt8 call cert1 swrt9: ld (hl),0ffh ; FFFF data pattern inc hl ld (hl),0ffh inc hl djnz swrt9 call cert1 swrtA: ld (hl),055h ; 5555 data pattern inc hl ld (hl),055h inc hl djnz swrtA call cert1 swrtC: ld (hl),055h ; 55FF data pattern inc hl ld (hl),0ffh inc hl djnz swrtC call cert1 swrtD: ld (hl),0f5h ; F5F5 data pattern inc hl ld (hl),0f5h inc hl djnz swrtD call cert1 fmtE5: ld hl,wrtbuf ; fill with E5's, ld bc,0 ; thus - swrtF: ld (hl),0e5h ; leaving it ready for use. inc hl ld (hl),0e5h inc hl djnz swrtF in a,(wdclow) xor a out (wdsnum),a out (wdscnt),a ld e,msecfmt ld hl,fmtbuf fillin: ld a,(hl) or a jr z,filn2 ; good block if zero, ld a,hdwrte+longbt ; else a bad block, use long write. out (wdcmd),a call fillbx xor a ; now give it a bad ecc out (wddata),a inc a out (wddata),a out (wddata),a out (wddata),a call busy jr filn3 filn2: ld a,hdwrte ; good block, out (wdcmd),a ; do a normal write call fillp filn3: dec e ret z inc hl inc hl in a,(wdclow) ; clear hrdw data strobe in a,(wdsnum) inc a out (wdsnum),a jr fillin fillp: call fillbx call busy ret fillbx: push hl ld hl,wrtbuf ld bc,0080h otir otir pop hl ret ENDIF ; read track verify routine verify: ld a,2 ; set retry counter to 2. ld (rtrycnt),a yverify:ld a,0 ; clear error flag. ld (errflag),a push bc ; save registers. push de push hl ld de,fmtbuf ; initialize buffer. ld hl,fmttbl ld bc,200h ldir pop hl ; restore registers. pop de pop bc push bc ; save registers. push de push hl call xverify pop hl ; restore registers. pop de pop bc ld a,(errflag) ; if no errors, then return. or a ret z call hdcres ; home disk. ld a,(rtrycnt) ; decrement retry counter and loop if not zero. dec a ld (rtrycnt),a jr nz,yverify ret xverify:call seldsk ; make sure we're selected before we start, xor a ; initialize: out (wdsnum),a ; sector count, out (wdscnt),a ; multiple read count (none), ld e,msecfmt ; number to read in e, ld hl,fmtbuf ; pointer to sector header table vfylp: ld a,(hl) ; get good/bad header byte from table or a ; good header ? jr nz,vfylp2 ; if not, don't bother to retry sector, in a,(wdclow) ; else clear hardware drq line ld a,hdread out (wdcmd),a ; issue a read command, call busy ; wait until it's done, and hderr+corerr ; any errors? jr z,vfylp2 ; no, continue, IF RETRY in a,(wdclow) ; else clear hardware drq ld a,hdread ; and prepare for first retry out (wdcmd),a call busy and hderr+corerr jr z,vfylp2 ; continue if retry good (a acc. = 0) ENDIF ld (hl),80h ; else set bad sector flag, call vfyerr ; and tell everyone about it. vfylp2: inc hl ; point to next header in table inc hl dec e ; last sector? ret z ; exit if so, in a,(wdsnum) ; else inc a out (wdsnum),a ; update sector number jr vfylp ; and try again. busy: in a,(wdsts) bit bsybit,a jr nz,busy ret fmterr: push hl push de push bc call print db cr,'format error',00 call dspdch call dsperr call dspsdh call print db cr,lf,00 call oprint jr erexit vfyerr: push hl push de push bc ld a,1 ; set error flag. ld (errflag),a ld a,(rtrycnt) ; if retry counter is not 1, then goto erexit. cp 1 jp nz,erexit call print db cr,'verify error',00 call dspdch call dspsec call dsperr call dspsdh ; display sdh register call print db cr,lf,00 call oprint jr erexit wrterr: push hl push de push bc ld a,1 ; set error flag. ld (errflag),a ld a,(rtrycnt) ; if retry counter is not 1, then goto erexit. cp 1 jr nz,erexit call print db cr,'write error',00 call dspdch call dspsec call dsperr call dspsdh call print db cr,lf,00 call oprint erexit: pop bc pop de pop hl ret cfexit: IF AUTOF jp 0000 ; warm boot ENDIF call print db esc,lodcur,23+offset,offset db 'Another pass ? (y/n) ',clreos,00 call getd cp ' ' call nc,putd ; echo if not carry ld a,(gotc) cp 'Y' jp z,start cp 'y' jp z,start cp 'N' jp z,0000 ; exit if 'N' cp 'n' jp z,0000 ; or 'n' jr cfexit ; else loop. ; reset the controller, delay, enable it, do a slow restore to cyl 0. ; hdcres: in a,(bitport) and hdcmsk or reshdc ; [plw] out (bitport),a ld bc,0 ; 1.8 Milliseconds hdrslp: djnz hdrslp dec c jr nz,hdrslp hdseld: in a,(bitport) and hdcmsk or hdcsel ; [plw] out (bitport),a ; [plw] push bc ; save registers. push de push hl call busy call seldsk ld a,hdrstr+seek30 ; slow restore out (wdcmd),a call busy pop hl ; restore registers. pop de pop bc ret seldsk: in a,(bitport) ; make sure the and invmsk ; isolate select bit(s), cp hdcsel ; is the HDC selected? jr nz,hdcres ; if not, go select, restore it call busy ; wait until controller is ready, ld a,(diskno) ; select the current disk, add a,a add a,a add a,a ld b,a ld a,(headno) ; current head, or b or eccdat+sec512 ; error detection and sector size out (wdsdh),a call busy ; wait until controller does it, and ready ; is the drive itself ready? jr z,notrdy ; not ready, wait on it, seltrk: push hl ; else re-select track number, exit. ld hl,(fcyl) ld a,l out (wdclow),a ld a,h out (wdchi),a pop hl ret notrdy: call print db esc,'B','6' ; save current cursor position db esc,lodcur,23+offset,offset db 'disk not ready, waiting 1 minute. ' db '( T minus 60 seconds and counting... )' db 00 ld hl,60 ld (cntdwn),hl ld de,60 ; 60X1=60 seconds D1Sec: ld bc,4500 ; 1 sec loop seld2: in a,(wdsts) ; wait until the disk drive is ready, and ready jp nz,seld3 ; it's ready, let's go push de push bc call getsts pop bc pop de jp nz,start dec bc ld a,b or c jr nz,seld2 ; else drift thru delay loop push de call print db esc,lodcur,23+offset,44+offset,00 ld hl,(cntdwn) dec hl ld (cntdwn),hl ld a,l cp 10 jr nc,seld99 push hl ; we need a leading space ld a,' ' ; for numbers smaller than 10 call putd pop hl seld99: call outdec ; output the count down number call print db esc,lodcur,23+offset,70+offset,00 pop de dec de ; 1 second gone... ld a,d or e jr nz,D1Sec call print ; if it isn't ready now it never will be. db esc,lodcur,16+offset,60+offset,'!!! SELECT ERROR !!!' db esc,lodcur,17+offset,60+offset,'Either that disk' db esc,lodcur,18+offset,60+offset,'does not exist, or' db esc,lodcur,19+offset,60+offset,'there has been an' db esc,lodcur,20+offset,60+offset,'equipment malfunc-' db esc,lodcur,21+offset,60+offset,'-tion. Type any' db esc,lodcur,22+offset,60+offset,'key to start over' db 00 call getd ; wait for them to hit a key, jp start ; then start over. seld3: call print ; clear delay display line, db esc,lodcur,23+offset,offset,clreos db esc,'C','6' ; restore cursor, db 00 jp seltrk ; let's go select track, exit! ; display drive, cylinder and head numbers, ; along with appropriate labels ; dspdch: call print db ' drive ',00 ld a,(diskno) ld l,a ld h,0 call outdec call print db ' cylinder ',00 ld hl,(fcyl) call outdec call print db ' head ',00 ld a,(headno) ld l,a ld h,0 call outdec ret ; display sector number ; dspsec: call print db ' sector ',00 in a,(wdsnum) ld l,a ld h,0 call outdec ret oprint: call getsts ; anyone type anything? jp z,seldsk ; no, return thru seldsk call print ; interrupt!!! db esc,'B','6' ; save cursor position db esc,lodcur,16+offset,60+offset,'!!! INTERRUPTED !!!' db esc,lodcur,17+offset,60+offset,'Please type any key' db esc,lodcur,18+offset,60+offset,'to continue,' db esc,lodcur,19+offset,60+offset,'or an ESC to return' db esc,lodcur,20+offset,60+offset,'to the main menu' db esc,lodcur,21+offset,60+offset,'and start all over' db esc,lodcur,22+offset,60+offset,'from the beginning ' db 00 call getd cp esc ; interrupted by an esc? jp z,start ; if so, interrupted out completely, start over, call print ; else erase message, db esc,lodcur,16+offset,60+offset,clreol db esc,lodcur,17+offset,60+offset,clreol db esc,lodcur,18+offset,60+offset,clreol db esc,lodcur,19+offset,60+offset,clreol db esc,lodcur,20+offset,60+offset,clreol db esc,lodcur,21+offset,60+offset,clreol db esc,lodcur,22+offset,60+offset,clreol db esc,'C','6' ; return cursor to last position, db 00 jp seldsk ; select disk, resume certification. dsppas: call print db esc,'B','6' ; save current cursor position db esc,lodcur,24+offset,40+offset ; middle of status line db 'Pass Number ' db 00 ld hl,(pascnt) call outdec call print db clreol,esc,'C','6' ; clear rest of line, return cursor. db 00 ret ; exit dspsdh: call busy in a,(wdsdh) ld hl,sdhtbl ld b,8 dssdh1: rla ld (hl),'0' jr nc,dssdh2 ld (hl),'1' dssdh2: inc hl djnz dssdh1 call print db ' SDH = ' sdhtbl: db 00,00,00,00,00,00,00,00 db 00 ret getd: call getsts jr z,getd ld (gotc),a ret putd: ld e,a ld c,06 call bdos ret getsts: ld e,0ffh ld c,06 call bdos or a ret print: pop hl ld a,(hl) inc hl push hl or a ret z call putd jr print lstit: ld c,05 call bdos ret include DSPERR.MAC include OUTDEC.MAC ; format skew table, skip 4: smallest is 4 sectors, largest is 4 + index gap. ; fmttbl: db 00,00,00,07,00,14,00,04,00,11 db 00,01,00,08,00,15,00,05,00,12 db 00,02,00,09,00,16,00,06,00,13 db 00,03,00,10 ldspce: db 00h ; leading zero suppress flag gotc: db 00h ; character input by getc fdsk: db 00h ; first disk, per pass, constant. drng: db 00h ; disk range, per pass, constant number: dw 0000h fhead: db 00h ; first head, per cylinder, constant. hrng: db 00h ; head range, per cylinder, constant. fstcyl: dw 0000h ; first cylinder to format, per disk, cylrng: dw 0000h ; cylinder range, per disk, constants. fcyl: dw 0000h ; current cylinder to format crng: dw 0000h ; current format pass cylinder range count diskno: db 00h ; current disk to format dskrng: db 00h ; current format pass disk range count headno: db 00h ; current head to format hcount: db 00h ; current range count, this cylinder errcnt: db 00h rollo: db 00h numlst: dw 0000h dw 0000h dw 0000h dw 0000h lstsw: db 00 ; list on/off switch, 00=list off pascnt: dw 0000h ; pass counter cntdwn: dw 0000h fmtbuf: defw 0000 redbuf equ fmtbuf+512 wrtbuf equ redbuf+512 rtrycnt equ wrtbuf+512 ; retry counter. errflag equ rtrycnt+1 ; error flag. END