TITLE VFBIOS SUBTTL Versafloppy and video driver firmware for CP/M .Z80 .PHASE 0F000H NBYTES EQU 128 ;BYTES PER SECTOR RBASE EQU 0 ;START OF RAM TADDR EQU RBASE+40H ;TRANSFER ADDRESS (SETDMA) UNIT EQU RBASE+42H ;DRIVE # SCTR EQU RBASE+43H ;SECTOR TRK EQU RBASE+44H ;TRACK NREC EQU RBASE+45H ;# OF SECTORS ERMASK EQU RBASE+46H ;ERROR MASK ERSTAT EQU RBASE+47H ;ERROR STATUS IDSV EQU RBASE+48H ;TRK,SCTR READ SAVE CMDSV EQU RBASE+4CH ;COMMAND SAVE SPSV EQU RBASE+4DH ;SP SAVE SSTACK EQU RBASE+80H ;SYSTEM STACK COLD EQU RBASE+80H ;COLD START ADDRESS ; PORTS USED BY DISK CONTROLLER X EQU 0E0H SELECT EQU X+3 ;DRIVE SELECT PORT STATUS EQU X+4 ;STATUS PORT (IN) TRACK EQU X+5 ;TRACK PORT SECTOR EQU X+6 ;SECTOR PORT DATA EQU X+7 ;DATA PORT (BID) CMD EQU X+4 ;COMMAND PORT (OUT) ; DAJEN KEYBOARD PORTS SDATA EQU 6CH ;INPUT DATA PORT SSTAT EQU 6EH ;INPUT STATUS PORT RXRMSK EQU 80H ;KBD READY,LOW ; PRINTER PORTS LSTAT EQU 2 ;LIST STATUS LDATA EQU 83H ;OUT LIST DATA LSTMSK EQU 2 ;PRINTER MASK(HIGH) ; DISK ERROR STATUS BYTE (ERSTAT) ;BIT 7 -- DRIVE NOT READY ;BIT 6 -- WRITE PROTECTED ;BIT 5 -- TRACK SEEK ERROR ;BIT 4 -- SECTOR NOT FOUND ;BIT 3 -- CRC ERROR ;BIT 2 -- DATA LOST ;BIT 1 -- DRQ BIT ;BIT 0 -- WRITE DELETED SECTOR READ ; DISK CONTROLLER COMMAND CODES RDACMD EQU 0C4H ;READ ADDRESS CMND RDCMD EQU 88H ;READ SECTOR CMND WRCMD EQU 0A8H ;WRITE SECTOR CMD WRTCMD EQU 0F4H ;WRITE TRACK CMD PAGE ; CP/M SYSTEM LINKAGES VFBIOS::JP ZAPPLE##;START UP IN ZAPPLE JP BOOT ;COLD BOOT ENTRY JP CONST ;CONSOLE STATUS JP CONIN ;READ CONSOLE JP CONOUT ;WRITE CONSOLE JP LIST ;WRITE PRINTER JP PUNCH ;WRITE PUNCH JP READER ;READ READER JP HOME ;MOVE DISK TO TRK 00 JP SELDSK ;SELECT DISK DRIVE JP SETTRK ;SET DISK TRACK JP SETSEC ;SET DISK SECTOR JP SETDMA ;SET MEM ADDR FOR READ/WRITE JP READ ;READ A SECTOR JP WRITE ;WRITE A SECTOR JP LOADER ;LOAD "N" SECTORS PAGE ; MINI/FULL SIZE VARIABLES ; MINI FUL SZE NSCTRS EQU 1AH ;12 1A SCTRS/TRK RSCMD EQU 0AH ;03 0A RESTORE CMND SKCMD EQU 1EH ;17 1E SEEK CMND HLDLY EQU 23H ;4B 23 HEAD LOAD DELAY ; DELAY CONSTANT. MUST BE SET FOR CLOCK RATE USED ; 2MHZ 2.5MHZ 3MHZ 4MHZ DLYCON EQU 99H PAGE BOOT: LD SP,0FB00H BOOT1:: LD HL,COLD LD (TADDR),HL XOR A LD (UNIT),A LD (TRK),A INC A LD (SCTR),A CALL READ ;LOAD BOOSTRAP AND JP Z,COLD ;BOOT IN CP/M (EXCEPT CBIOS) CALL ERR HALT ;IF BAD DISK, HALT PAGE ; NON DISK I/O LINKAGES--DAJEN BOARD AND LIST CONST:: IN A,(SSTAT) CPL AND RXRMSK RET Z LD A,0FFH RET CONIN:: CALL CONINF LD HL,UPFLAG CP "^"-40H ;CONTROL CHARACTER FOR UPPERCASE MODE JR NZ,CHECKA LD (HL),0FFH ;SET UPPERCASE MODE JR CONIN2 CHECKA: CP "\"-40H ;CONTROL CHARACTER FOR LOWERCASE MODE JR NZ,CONVRT LD (HL),0 ;SET LOWERCASE MODE CONIN2: CALL CONINF CONVRT: LD C,A LD A,(HL) OR A LD A,C RET Z ;RETURN IF IN LOWERCASE MODE CP "A" RET C ;RETURN IF <"A" CP "Z"+1 JR NC,CHECKB ;SKIP IF >"Z" ADD A,20H ;CHANGE UPPERCASE TO LOWERCASE RET CHECKB: CP "a" RET C ;RETURN IF <"a" CP "z"+1 RET NC ;RETURN IF >"z" SUB 20H ;CHANGE LOWERCASE TO UPPERCASE RET CONINF: CALL CONST JR Z,CONINF CONINP::IN A,(SDATA) AND 7FH RET CONINS: PUSH HL CALL CONIN POP HL RET PAGE ; Z80 Video Driver MBASE DEFL 0FC00H ;BASE OF VIDEO RAM VWORK DEFL 0F800H ;SCRATCHPAD AREA SPEED EQU VWORK CURSOR EQU VWORK+1 UPFLAG EQU VWORK+3 GLOBAL SPEED,CURSOR,UPFLAG TOP DEFL MBASE BOTTOM DEFL MBASE+3C0H BOTRT DEFL BOTTOM+3FH BSCHAR EQU 8 LFCHAR EQU 10 CRCHAR EQU 13 CONOUT::LD HL,EXIT PUSH HL LD HL,(CURSOR) LD A,C CP BSCHAR JR C,ENTER CP CRCHAR+1 JR NC,ENTER ADD A,A LD D,0 LD E,A LD IY,CMDTBL-BSCHAR*2 ADD IY,DE LD E,(IY) LD D,(IY+1) LD A,C PUSH DE RET ;Jump to routine CMDTBL: DEFW CLEFT,ENTER,LF,ENTER,CLEAR,CR EXIT: SET 7,(HL) LD (CURSOR),HL RET CLEFT: DEC HL LD A,H INC HL CP HIGH TOP-1 RET Z RES 7,(HL) DEC HL RET CLEAR: LD HL,BOTRT LD DE,BOTRT-1 LD BC,03FFH LD (HL)," " LDDR RET CR: RES 7,(HL) LD A,L AND 0C0H LD L,A RET LF: RES 7,(HL) LD A,3 AND H LD B,A LD A,0C0H AND L OR B CP 0C3H ;On line 15? JR Z,SCRLL LD DE,40H ADD HL,DE RET SCRLL: PUSH HL CALL SCROLL POP HL RET ENTER:: LD (HL),A INC HL PUSH HL LD DE,BOTRT+1 OR A ;Clear carry flag SBC HL,DE POP HL RET NZ SCROLL: LD DE,TOP LD HL,TOP+40H LD BC,3C0H LDIR LD HL,BOTRT LD DE,BOTRT-1 LD BC,03FH LD (HL)," " LDDR CALL CONINP CP "S"-40H CALL Z,CONINS SCR0: SUB "0" CP 8 JR Z,FAST JR NC,SCR1 RRCA RRCA RRCA LD (SPEED),A SCR1: LD A,(SPEED) OR A JR NZ,SCR2 CALL CONINS CP " " RET Z CP "0" RET Z JR SCR0 SCR2: INC A RET Z LD B,0 SCR3: DJNZ SCR3 INC A JR NZ,SCR3 RET FAST: LD A,0FFH LD (SPEED),A RET PAGE LIST: IN A,(LSTAT) AND LSTMSK JR NZ,LIST LD A,C OUT (LDATA),A RET READER EQU CONIN PUNCH EQU CONOUT PAGE ; DISK CONTROLLER LINKAGES HOME: CALL DRVSET ;SELECT DRIVE LD (SPSV),SP LD A,RSCMD CALL CMDI XOR A RET SELDSK: LD A,C LD (UNIT),A RET SETTRK: LD A,C LD (TRK),A RET SETSEC: LD A,C LD (SCTR),A RET SETDMA: LD (TADDR),BC RET READ: LD B,10 READ1: PUSH BC CALL RDSC ;READ A SECTOR POP BC RET Z ;RETURN IF NO ERROR DJNZ READ1 ;10 RETRIES XOR A INC A RET ;ERROR RETURN WRITE: LD B,10 WRITE1: PUSH BC CALL WRSC ;WRITE A SECTOR POP BC RET Z ;RETURN IF NO ERROR DJNZ WRITE1 ;10 RETRIES XOR A INC A RET ;ERROR RETURN PAGE ; END OF COMMAND END: IN A,(STATUS) RRA JR C,END CALL DWAIT IN A,(STATUS) LD D,A LD A,(ERMASK) AND D ;CHECK FOR ERRORS RET Z END1: LD A,D END2: LD (ERSTAT),A OR 1 LD SP,(SPSV) RET PAGE ; SELECT SIDE AND SEEK TRACK SEEK: LD A,(TRK) LD C,A IN A,(TRACK) CP C RET Z ; IF SAME TRACK, RETURN LD B,3 ;3 RETRIES SEEK2: LD A,C ;TRK # OUT (DATA),A LD A,SKCMD ;SEEK COMMAND PUSH BC ;SAVE RETRY COUNT AND TRACK # CALL CMDI POP BC IN A,(STATUS) AND 10H ;TEST FOR SEEK ERROR RET Z ; RET IF NO ERROR LD A,RSCMD PUSH BC CALL CMDI ;RESTORE DISK POP BC DJNZ SEEK2 LD A,20H JR END2 PAGE ; CHECK DRIV SEL AND CHANGE IF DIFFERENT DRVSET: IN A,(SELECT) CPL AND 0FH JR Z,DRVS1 ;IF NONE SELECTED,DEFAULT=0 LD C,0FFH DRVS0: INC C ;CONVERT TO DRV # RRA JR NC,DRVS0 LD A,(UNIT) AND 3 CP C RET Z ;IF SAME DRIVE, RETURN DRVS1: CALL DRSEL XOR A INC A RET PAGE ; READ PRESENT DISK ADDRESS (TRK & SCTR) IDRD: LD HL,IDSV LD B,4 LD A,0F8H LD (ERMASK),A CALL SWEB LD A,RDACMD CALL RDSC0 ;READ ID LD A,(IDSV) OUT (TRACK),A RET PAGE ; READ SECTOR COMMAND RDSC: LD (SPSV),SP CALL DRVSET CALL NZ,IDRD ;NEW DRIVE CALL SEEK ;SEEK TRACK LD A,0FEH LD (ERMASK),A CALL TRINT LD A,RDCMD ;READ COMMAND CALL HLCHK ;SET UP HEAD LOAD BIT RDSC0: LD (CMDSV),A OUT (CMD),A ;OUTPUT COMMAND LD C,DATA INIR ;INPUT SECTOR TO (HL) CALL END XOR A RET ; WRITE SECTOR COMMAND WRSC: LD (SPSV),SP CALL DRVSET CALL NZ,IDRD CALL SEEK LD A,0FCH LD (ERMASK),A CALL TRINT LD A,WRCMD CALL HLCHK LD (CMDSV),A OUT (CMD),A LD C,DATA OTIR CALL END XOR A RET PAGE ; TYPE I COMMANDS CMDI: LD (CMDSV),A ;SAVE IT LD A,80H LD (ERMASK),A CMDI1: IN A,(STATUS) RRA JR C,CMDI1 ;WAIT FOR NOT BUSY IN A,(SELECT) AND 1FH OR 60H OUT (SELECT),A ;NO WAIT STATE ENABLED LD A,(CMDSV) OUT (CMD),A LD A,1 CALL MSEC ;WAIT FOR STATUS JP END ; DISABLE WAIT STATES DWAIT: IN A,(SELECT) OR 0E0H ;NEG TRUE .AND. OUT (SELECT),A RET ; ENABLE WAIT STATES SWEB: IN A,(SELECT) AND 1FH OUT (SELECT),A RET ; SELECT DRIVE DRSEL: LD A,(UNIT) AND 3 OR A ;CHECK FOR ZERO LD C,A LD A,1 JR Z,DRSEL3 ;NO SHIFTING DRSEL2: RLCA ;SHIFT LEFT DEC C JR NZ,DRSEL2 DRSEL3: CPL OUT (SELECT),A LD A,HLDLY CALL MSEC ;DELAY FOR HEAD LOAD IN A,(STATUS) AND 80H RET Z POP AF LD A,40H ;DRIVE NOT READY SO ERR JP END2 ; DELAY (A)*1 MILLISEC MSEC: LD B,DLYCON MSEC1: DJNZ MSEC1 DEC A JR NZ,MSEC RET ; INITIALIZE FOR DISK TRANSFER TRINT: LD HL,(TADDR) LD B,NBYTES LD A,(SCTR) OUT (SECTOR),A ;SELECT SECTOR JR SWEB ; CHECK FOR HEAD LOADED. IF NOT SET "H" BIT IN ; COMMAND HLCHK: LD D,A ; SAVE COMMAND LD A,0D0H OUT (CMD),A ; FORCE INTERRUPT COMMAND LD A,4 HLCHK0: DEC A JR NZ,HLCHK0 RWAIT: IN A,(STATUS) RLA JR C,RWAIT AND 40H LD A,D RET NZ ;IF HEAD LOADED, RET OR 4 ;SET H BIT RET PAGE ; LOAD # OF SECTORS IN (NREC) LOADER: CALL READ ;READ A SECTOR JR NZ,ERR LD HL,(TADDR) LD DE,NBYTES ADD HL,DE LD (TADDR),HL LD HL,NREC ;POINT TO NREC DEC (HL) RET Z DEC HL DEC HL INC (HL) ;INC SECTOR # LD A,NSCTRS+1 CP (HL) ;LAST SECTOR ON TRACK? JR NZ,LOADER ;NOPE, RETURN LD (HL),1 ;SET TO SECTOR 1 INC HL ;POINT TO TRACK # INC (HL) JR LOADER PAGE ;ERROR MESSAGE "Disk err #nn" ERR: LD HL,ERMSG CALL PTXT LD A,(ERSTAT) CALL PACC LD C,CRCHAR CALL CONOUT LD C,LFCHAR JP CONOUT ERMSG: DEFB "Disk err #",0 PTXT: LD A,(HL) OR A RET Z LD C,A CALL CONOUT INC HL JR PTXT ; PRINT ACCUMULATOR PACC: PUSH AF RRCA RRCA RRCA RRCA CALL PRVAL POP AF PRVAL: AND 0FH ADD A,90H DAA ADC A,40H DAA LD C,A JP CONOUT GLOBAL LENGTH LENGTH EQU $-VFBIOS .DEPHASE END VFBIOS