; MYDDBIOS.Z80 ; ; THIS IS A ROM BASED BIOS SUITABLE TO RUN 2.2 CP/M ON A VERSAFLOPPY II BOARD ; THE BIOS AUTOMATICALLY FIGURES OUT THE DENSITY OF DRIVES A: & B: ; IT IS SETUP TO TALK TO A ZAPPLE LIKE MONITOR AT 0F000H ; ; VERSION 1.0 JOHN J.MONAHAN (201)779-0635 1/15/1981 ; ZCI EQU 0F003H ;CONSOLE INPUT ZCO EQU 0F009H ;CONSOLE OUTPUT ZCSTS EQU 0F012H ;CONSOLE STATUS ZRI EQU 0F006H ;READER TO MONITOR ZPOO EQU 0F00CH ;PUNCH TO MONITOR ZLO EQU 0F00FH ;LIST TO MONITOR ZLISTS EQU 0F027H ;LIST STATUS TO MONITOR SSMVID EQU 0ED00H ;LOCATION FOR DUMP OF DISK INFO ON SCREEN SSMDSK EQU SSMVID+06H ;LOCATION TO PLACE UNIT# SSMTRK EQU SSMVID+12H ;LOCATION TO PLACE TRACK# SSMSEC EQU SSMVID+1FH ;LOCATION TO PLACE SECTOR# SSMDMA EQU SSMVID+2EH ;LOCATION TO PLACE DMA ADDRESS MONITOR EQU 0F000H ;ZAPPLE LIKE MONITOR (NOTE IT IS NOT ZAPPLE ITSELF) PANNEL EQU 0FFH ;FRONT PANEL SWITCH USED TO SWITCH ON/OFF DUMP TO VDM STORE EQU 0D8H ;PORT USED AS KIND OF IOBYTE WITHIN MY MONITOR (CAN BE ; ;REMOVED FROM CODE IF YOU LIKE ) ; ; LF EQU 0AH CR EQU 0DH BELL EQU 07H CLEAR EQU 1AH TAB EQU 09H ; ; IOBYTE EQU 03H CDISK EQU 04H TADDR EQU 40H UNIT EQU 42H ;NEW UNIT BYTE SCTR EQU 43H ;SECTOR TRK EQU 44H ;TRACK NREC EQU 45H ;# OF SECTORS ERMASK EQU 46H ;ERROR MASK ERSTAT EQU 47H ;ERROR FLAG STORE IDSV EQU 48H ;6 BYTES (USED FOR TRACK ID COMMAND) CMDSV EQU 4EH ;COMMAND SAVE SPSV EQU 4FH ;SP SAVE TEMP2 EQU 51H ;2 BYTE TEMP RECORD COUNT EQU 53H ;SECTORS/TRACK STORE VDMFLG EQU 54H ;FLAG TO INDICATE ASCII TO VDM BOARD HAS BEEN PLACED UNITCK EQU 55H ;OLD UNIT BYTE RSEEK EQU 56H ;NBR OF RESEEKS RTRY EQU 57H ;NBR OF RTRYS ADRIVE EQU 58H ;STORE OF A: DRIVE DENSITY ETC TYPE BDRIVE EQU 59H ;STORE OF B: DRIVE TYPE CBFLAG EQU 5AH ;FLAG TO INDICATE WBOOT OR CBOOT FOR LOADER ON DISK SSTACK EQU 80H ;SYSTEM STACK COLD EQU 80H ;COLD START ADDRESS ; X EQU 60H ;PORTS FOR 1791 RSET EQU X+0 ;CONTROLLER RESET ADDRESS SELECT EQU X+3 ;DRIVE SELECT PORT STATUS EQU X+4 ;STATUS PORT TRACK EQU X+5 ;TRACK PORT SECTOR EQU X+6 ;SECTOR PORT DATA EQU X+7 ;DATA PORT CMD EQU X+4 ;COMMAND PORT ; RDACMD EQU 0C0H ;READ ADDRESS CODE RDCMD EQU 088H ;READ SECTOR CODE WRCMD EQU 0A8H ;WRITE SECTOR CODE WRTCMD EQU 0F4H ;WRITE TRACK CODE RSCMD EQU 009H ;RESTORE COMMAND SKNCMD EQU 019H ;SEEK NO VERIFY SKCMD EQU 1DH ;SEEK WITH VERIFY ; STDSDT EQU 26 ;STANDARD 8" 26 SECTORS/TRACK STDDDT EQU 50 ;STANDARD DD 8" 50 SECTORS/TRACK NBYTES EQU 128 ;BYTES/SECTOR NTRKS EQU 77 ;TRACKS/DISK ; ; ; ; ORG 0F800H ;<--------- LOCATION OF 2716 PROM ; ; DOS SYSTEM LINKAGES (USED BY SDOS & 2.2 CP/M DO NOT CHANGE ORDER) ; CBOOT: JP BOOT ;COLD START ENTRY WBOOT: JP BOOTW ;WARM START ENTRY CSE: JP ZCSTS ;CONSOLE STATUS CIE: JP ZCI ;CONSOLE IN COE: JP ZCO ;CONSOLE OUT LIST: JP ZLO ;TO MONITOR FOR PRINTER PUNCH: JP ZPOO ;TO MONITOR FOR PUNCH READR: JP ZRI ;TO MONITOR FOR READER HME: JP HOME ;MOVE TO TRACK 0 SDSKE: JP SELDSK STRKE: JP SETTRK SSECE: JP SETSEC SDMAE: JP SETDMA RDE: JP READ WRE: JP WRITE LISTS: JP ZLISTS ;LIST STATUS SECTR: JP SECTRAN ;FOR 2.2 SECTOR TRANSLATION TABLE ; DTYPE: JP UNITSL ;SET UP UNIT BYTE (DISK DENSITY) SVE: JP SAVER ;SAVE N RECORDS LDE: JP LOADER ;LOAD N SECTORS ; ;---------------------------------------------------------------------- ; ;BOOT LOADS A SECTOR TO 80H AFTER CHECKING DISK TYPE THEN JUMPS TO 80H ; BOOT: XOR A LD (CDISK),A ;MAKE CURRENT DISK A: LD (IOBYTE),A ;CLEANUP IOBYTE LD (VDMFLG),A ;ASCII TO VDM BOARD NOT YET SENT DEC A LD (CBFLAG),A ;INDICATE A COLD BOOT TO LOADER LD HL,MSG0 ;SEND SIGNON MESSAGE CALL ZTOMM IN A,(STORE);---FOR MY SYSTEM I/O (CAN REMOVE THIS & NEXT 2 LINES) LD E,A CALL ZBITS JR BOOTW1 ; BOOTW: XOR A ;INDICATE TO LOADER A WARM BOOT LD B,A LD (CBFLAG),A BOOTW1: LD SP,SSTACK LD A,8EH ;SWITCH ON DRIVE A DISABLE ANY WAIT STATES OUT (SELECT),A LD A,08H ;LOAD HEAD WITH A RESTORE (NO VERIFY) OUT (CMD),A ;THE HEAD LOAD STARTS MY DRIVE MOTOR BOOTW2: DJNZ BOOTW2 ;DELAY A LITTLE TO LET MOTOR GET TO SPEED PUSH HL ;SAVE [SP] HERE FOR ALL ERRORS ETC LD (SPSV),SP POP HL CALL FRCINT XOR A OUT (TRACK),A LD A,2 LD (TRK),A LD A,SKNCMD CALL SEEK4 BT2: XOR A ;COME UP ON A: DRIVE CALL UNITSL ;IS IT SD OR DD JR NZ,GOMON ;IF NONE OF THE ABOVE QUIT ; BT4: LD A,(UNIT) AND 01000000B ;ISOLATE ALL BUT DENSITY BIT LD (ADRIVE),A ;SO ADRIVE= 0H IF SD & 40H IF DD LD A,0FFH ;FLAG B: AS NOT YET OBTAINED LD (BDRIVE),A CALL BOOTLD LD HL,COLD LD A,(HL) CP 31H ;EXPECT TO HAVE 31H @80H IE. LD SP,80H JR NZ,GOMON1 ;AS THE FIRST INSTRUCTION JP COLD ;IF ALL IS OK. JUMP TO 80H AND LOAD CP/M ; GOMON: LD HL,MSG1 ;"CANNOT SELECT DISK" JR GOMON2 GOMON1: LD HL,MSG2 ;"ERROR READING LOADER" GOMON2: CALL ZTOMM JP MONITOR ; BOOTLD: LD HL,COLD BOOT1: LD (TADDR),HL BOOT2: XOR A LD (TRK),A ;SET TRACK 0 INC A LD (SCTR),A CALL READ RET Z JR GOMON1 ; ; THIS ROUTINE SETS UP THE UNIT BYTE ; THE REQUIRED DRIVE IS IN [A] ; UNITSL: LD B,5 AND 0FH OR 40H ;COME UP DEFALT IN 8" DD LD (UNIT),A LD HL,(TADDR) LD (TEMP2),HL CALL USL1 LD HL,(TEMP2) LD (TADDR),HL LD A,(UNIT) RET ; USL1: PUSH BC PUSH HL LD (SPSV),SP POP HL CALL DRVSET ;SELECT DRIVE IN HARDWARE CALL IDRD POP BC LD A,(IDSV+3) ;THIS CHECKS FOR 256 BYTES/SECTOR NOT RRCA ;USED IN THIS BIOS. IF CORRECT DENSITY RET Z ;IT WILL BE Z ;@ IDSV) DEC B ;DECREASE 5.......0 IF Z THEN ERROR JP Z,SPECIAL CALL CHGTYP JR USL1 ; SPECIAL:XOR A ;COULD BE LATER USED FOR SPECIAL SECTOR SIZE DEC A RET ;RET NZ SO SELDSK KNOWS THERE IS A PROBLEM ; CHGTYP: LD A,(UNIT) ADD 01000000B ;TOGGLE DENSITY BIT AND 01111111B ;CLEAR BIT 7 LD (UNIT),A RET ; ; DISK CONTROLLER LINKAGES ; HOME: XOR A ;THIS CUTS DOWN ON HEAD MOVEMENT SINCE MANY LD (TRK),A ;TIMES RESTORE IS NOT REQ RET ; ; SELDSK: LD A,C CP 2 JP NC,HDBIO1 ;THIS WILL RETURN 0000 IN [HL] TO TELL CPM OR A ;THERE IS A PROBLEM JP NZ,BBBB ;IS B DRIVE LD A,(ADRIVE) OR C LD (UNIT),A ;SET A: TO CORRECT DENSITY JP ALLOK BBBB: LD A,(BDRIVE) CP 0FFH ;IS THIS FIRST TIME JP NZ,BBB1 LD A,C ;IF SO GET DISK TYPE (AND SIZE) CALL UNITSL JP NZ,HDBIO1 ;BACK TO CPM WITH [HL]=0 & ERROR LD A,(UNIT) AND 01000000B LD (BDRIVE),A BBB1: OR C LD (UNIT),A ; ALLOK: BIT 6,A JP Z,ALLOK1 ;IS IT DD OR SD LD A,00000010B ;YES DD THEN CONVERT TO DD ADD C ;IE MAKE A:=C: AND B:=D: LD C,A ;NOTE THIS IS ONLY FOR CPM SOFTWARE ALLOK1: LD L,C LD H,0 ;ACTUAL DISK PARAMETER BLOCK IS GOT IN DDSKBIOS RET ; ; SETTRK: LD A,C LD (TRK),A RET ; SETSEC: LD A,C LD (SCTR),A RET ; SETDMA: LD (TADDR),BC RET ; SECTRAN:LD B,0 EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; ; READ A SECTOR READ: LD BC,301H READBT: LD (RSEEK),BC READ1: PUSH BC CALL RDSC POP BC RET Z CALL RETRY JR READ1 ; ; WRITE A SECTOR WRITE: LD BC,301H WRBT: LD (RSEEK),BC WRITE1: PUSH BC CALL WRSC POP BC RET Z CALL RETRY JR WRITE1 ; RETRY: DJNZ RETRY2 LD A,(RTRY) LD B,A DEC C JP P,RETRY1 POP AF XOR A INC A RET RETRY1: PUSH BC CALL HOME1 POP BC RETRY2: RET HOME1: LD (SPSV),SP LD A,RSCMD CALL SEEK4 XOR A RET ; ; SELECT DRIVE IN HARDWARE ; DRVSET:LD DE,UNIT LD A,(DE) AND 0E0H LD C,A ;STORE DRIVE TYPE IN [C] LD A,(DE) AND 03 LD B,A ;STORE DRIVE # IN [B] LD A,1 JR Z,DRVSEL CKDRV1: RLCA DJNZ CKDRV1 DRVSEL: OR C ;COMBINE TYPE & DRIVE# AND 7FH LD B,A ;[B] CONTAINS INFO FOR HARDWARE LD A,STDSDT ;SETUP FOR SD LD (COUNT),A ;STORE AS 26 SECTORS/TRACK LD A,40H ;WAS IT DD DRV1: CP C JR NZ,CKDRV LD A,STDDDT ;SETUP FOR DD LD (COUNT),A ;SET TO 50 SECTORS/TRACK CKDRV: LD A,B ;GET HARDWARE SELECT DATA CPL ;HARDWARE IS INVERTED OUT (SELECT),A LD A,(DE) LD (UNITCK),A CALL DELAY RDYCK: IN A,(STATUS) AND 80H JP NZ,END2 RET ; ; READ PRESENT DISK ADDRESS IDRD: CALL WAIT LD HL,IDSV LD BC,600H+DATA ;READ 6 BYTES LD A,0F8H LD (ERMASK),A CALL SWEB LD A,RDACMD ;DO THE ID READ CALL RDSCO LD A,(IDSV) CP NTRKS ;IS IT REASONABLE JP NC,SEEK0 OUT (TRACK),A XOR A RET ; DELAY: LD A,40 ;DELAY ~32 MS (DOES NOT SEEM TO BE CRITICAL) DELAY1: LD B,0 M0: DJNZ M0 DEC A JR NZ,DELAY1 RET ; ; READ SECTOR COMMAND RDSC: CALL DRINIT LD A,RDCMD RDSCO: LD (CMDSV),A DI OUT (CMD),A JR M2 M2: JR MM2 MM2: INIR EI JR END ; ; ; WRITE SECTOR COMMAND WRSC: CALL DRINIT LD A,WRCMD LD (CMDSV),A DI OUT (CMD),A JR H2 H2: JR HM2 HM2: OTIR EI ; ; END OF COMMAND END: CALL WAIT IN A,(STATUS) LD D,A LD A,(ERMASK) AND D RET Z END1: LD A,D END2: LD (ERSTAT),A CALL DELAY OR 1 LD SP,(SPSV) CALL UNITFX RET ; ; ; DRIVE INITIALIZATION ; DRINIT: CALL VDMDUMP ;WILL SEE IF DISK TRACK/SECTOR INFO IS REQ. POP HL LD (SPSV),SP PUSH HL LD A,(UNIT) LD D,A LD A,(UNITCK) CP D JR Z,DINIT1 CALL DRVSET CALL IDRD DINIT1: CALL SEEK LD A,0FEH LD (ERMASK),A ; TRINT: LD HL,(TADDR) ;SETUP DMA ADDRESS AND BYTE COUNT LD A,(SCTR) OUT (SECTOR),A LD BC,NBYTES*100H+DATA ; SWEB: IN A,(SELECT) ;ENABLE WAIT STATES AND 7FH OUT (SELECT),A RET ; ; ; ; SEEK TRACK ; SEEK: CALL RDYCK LD C,NTRKS ;MUST BE REASONABLE TRACK # LD A,(TRK) CP C JR C,SEEK1 SEEK0: LD A,0FH JR END2 SEEK1: LD C,A IN A,(TRACK) CP C RET Z ;IF SAME TRACK NO NEED TO SEEK LD A,SKCMD SEEK4: LD (CMDSV),A LD B,210 S0: DJNZ S0 CALL WAIT LD A,(TRK) OUT (DATA),A LD A,80H LD (ERMASK),A LD A,(CMDSV) OUT (CMD),A LD B,10 D0: DJNZ D0 CALL END CALL DELAY LD A,(CMDSV) CP RSCMD ;NO NEED TO CHECK RESTORE COMMAND RET Z IN A,(STATUS) AND 10H JR NZ,SEEK2 IN A,(TRACK) CP C RET Z SEEK2: LD A,20H END2JP: JP END2 ; WAIT: LD E,0 PUSH BC LD C,2 WAIT2: IN A,(STATUS) AND 1 JR Z,DWAIT DJNZ WAIT2 DEC E JR NZ,WAIT2 DEC C JR NZ,WAIT2 POP BC IN A,(SELECT) ;IF BY THIS TIME NOT READY FORCE OR 80H ;A HARDWARE RESET OUT (RSET),A F0: DJNZ F0 IN A,(RSET) CALL FRCINT LD A,RSCMD CALL SEEK4 LD A,0FEH JP END2JP ; ; DISABLE WAIT STATES DWAIT: POP BC ;TO BALANCE THE ABOVE PUSH IN WAIT IN A,(SELECT) OR 80H OUT (SELECT),A RET ; ; ; ; FORCE CHIP INTERUPT FRCINT: LD A,0D0H OUT (CMD),A LD A,10 FRC1: DEC A JR NZ,FRC1 IN A,(STATUS) RET ; ; LOAD A NUMBER OF SECTORS LOADER: CALL UNITFX LD1: CALL READ RET NZ CALL INCP JR NZ,LD1 RET ; ; SAVE A NUMBER OF SECTORS SAVER: CALL UNITFX SV1: CALL WRITE RET NZ CALL INCP JR NZ,SV1 RET ; ; INC SECTOR AND TRACK INCP: LD HL,(TADDR) LD DE,NBYTES INCP2: ADD HL,DE LD (TADDR),HL LD HL,NREC DEC (HL) RET Z LD HL,SCTR INC (HL) LD A,(COUNT) ;IS ONE TRACK DONE YET INC A CP (HL) RET NZ ;IF FULL GO TO NEXT TRACK LD (HL),1 ;SET SECTOR COUNT BACK TO 1 INC HL ;ASSUMES TRK=SECTOR+1 IE 44H INC (HL) OR A ;MAKE SURE TO RETURN NZ RET ; ; UNITFX: LD A,0FFH LD (UNITCK),A RET ; ;THE FOLLOWING ARE MONITOR LIKE COMMANDS I HAVE ADDED ; ZTOMM: LD A,(HL) CP '$' RET Z LD C,A INC HL CALL ZCO JR ZTOMM ; ZBITS: PUSH BC ;DISPLAY BIT PATTERN IN [E] LD B,8 BQ2: SLA E LD A,18H ADC A,A LD C,A CALL ZCO DJNZ BQ2 POP BC RET ; ; THIS IS A ROUTINE THAT WILL PLACE ON A VDM THE CURRENT SELECTED TRACK/SECTOR ; INFORMATION. IT IS CONTINOUSLY UPDATED FOR EACH SECTOR READ OR WRITE IF BIT 7 ; OF PORT "PANEL" IS RESET. NOTE IT ADDS EXTRA TIME TO DISK ASCESS SO BIT 7 ; SHOULD BE USED ONLY FOR DEBUGGING ETC. ; VDMDUMP:IN A,(PANNEL) ;FIND OUT IF DISPLAY IS REQ BIT 7,A RET NZ ;NZ IF NO DISPLAY WANTED PUSH HL ;JUST IN CASE PUSH DE PUSH BC ;[AF] DOES NOT MATTER LD A,(VDMFLG) ;IS ASCII ALREADY THERE OR A JR NZ,VDM1 LD HL,MSG3 ;DROP IN ASCII LD DE,SSMVID LD BC,MSGL-MSG3 LDIR XOR A LD (VDMFLG),A ;SO NO UPDATE NEXT TIME VDM1: LD HL,SSMDSK LD A,(UNIT) CALL DUMP LD HL,SSMTRK LD A,(TRK) CALL DUMP LD HL,SSMSEC LD A,(SCTR) CALL DUMP LD HL,SSMDMA LD A,(TADDR+1) CALL DUMP LD HL,SSMDMA+2 LD A,(TADDR) CALL DUMP POP BC POP DE POP HL RET ; DUMP: LD B,A ;STORE [A] FOR BELOW CALL CONVII LD A,B DEC HL ;DEC BECAUSE PRINTS RIGHT TO LEFT RRCA ;GET UPPER NIBBLE RRCA RRCA RRCA CONVII: AND 0FH ;CONVERT HEX TO ASCII ADD A,90H DAA ADC A,40H DAA LD (HL),A RET ; ; ; HDBIO1: LD HL,0H POP AF ;THIS POPS OFF THE RETURN THAT WOULD GO ;TO DSKBIOS INSTEAD IT RETURNS TO CP/M WITH XOR A ;0000 IN [HL]. THIS IS TAKEN AS AN ERROR BY CPM LD (CDISK),A ;SO WARMSTART WILL COME UP ON A: INC A RET ; MSG0: DB CLEAR,LF,01H,10H,11H,CR,TAB,TAB,'DISK LOADING' DB TAB,TAB,TAB,TAB,'STORE BYTE--',03H,5DH,' $' MSG1: DB CR,LF,BELL,'Cannot select disk',CR,LF,'$' MSG2: DB CR,LF,BELL,'Error reading CP/M loader',CR,LF,'$' MSG3: DB 'Disk Track Sector ' DB ' Taddress ' MSGL EQU $ ; ; ;END DDBIOS.Z80