TITLE 'GBC Format program.' ; Disk FORMAT for CompuPro Controller. ; ; +-----------------------+ ; | | ; | F O R M A T | ; | | ; +-----------------------+ ; ; ; COMPUPRO ; Oakland Airport ; Oakland California ; ; Copyright 1980, Compupro Corporation. ; ; This product is a copyright program product of ; COMPUPRO and is supplied for use with the COMPUPRO ; Disk controllers. ; ; Version number: 2.2A ; Version date: October 27, 1980 ; ; Version number: 2.2B ; Version date: February 24, 1980. ; ; . Corrected multiple formats. ; . Added two sided disk support. VER = '2' LEVEL = '2B' CR = 0Dh ;ASCII carriage return LF = 0Ah ;ASCII line feed BKSCHR = 08h ;ASCII backspace ABTCHR = 03h ;ASCII control C PRMCHR = '>' ;Prompt character BDOS = 0005h ;BDOS jump address RCO = 1 ;Read console WCO = 2 ;Write console GCNS = 11 ;Get console status RDS = 13 ;Reset disk system TBUFF = 080h ;Command line buffer ; Assembly Constants FDPORT EQU 0C0h ;Base port address for Controller FDCS EQU FDPORT ;Status register FDCD EQU FDPORT+1 ;Data register FDMA EQU FDPORT+2 ;Dma address (when write) INTS EQU FDPORT+2 ;Status Register (when read) MTRK = 76 ;Maximum cylinder for seek (0-76)=77 MRTRY = 5 ;Maximum retries of r/w op ; Controller function definitions F.DSTS = 04 ;Drive status F.RDAT = 06 ;Read data F.RECA = 07 ;Recalibrate F.RSTS = 08 ;Read status F.DRID = 10 ;Read Disk identification F.FMT = 13 ;Format cylinder F.SEEK = 15 ;Seek page ORG 0100h FORMAT: proc JMP FORMT1 ;start DB CR,LF,'Copyright SORCIM, 1980 ' DB VER,'.' DW rev (LEVEL) DB CR,LF,'Sorcim proprietary product.',CR,LF,01Ah FORMT1: PUSH PSW PUSH B PUSH D PUSH H LXI H,0 DAD SP SHLD SYSTK ;save system stack LDK SP,STK CALL PARG ;process command args LDK HL,IMSG CALL OSTR ;Initial message :1: LDK SP,STK ;Select drive and format disk CALL FMTD LDK HL,NEXTM CALL NLSTR CALL GANS CMP 'R' JNZ :5 ;If not reset LDK A,-1 STO A,ACTDSK ;Indicate reset of drive select JMP :1 :5: CMP CR JZ :1 ;If continue from last EXIT: ;If not R or CR, the exit MVI C,RDS CALL BDOS ;Reset disk system LHLD SYSTK SPHL POP H POP D POP B POP PSW RET SYSTK: DW 0 ; Here if some error in formatting FMTR: LDK A,-1 STO A,ACTDSK LDK HL,ABMSG CALL NLSTR CALL GANS JC EXIT ;If exit requested JMP :1 ;continue page FMTD: ;Format cylinders ; Exit Disk reformatted. proc LDK A,1 STO A,MRTRYC LD A,ACTDSK ;Active disk PUSH PSW CALL SDRV ;Select drive POP PSW ANI 080h CNZ SELFMT ;Select mode of disk CALL RDRV ;reset drive LDK HL,VFMTR CALL NLSTR ;verify user is ready CALL GANS JC FMTR ;If no confirmation ; Output cylinder template to console LDK HL,TRK10M CALL NLSTR LDK E,7 :2: LDK HL,TRK01M CALL OSTR DEC E JNZ :2 ;If not 70 times LDK HL,TRK06M CALL OSTR CALL CRLF ;new line LDK A,MRTRY STO A,MRTRYC ;reset retrys to max LDK HL,TRKDAT ;Set DMA address STO HL,BUFADR ; Now format the disk cylinder by cylinder. XOR A :10: STO A,CTRK ;set next cylinder CALL UFCHRN ;Update UFCHRN LD A,CTRK INC A CMP MTRK+1 JNZ :10 ;If not done ; Now validate good format. CALL CRLF ;new line LDK A,' ' CALL CONOUT ;skip cylinder 0 CALL TREAD LDK HL,FMTC CALL NLSTR RET space 4,10 UFCHRN: ;Update C,H,R,N for next format proc LD A,ACTDSK STO A,FMTRK+1 ;Set drive into command buffer LD A,CTRK OR A JNZ UFC1 ;If not cylinder 0 CALL RCAL LDK DE,0 ;Head 0, N = 0 LDK BC,26 ;Cylinder = 0, Sectors = 26 LDK A,F.FMT ;Set command code JMP UFC3 UFC1: CALL DOSEEK ;Seek to cylinder LDK D,0 ;Set head 0 UFC2: LD A,CTRK ;Get current cylinder MOV B,A ;B = cylinder number LD A,MSEC MOV C,A ;Set maximum number of sectors LD A,COD.N MOV E,A ;Set n field OR A LDK A,F.FMT ;Set MFM and command JZ UFC3 ;If single density OR 040h UFC3: STO A,FMTRK ;Set command into buffer CALL SETBUF CALL SDMA ;Set DMA address CALL IFMT ;Format 1 track JNZ UFC5 ;If error LD A,ACTTYP AND 1b JZ UFC4 ;If single sided LD A,FMTRK+1 MOV B,A OR 100b ;Set head = 1 STO A,FMTRK+1 LDK D,1 ;Set head = 1 CMP B JNZ UFC2 ;If side not already done UFC4: LDK A,'F' JMP CONOUT ;Display F and exit UFC5: LDK HL,NWRMS MOV A,C CMP 2 JZ UFC6 ;If not write enabled LDK HL,FMERM UFC6: CALL NLSTR JMP FMTR NWRMS: DC 'Disk does NOT have write ENABLED.' FMERM: DC 'FORMAT error, ABORT.' space 4,10 ; Setup formatting buffer. ; ; ENTRY B = cylinder. ; C = number of sectors per track ; D = head number. ; E = N field. SETBUF: XOR A ;A = 0 LDK HL,TRKDAT SBF1: INC A STO B,[hl] ;Set cylinder INC HL STO D,[hl] ;Set head INC HL STO A,[hl] ;Set sector INC HL STO E,[hl] ;Set N field INC HL CMP C JNZ SBF1 ;If track buffer not complete MOV A,C STO A,FMT.S ;Set number of sectors MOV A,E STO A,FMT.N ;Set N Field LDK D,0 LDK HL,TFGPL ADD HL,DE LD A,[hl] STO A,FMT.G ;Set gap size RET space 4,10 IFMT: ;Format one track on floppy disk LDK HL,FMTRK ;Set address LDK B,6 LDK C,7 CALL EXEC ;format cylinder LD A,LSTSB ANI 0F8h ;Mask out unit RZ ;If no errors LD A,LSTSB+1 MOV C,A LD A,LSTSB+2 MOV B,A OR C RET page TREAD: ;Test format by reading each sector proc CALL RDRV ;reset drive LD A,ACTTYP ;Get type ANI 1B RRC MOV C,A LD A,COD.F OR C STO A,COD.F ;Set MT if two sided LDK A,0 :2: INC A STO A,ACTTRK ;set to next cylinder CALL RSEC LD A,RSTS CALL CONOUT ;output status to user LD A,ACTTRK CMP MTRK JNZ :2 ;If not done RET space 4,10 RSEC: ;Read sector ; Exit Cbit set if read error proc LDK HL,RTRY STO 0,[hl] ;clear retry count LDK A,'V' STO A,RSTS ;set status to good :2: LDA ACTTRK CALL DOSEEK ;seek to cylinder LDK A,F.RDAT LDK B,LRCMD LDK C,7 CALL EXFNC ;Issue read CMP 40h JNZ :3 ;If bad read LD A,LSTSB+1 CMP 80h RZ ;If good read :3: LDK A,'S' STO A,RSTS ;Indicate soft error LDK HL,RTRY INC [hl] ;update retrys LD A,MRTRYC CMP [hl] JNZ :2 ;If not max retrys LDK A,'E' STO A,RSTS ;Indicate hard error STC ;Indicate error RET RSTS: DB 0 ;Indicate status of read RTRY: DB 0 ;retry count page ; Select drive ; Entry A= -1, request disk, else use A as disk drive ; Check for repeat of previous FORMAT, 2**7 on. SDRV: proc ANI 07Fh CMP 07Fh JNZ :2 ;If drive known SDRVA: LDK HL,SDRVM CALL NLSTR ;send format request MVI C,RCO ;Read console CALL BDOS CALL NORM SUI 'A' JM SDRVA ;If illegal CMP 'D'+1-'A' JP SDRVA ;If illegal :2: STO A,ACTDSK ;set active disk ADI 'A' STO A,PRMDRV ;set into prompt ; Try and determine density of device CALL DDTYP ;Determine disk type JZ :10 ;If type determined LDK HL,SDRNF CALL NLSTR ;Indicate disk NOT formatted RET ; Here if disk is currently formatted and I could ; perform a read, output density info. :10: STA ACTTYP ANI 0FEh ;Remove sided bit RLC ;*4 MOV E,A LDK D,0 LDK HL,SECFL ADD HL,DE LDK DE,SDRFN LDK C,4 :11: LD A,[hl] STO A,[de] INC HL INC DE DEC C JNZ :11 ;If not done LDK HL,SDRFF CALL OSTR ;show user density RET SECFL: DB ' 128 256 5121024' SDRFF: DB ' Disk is Formatted as ' SDRFN: DB ' ' DC ' byte sectors.' SDRNF: DC ' Disk is NOT formatted.' SDRVM: DB 'Specify drive (A: - D:) :',BKSCHR DC BKSCHR page SELFMT: proc ;Select disk mode format LDK HL,SELMS CALL OSTR MVI C,RCO ;Read console CALL BDOS CMP ' ' RZ ;If no change JC FMTR ;If abort CMP '0' JM SELFMT ;If illegal CMP '3'+1 JP SELFMT ;If illegal SUB '0' RLC ! RLC ;n*4 LDK D,0 MOV E,A LDK HL,SELFM ADD HL,DE LD A,[hl] ! STO A,COD.F ! INC HL LD A,[hl] ! STO A,COD.N ! INC HL LD A,[hl] ! STO A,COD.G ! INC HL LD A,[hl] ! STO A,COD.D ! INC HL LD A,COD.N MOV E,A LDK HL,TFGPL+4 ADD HL,DE LD A,[hl] STO A,MSEC ;set max sectors/cylinder RET SELMS: DB cr,lf DB 'Select Disk format mode (0,1,2,3):',cr,lf DB '0 - 128 2 = 512',cr,lf DB '1 = 256 3 = 1024 ' DC PRMCHR SELFM: DB 00h,00h,07h,80h DB 40h,01h,0eh,0FFh DB 40h,02h,1bh,0FFh DB 40h,03h,35h,0FFh page RDRV: ;Reset drive performing on ; Exit A = 0, transfer ok LDK HL,1 STO HL,ACTTRK ;cylinder to 1 MOV A,L STO A,ACTSEC ;set sector = 1 LDK HL,DSKB1 STO HL,BUFADR ;set FWA of load LDK A,0 STO A,BUFADE JMP RCAL ;recalibrate drive 0 page ; DDTYP - Determine floppy disk type. ; ; ENTRY A = Selected drive + 'A'. ; ; Exit Zbit set = no error ; A = disk type (0-3) DDTYP: STA NRDYM2 ;Set drive into message LDK HL,DSTS LDK B,DSTSL LDK C,0 CALL EXECP ;Perform command LDK B,1 CALL GCMPS ;Get the one status byte ANI 020h ;Mask ready bit JNZ DTYP1 ;If drive is ready LDK HL,NRDYM1 CALL OSTR ORI 0FFh ;Clear zero flag RET DTYP1: LDA LSTSB ;Get status byte ANI 008h ;Mask TS bit RRC RRC RRC STA ACTTYP ;Save sided flag LDK HL,RECAL ;Do a test seek LDK B,LRECAL CALL MOVETO ;Process command RNZ ;If error LDK A,2 ;Seek to cylinder two CALL DOSEEK ;Do seek RNZ ;If error LDK A,F.DRID STA DRID DTYP2: LDK HL,DRID LDK B,DRIDL LDK C,7 CALL EXECP ;Process command JZ DTYP3 ;If read valid LDA DRID XRI 040h ;Compliment MFM bit STA DRID ANI 040h JNZ DTYP2 ;If MFM not tried ORI 0FFh RET DTYP3: LDA LSTSB+6 ;Get number of bytes ADD A MOV B,A LDA ACTTYP ORA B ;Combine N with sided flag CMP A ;Set zero flag RET DSTS: DB F.DSTS DB 0 DSTSL: = *-DSTS DRID: DB F.DRID DB 0 DRIDL: = *-DRID NRDYM1: DB CR,LF,'Drive ' NRDYM2: DB 'x' DC ' not ready.' page ; Seek to specified Track/Sector ; Entry A = cylinder. ; ; Exit Cbit set if seek error DOSEEK: STO A,DSEKC+2 LDK HL,DSEKC LDK B,3 MOVETO: LDK C,0 CALL EXECP ;perform positioning DSEK2: IN INTS OR A JP DSEK2 ;If not complete LDK A,F.RSTS OUT FDCD ;request status LDK B,2 CALL GCMPS ;read status CMP 20h RZ ;If on cylinder LDA LSTSB ;Get status from buffer ANI 3h ;Mask unit number MOV C,A LD A,ACTDSK CMP C JNZ DSEK2 ;If not same unit LDK HL,SEKERR CALL NLSTR ;Indicate seek error JMP FMTR ;start again SEKERR: DC 'Seek error.' space 4,10 RCAL: ;Recalibrate drive LD A,ACTDSK STO A,RECAL+1 ;set drive LDK HL,RECAL LDK B,2 JMP MOVETO ;process command DSEKC DB F.SEEK DB 0 DB 0 RECAL DB F.RECA,0 LRECAL: = *-RECAL page ; Execute function ; Entry A = Function code ; B = # of bytes to output ; C = # of bytes for status ; Exit None EXFNC: MOV E,A LD A,COD.F ANI 1110_0000b ;high 3 bits only OR E STO A,COD.F ;set code LD A,ACTTRK STO A,COD.T LD A,ACTSEC STO A,COD.BR DEC A MOV E,A LD A,MSEC ;Note, cannot be 0 ADD E STO A,COD.FR ;set EOT CALL CKABT ;check for abort LDK HL,COD.F ;FWA of function block EXECT: CALL SDMA ;Set DMA EXECP: INC HL LD A,ACTDSK ;Set drive into command table STO A,[hl] DEC HL EXEC: PUSH BC ;save length EXEC1: IN FDCS OR A JP EXEC1 ;If no master ready bit LD A,[hl] ;command byte OUT FDCD ;to controller INC HL DCR B JNZ EXEC1 ;If more bytes POP BC MOV A,C ;# of status bytes+1 OR A RZ ;If no status bytes MOV B,C ;# of status bytes ; Check for no status function ; If so, exit without checking DMA ; Status. ; Entry B= Number+1 of status bytes to ; input. ; HL= Exit address ; Exit A= ST0, status INT: IN INTS OR A JP INT ;If not done ; Get completion status. ; Entry B= # of status bytes to read GCMPS: GCS2: IN FDCS OR A JP GCS2 ;If not ready ; Read in (B) status bytes ; ST0,1,2, C,H,R and N LDK DE,LSTSB ;last status bytes GCS3 IN FDCS OR A JP GCS3 ;If not ready IN FDCD ;read status STO A,[de] INC DE ;for next store DEC B ;decrement counter JNZ GCS3 ;wait until all done LD A,LSTSB ANI 0F8h ;Ignore us0,1 bits RET LSTSB: DB 0,0,0,0,0,0,0 space 4,10 SDMA: ;Send DMA to controller PUSH HL ;save user's HL LDK HL,BUFADE LDK E,3 SDMA1: LD A,[hl] ;get ext adr OUT FDMA DEC HL ;data is backward in memory DEC E JNZ SDMA1 ;If not all 3 bytes POP HL RET page PARG: ;Process command line arugments proc IN INTS ;free status JP :3 ;If no pending int ; input any hanging status :2: IN FDCS OR A JP :2 ;If all done IN FDCD CMP 80h JNZ :2 ;If not done ; process any command argument :3: LD A,TBUFF OR A LDK C,-1 ;Indicate un-initialized JZ :4 ;If no arguments LD A,TBUFF+2 CMP '?' JZ :10 ;If HELP request CMP 'A' LDK C,0 ;default drive=0 JM :4 ;If not legal drive CMP 'D'+1 JP :4 ;If not legal drive SUB 'A' ORI 080h ;Set sign bit MOV C,A ;set drive :4: MOV A,C STO A,ACTDSK ;set drive RET ; Here on HELP request :10: LDK HL,HELPM CALL NLSTR JMP EXIT ;exit HELPM: DB 'FORMAT will format a diskette to be compatible' DB cr,lf,'with the CompuPro disk subsystem. The FORMAT' DB cr,lf,'program will format a diskette as either' DB cr,lf,'128, 256, 512 or 1024 byte sectors, depending' DB cr,lf,'on the user request.' DB cr,lf,'The FORMAT command has one optional argument,' DB cr,lf,'the drive to format. The legal values' DB cr,lf DC 'are A thru D.' page CKABT: ;Check for abort ; Exit to master loop if console active PUSH HL ! PUSH DE ! PUSH BC MVI C,GCNS ;Get console status CALL BDOS POP BC ! POP DE ! POP HL OR A RZ ;If no abort MVI C,RCO ;Read console CALL BDOS JMP FMTR ;anew space 4,10 NORM: ;Normalize character UPPER ;Entry A= char ;Exit A= normalized char ; to system if char = ^c. CMP ABTCHR JZ EXIT ;If ^c, exit to system CMP 'a' RM ;If not lower case CMP 'z'+1 RNC ;If not lower case SUI 'a'-'A' RET space 4,10 NLSTR: ;Output newline followed by message PUSH HL CALL CRLF POP HL ; JMP OSTR OSTR: ;Output message to console ; Entry HL= FWA of message LD A,[hl] OR A ;check sign bit PUSH AF MOV C,A CALL CONOUT ;output char POP AF INC HL JP OSTR ;If not done RET space 4,10 GANS: ;Get answer to 'y' question ; Exit Cbit set if NO. MVI C,RCO ;Read console CALL BDOS CALL NORM CMP 'Y' STC RNZ ;If NO confirmation CLC RET space 4,10 ; Output new line ; Must perserve all registers CRLF: LDK A,CR CALL CONOUT LDK A,LF ; JMP CONOUT space 4,10 CONOUT: ;Output character to console ; Entry A=character ; Exit DE=DE,BC=BC,HL=HL PUSH HL ! PUSH DE ! PUSH BC MOV E,A MVI C,WCO ;Display character CALL BDOS POP BC ! POP DE ! POP HL RET page ABMSG: DC 'Format error, Do you want to continue (y) ? ' NEXTM: DB 'Do you want to FORMAT another disk ?' DB cr,lf,' R - request new parameters.' DB cr,lf,' cr - duplicate last FORMAT.' DB cr,lf,' N - exit back to system. ' DC prmchr IMSG: DB CR,LF,LF,LF DB 'CompuPro Disk Sub-system FORMAT Version ' DB VER,'.' DW rev (LEVEL) DB CR DC LF TRK10M: DB ' ' DB '1 ' DB '2 ' DB '3 ' DB '4 ' DB '5 ' DB '6 ' DB '7',cr DC lf TRK01M: DC '0123456789' TRK06M: DC '0123456' CTRK: DB 0 ;current cylinder MRTRYC: DB 0 FMTC: DC 'FORMAT complete.' VFMTR: DB 'Confirm ready for format on disk drive ' PRMDRV: DC 'a (y).' FMTRK: DB F.FMT DB 0 ;h,us1,us0 FMT.N DB 0 ; 0, 1, 2,3 FMT.S DB 0 ;26,15,8 FMT.G DB 0 ;36,54,74 DB 0E5h ;filler TFGPL: DB 01Bh,036h,054h,074h DB 26, 26, 15, 8 COD.F: DB F.RDAT+40h ;Command = read DB 0 ;hds,ds1,dso COD.T DB 1 ;C, cylinder 1 DB 0 ;Head COD.BR DB 1 ;record COD.N DB 1 ;N=MFM mode 256 COD.FR DB 22 ;EOT COD.G DB 0Eh ;GPL, MFM 256 COD.D DB 0ffh ;DTL, MFM 256 LRCMD = *-COD.F space 4,10 BUFADR: DW 0 ;lsbs of address BUFADE: DB 0 TWOBUF: DS 2 ;side two's buffer address ACTDSK: DS 1 ;disk drive selection ACTTYP: DS 1 ;disk type code ACTTRK: DS 2 ;Track ACTSEC: DS 1 ;sector MSEC: DS 1 ;Maximum sector per cylinder ORG ((*+100h)/100h)*100h TRKDAT: DS 26*4 ;26 sectors, 4 bytes/sector, two sides DS 2*30 ORG ((*+1000h)/1000h)*1000h STK: DS 0 ; Disk buffer DSKB1: DS 1024*8*2 DS 0 TITLE 'Cross Reference Listing.'