From 280aba4f8752e67066ce093b630e753d0771dfd5 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 8 Nov 2013 23:10:11 +0100 Subject: [PATCH] cpm: initial cbios and 20k cp/m 2.2 system --- z80/cpm/Makefile | 40 +++++++ z80/cpm/cbios.S | 275 ++++++++++++++++++++++++++++++++++++++++++++++ z80/cpm/cpm20.sys | Bin 0 -> 5584 bytes 3 files changed, 315 insertions(+) create mode 100644 z80/cpm/Makefile create mode 100644 z80/cpm/cbios.S create mode 100644 z80/cpm/cpm20.sys diff --git a/z80/cpm/Makefile b/z80/cpm/Makefile new file mode 100644 index 0000000..4567c42 --- /dev/null +++ b/z80/cpm/Makefile @@ -0,0 +1,40 @@ +# makefile + +PROG = cbios +OBJS = cbios.rel + +AS = sdasz80 +CC = sdcc -mz80 --all-callee-saves --no-std-crt0 +LD = sdldz80 + +.PHONY: all clean +all: dump.hex + +dump.hex: cbios.hex cpm20.hex + srec_cat -Output -Intel --address-length=2 \ + cbios.hex -Intel cpm20.hex -Intel > dump.hex + +cpm20.hex: cpm20.sys + objcopy -I binary -O ihex --change-addresses=0x3400 cpm20.sys cpm20.hex + +$(PROG).hex: $(PROG).ihx + @echo -e "\tMV\t$@" + @mv $< $@ + +$(PROG).ihx: $(OBJS) + @echo -e "\tLD\t$@" + @$(LD) -i $(OBJS) + +%.rel: %.c + @echo -e "\tCC\t$@" + @$(CC) -c -o $@ $^ + +%.rel: %.S + @echo -e "\tAS\t$@" + @$(AS) -l -p -o $@ $^ + +clean: + @echo -e "\tCLEAN" + rm -f *.asm *.hex *.lk *.lst *.map *.noi *.rel *.sym + rm -f cpm20.hex dump.hex + diff --git a/z80/cpm/cbios.S b/z80/cpm/cbios.S new file mode 100644 index 0000000..18039d8 --- /dev/null +++ b/z80/cpm/cbios.S @@ -0,0 +1,275 @@ +; Z80 CBIOS +.area BIOS (ABS) + +; configuration +MSIZE = 20 ; memory size +NDRIVES = 2 ; number of drives +TTY_D = 0x10 ; usart data port +TTY_S = 0x11 ; usart status port +ROMDISK = 0x0f ; romdisk port + +; constants +BIAS = (MSIZE-20)*1024 ; address offset from 0x3400 +CCP = (0x3400+BIAS) ; ccp base +BDOS = (CCP+0x806) ; bdos base +BIOS = (CCP+0x1600) ; bios base +NSECTS = (BIOS-CCP)/128 ; sector count for CCP+BDOS + +IOBYTE = 3 ; address of IOBYTE +CDISK = 4 ; address of CDISK + +;============================================================================ +; COLD BOOT ROUTINE +.org 0 + LD SP, #0x80 + JP BIOS + +;============================================================================ +;BIOS ENTRY POINT +.org BIOS + JP BOOT ; COLD START + 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 IN + JP HOME ; MOVE HEAD TO HOME + 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 + +;============================================================================ +; DATA TABLES +DPHEAD: + ; A: ROM DISK + .dw 0x0000, 0x0000, 0x0000, 0x0000 + .dw DIRBF, DPB_A, 0x0000, ALV_A + + ; B: 8MB DRIVE + .dw 0x0000, 0x0000, 0x0000, 0x0000 + .dw DIRBF, DPB_B, CHK_B, ALV_B + +DPB_A: + .dw 1 ; SPT -> 1 sector/track + .db 3, 7 ; BSH, BLM -> 1k blocksize + .db 0 ; EXM -> no extends + .dw 23 ; DSM -> 24 blocks + .dw 31 ; DRM -> 32 directory entries + .db 0x80,0x00 ; AL0/AL1 -> 1 block used for directory + .dw 0 ; CKS -> fixed disk (no change scratchpad) + .dw 44 ; OFF -> 44 reserved tracks (5.5 KB) + +DPB_B: + ; FIXME + .db 26,0,3,7,0,242,0,63,0,192,0,16,0,2,0 + +;============================================================================ +; MESSAGES +MSG_SIGNON: .asciz "CP/M 2.2 CBIOS v0\r\n" + +;============================================================================ +OUTMSG: + LD A,(HL) ; load char + OR A,A + RET Z ; return if zero + OUT (TTY_D),A + INC HL ; next char + JR OUTMSG + +OUTHEX: ; input = HL + LD C, H + CALL OUTHEX8 + LD C, L +OUTHEX8: ; input = C + LD A, C + RRA + RRA + RRA + RRA + CALL OUTHEXC + LD A, C +OUTHEXC: + AND #0x0F + ADD A, #0x90 + DAA + ADC A, #0x40 + DAA + OUT (TTY_D), A + RET + +;============================================================================ +BOOT: + LD HL, #MSG_SIGNON + CALL OUTMSG + + XOR A + LD (IOBYTE),A ; CON:TTY,RDR:TTY,PUN:TTY,LST:TTY + LD (CDISK),A ; drive A + ;JP GOCPM + +;============================================================================ +WBOOT: + ; read cp/m + LD HL, #CCP ; destination + LD C, #ROMDISK ; port + LD D, #(NSECTS) ; count sectors down + LD A, #0 ; count sectors up +1$: + OUT (C),A ; select track + LD B, #128 ; number of bytes + INIR ; read + INC A ; next track + DEC D ; one sector less + JR NZ, 1$ ; repeat + + JP GOCPM + +;============================================================================ +GOCPM: + LD A, #0xC3 ; JP opcode + LD (0), A ; ...at 0x0000 + LD (5), A ; ...at 0x0005 + LD HL, #WBOOT + LD (1), HL ; WBOOT pointer at 0x0001 + LD HL, #BDOS + LD (6), HL ; BDOS pointer at 0x0006 + + LD BC, #0x0080 + CALL SETDMA ; default DMA address 0x0080 + + EI ; enable interrupts + LD A, (CDISK) + LD C, A ; set active drive + + JP CCP ; go to cp/m + +;============================================================================ +CONST: + IN A, (#TTY_S) + OR A,A + RET Z ; no data: A=0x00 + LD A, #0xFF + RET ; else: A=0xFF + +;============================================================================ +CONIN: + CALL CONST + JR Z, CONIN + IN A, (TTY_D) ; read data + AND #0x7F ; strip parity bit + RET + +;============================================================================ +CONOUT: + LD A, C + OUT (TTY_D), A ; write data + RET + +;============================================================================ +LIST: + RET + +;============================================================================ +PUNCH: + RET + +;============================================================================ +READER: + LD A, #0x1A + AND #0x7F + RET + +;============================================================================ +HOME: + LD C, #0 + JP SETTRK ; will return for us + +;============================================================================ +; select disk from C (0..15 => A..P) +; return HL=dph or 0x0000 on error +SELDSK: + ; check for valid drive + LD HL, #0 ; error code + LD A, C + LD (DISKNO), A ; select drive + CP #NDRIVES + RET NC ; return if >NDRIVES + + ; put disk parameter header in HL + LD H, #0 + LD L, A ; drive number in HL + ADD HL, HL + ADD HL, HL + ADD HL, HL + ADD HL, HL ; * sizeof(dph) + LD DE, #DPHEAD + ADD HL, DE ; HL = table base + 16*drive + RET + +;============================================================================ +SETTRK: + LD (TRACK), BC + RET + +;============================================================================ +SETSEC: + LD (SECTOR), BC + RET + +;============================================================================ +SETDMA: + LD (DMAAD), BC + RET + +;============================================================================ +; return A=0 on success, A=1 on error; do retry +READ: + LD A,(TRACK) + OUT (ROMDISK),A ; select sector=track + + LD HL,(DMAAD) ; select destination + LD C, #ROMDISK ; disk data port + LD B, #128 ; 128 bytes + INIR ; read + + LD A, #0 + RET + +;============================================================================ +; return A=0 on success, A=1 on error; do retry +WRITE: + LD A, #1 + RET ; fail + +;============================================================================ +; return A=0 if printer busy, A=0xFF otherwise +LISTST: + XOR A + RET ; fail + +;============================================================================ +; logical sector number in BC and translation table address in DE, +; return physical sector in HL +SECTRAN: + RET + + +;============================================================================ +; VARIABLES AND SCRATCH RAM +DISKNO: .ds 1 ; selected disk +TRACK: .ds 2 ; selected track +SECTOR: .ds 2 ; selected sector +DMAAD: .ds 2 ; selected DMA address + +DIRBF: .ds 128 ; shared directory buffer +ALV_A: .ds 3 ; allocation buffer for ROM DISK +CHK_B: .ds 16 ; FIXME +ALV_B: .ds 31 ; FIXME + diff --git a/z80/cpm/cpm20.sys b/z80/cpm/cpm20.sys new file mode 100644 index 0000000000000000000000000000000000000000..9ef4a39180ebf342abd8920fa1bbeb02b696c763 GIT binary patch literal 5584 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 literal 0 HcmV?d00001 -- 2.30.2