; 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