; 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