; CBIOS for Z80-Simulator
;
; Copyright (C) 1988 by Udo Munk
;
MSIZE EQU 64 ;cp/m version memory size in kilobytes
;
; "bias" is address offset from 3400H for memory systems
; than 16K (referred to as "b" throughout the text).
;
BIAS EQU (MSIZE-20)*1024
CCP EQU 3400H+BIAS ;base of ccp
BDOS EQU CCP+806H ;base of bdos
BIOS EQU CCP+1600H ;base of bios
CDISK EQU 0004H ;current disk number 0=A,...,15=P
IOBYTE EQU 0003H ;intel i/o byte
;
; I/O ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
PRTSTA EQU 2 ;printer status port
PRTDAT EQU 3 ;printer data port
AUXDAT EQU 5 ;auxiliary data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
;
ORG BIOS ;origin of this program
NSECTS EQU (BIOS-CCP)/128 ;warm start sector count
;
; jump vector for individual subroutines
;
JP BOOT ;cold start
WBOOTE: JP WBOOT ;warm start
JP CONST ;console status
JP CONIN ;console character in
JP CONOUT ;console character out
JP LIST ;list character out
JP PUNCH ;punch character out
JP READER ;reader character out
JP HOME ;move head to home position
JP SELDSK ;select disk
JP SETTRK ;set track number
JP SETSEC ;set sector number
JP SETDMA ;set dma address
JP READ ;read disk
JP WRITE ;write disk
JP LISTST ;return list status
JP SECTRAN ;sector translate
;
; fixed data tables for four-drive standard
; IBM-compatible 8" disks
;
; disk parameter header for disk 00
DPBASE: DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK00,ALL00
; disk parameter header for disk 01
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK01,ALL01
; disk parameter header for disk 02
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK02,ALL02
; disk parameter header for disk 03
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK03,ALL03
;
; sector translate vector
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block, common to all disks
;
DPBLK: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;null mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
; DEFW 16 ;check size
DEFW 0 ;because medium not changable with z80sim!
DEFW 2 ;track offset
;
; signon message
;
SIGNON: DEFM '64K CP/M Vers. 2.2'
DEFB 0
;
; end of fixed tables
;
; individual subroutines to perform each function
; simplest case is to just perform parameter initialization
;
BOOT: LD SP,80H ;use space below buffer for stack
LD HL,SIGNON ;print message
BOOTL: LD A,(HL)
OR A
JP Z,BOOTC
LD C,A
CALL CONOUT
INC HL
JP BOOTL
BOOTC: XOR A ;zero in the accum
LD (IOBYTE),A ;clear the iobyte
LD (CDISK),A ;select disk zero
JP GOCPM ;initialize and go to cp/m
;
; simplest case is to read the disk until all sectors loaded
;
WBOOT: LD SP,80H ;use space below buffer for stack
LD C,0 ;select disk 0
CALL SELDSK
CALL HOME ;go to track 00
;
LD B,NSECTS ;b counts # of sectors to load
LD C,0 ;c has the current track number
LD D,2 ;d has the next sector to read
; note that we begin by reading track 0, sector 2 since sector 1
; contains the cold start loader, which is skipped in a warm start
LD HL,CCP ;base of cp/m (initial load point)
LOAD1: ;load one more sector
PUSH BC ;save sector count, current track
PUSH DE ;save next sector to read
PUSH HL ;save dma address
LD C,D ;get sector address to register c
CALL SETSEC ;set sector address from register c
POP BC ;recall dma address to b,c
PUSH BC ;replace on stack for later recall
CALL SETDMA ;set dma address from b,c
; drive set to 0, track set, sector set, dma address set
CALL READ
CP 00H ;any errors?
JP NZ,WBOOT ;retry the entire boot if an error occurs
; no error, move to next sector
POP HL ;recall dma address
LD DE,128 ;dma=dma+128
ADD HL,DE ;new dma address is in h,l
POP DE ;recall sector address
POP BC ;recall number of sectors remaining, and current trk
DEC B ;sectors=sectors-1
JP Z,GOCPM ;transfer to cp/m if all have been loaded
; more sectors remain to load, check for track change
INC D
LD A,D ;sector=27?, if so, change tracks
CP 27
JP C,LOAD1 ;carry generated if sector<27
; end of current track, go to next track
LD D,1 ;begin with first sector of next track
INC C ;track=track+1
; save register state, and change tracks
CALL SETTRK ;track address set from register c
JP LOAD1 ;for another sector
; end of load operation, set parameters and go to cp/m
GOCPM:
LD A,0C3H ;c3 is a jmp instruction
LD (0),A ;for jmp to wboot
LD HL,WBOOTE ;wboot entry point
LD (1),HL ;set address field for jmp at 0
;
LD (5),A ;for jmp to bdos
LD HL,BDOS ;bdos entry point
LD (6),HL ;address field of jump at 5 to bdos
;
LD BC,80H ;default dma address is 80h
CALL SETDMA
;
EI ;enable the interrupt system
LD A,(CDISK) ;get current disk number
LD C,A ;send to the ccp
JP CCP ;go to cp/m for further processing
;
;
; simple i/o handlers
;
; console status, return 0ffh if character ready, 00h if not
;
CONST: IN A,(CONSTA) ;get console status
RET
;
; console character into register a
;
CONIN: IN A,(CONDAT) ;get character from console
RET
;
; console character output from register c
;
CONOUT: LD A,C ;get to accumulator
OUT (CONDAT),A ;send character to console
RET
;
; list character from register c
;
LIST: LD A,C ;character to register a
OUT (PRTDAT),A
RET
;
; return list status (0 if not ready, 1 if ready)
;
LISTST: IN A,(PRTSTA)
RET
;
; punch character from register c
;
PUNCH: LD A,C ;character to register a
OUT (AUXDAT),A
RET
;
; read character into register a from reader device
;
READER: IN A,(AUXDAT)
RET
;
;
; i/o drivers for the disk follow
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: LD HL,0000H ;error return code
LD A,C
CP 4 ;must be between 0 and 3
RET NC ;no carry if 4,5,...
; disk number is in the proper range
; compute proper disk parameter header address
OUT (FDCD),A ;selekt disk drive
LD L,A ;L=disk number 0,1,2,3
ADD HL,HL ;*2
ADD HL,HL ;*4
ADD HL,HL ;*8
ADD HL,HL ;*16 (size of each header)
LD DE,DPBASE
ADD HL,DE ;HL=.dpbase(diskno*16)
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by BC using the
; translate table given by DE
;
SECTRAN:
EX DE,HL ;HL=.trans
ADD HL,BC ;HL=.trans(sector)
LD L,(HL) ;L = trans(sector)
LD H,0 ;HL= trans(sector)
RET ;with value in HL
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A ;in dma
RET
;
; perform read operation
;
READ: XOR A ;read command -> A
JP WAITIO ;to perform the actual i/o
;
; perform a write operation
;
WRITE: LD A,1 ;write command -> A
;
; enter here from read and write to perform the actual i/o
; operation. return a 00h in register a if the operation completes
; properly, and 01h if an error occurs during the read or write
;
; in this case, we have saved the disk number in 'diskno' (0-3)
; the track number in 'track' (0-76)
; the sector number in 'sector' (1-26)
; the dma address in 'dmaad' (0-65535)
;
WAITIO: OUT (FDCOP),A ;start i/o operation
IN A,(FDCST) ;status of i/o operation -> A
RET
;
; the remainder of the CBIOS is reserved uninitialized
; data area, and does not need to be a part of the
; system memory image (the space must be available,
; however, between "begdat" and "enddat").
;
; scratch ram area for BDOS use
;
BEGDAT EQU $ ;beginning of data area
DIRBF: DEFS 128 ;scratch directory area
ALL00: DEFS 31 ;allocation vector 0
ALL01: DEFS 31 ;allocation vector 1
ALL02: DEFS 31 ;allocation vector 2
ALL03: DEFS 31 ;allocation vector 3
CHK00: DEFS 16 ;check vector 0
CHK01: DEFS 16 ;check vector 1
CHK02: DEFS 16 ;check vector 2
CHK03: DEFS 16 ;check vector 3
;
ENDDAT EQU $ ;end of data area
DATSIZ EQU $-BEGDAT ;size of data area
END