diff options
author | H. Peter Anvin <hpa@zytor.com> | 2014-06-01 15:09:53 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2014-06-01 15:09:53 -0700 |
commit | 78c734aef743b43c87c82eacbee3e0d2d2c9555f (patch) | |
tree | a65f7969a6ce9bf7740dfe5c3ef17a0f0f8b0a7f | |
parent | 81f02dd08a3879cce12754d8f4ec1b260bd210a5 (diff) | |
download | abc80-78c734aef743b43c87c82eacbee3e0d2d2c9555f.tar.gz abc80-78c734aef743b43c87c82eacbee3e0d2d2c9555f.tar.xz abc80-78c734aef743b43c87c82eacbee3e0d2d2c9555f.zip |
Actually working version of CP/M
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | data/cbios.asm | 183 | ||||
-rw-r--r-- | data/cpm.asm | 13 | ||||
-rw-r--r-- | data/cpm22.asm | 5 |
3 files changed, 92 insertions, 109 deletions
diff --git a/data/cbios.asm b/data/cbios.asm index caaa382..77746ae 100644 --- a/data/cbios.asm +++ b/data/cbios.asm @@ -1,15 +1,15 @@ ; SOCZ80 CP/M 2.2 BIOS (or at least an attempt!) ; 2013-11-03 Will Sowerbutts - +; 2014-06-01 H. Peter Anvin +; ; useful resources: ; http://www.cpm.z80.de/manuals/cpm22-m.pdf ; http://www.retrotechnology.com/dri/howto_cpm.html#myown ; http://www.retrotechnology.com/dri/cpm_features.html ; cpmtools package -msize: equ 64 ; KB of system RAM -biosextra: equ 512 -bias: equ (msize-20)*1024-biosextra +msize: equ 63 ; KB of system RAM +bias: equ (msize-20)*1024 ccp: equ 0x3400+bias bdos: equ ccp+0x0806 bios: equ ccp+0x1600 @@ -46,68 +46,37 @@ wboote: jp wboot ; warm start kbdvec: defw irq_kbd v24vec: defw irq_v24 -; disk parameter header (16 bytes for each drive), see page 6-28 in CP/M 2.2 operating system manual +; disk parameter header (16 bytes for each drive), +; the chk and alv get dynamically adjusted dpbase: - ; disk 0 (A) - dw 0 ; sector translation table (0 = no translation) - dw 0 ; must be 0 - dw 0 ; must be 0 - dw 0 ; must be 0 - dw dirbf ; DIRBUF (address of shared 128 byte scratch pad area) - dw dpblk ; DPB (disk parameter block) - dw chk00 ; CSV (unique scratch pad used to check for changed disks) - dw alv00 ; ALV (unique scratch pad for allocation information) - ; end of disk 0 - - ; disk 1 (B) - dw 0 ; sector translation table (0 = no translation) - dw 0 ; must be 0 - dw 0 ; must be 0 - dw 0 ; must be 0 - dw dirbf ; DIRBUF (address of shared 128 byte scratch pad area) - dw dpblk ; DPB (disk parameter block) - dw chk01 ; CSV (unique scratch pad used to check for changed disks) - dw alv01 ; ALV (unique scratch pad for allocation information) - ; end of disk 1 - - ; disk 2 (C) - dw 0 ; sector translation table (0 = no translation) - dw 0 ; must be 0 - dw 0 ; must be 0 - dw 0 ; must be 0 - dw dirbf ; DIRBUF (address of shared 128 byte scratch pad area) - dw dpblk ; DPB (disk parameter block) - dw chk02 ; CSV (unique scratch pad used to check for changed disks) - dw alv02 ; ALV (unique scratch pad for allocation information) - ; end of disk 2 - - ; disk 3 (D) - dw 0 ; sector translation table (0 = no translation) - dw 0 ; must be 0 - dw 0 ; must be 0 - dw 0 ; must be 0 - dw dirbf ; DIRBUF (address of shared 128 byte scratch pad area) - dw dpblk ; DPB (disk parameter block) - dw chk03 ; CSV (unique scratch pad used to check for changed disks) - dw alv03 ; ALV (unique scratch pad for allocation information) - ; end of disk 3 - -ndisks: equ 4 ; number of disks we defined + dw 0 ; sector translation table (0 = no translation) + dw 0 ; must be 0 + dw 0 ; must be 0 + dw 0 ; must be 0 + dw dirbf ; DIRBUF (address of shared 128 byte scratch pad area) + dw dpblk ; DPB (disk parameter block) +dp_csv: dw csv ; CSV (unique scratch pad used to check for changed disks) +dp_alv: dw alv ; ALV (unique scratch pad for allocation information) + +ndisks: equ 8 ; number of disks we defined ; disk parameter block (can be shared by all disks with same configuration) -; each volue is 15,597,568 bytes (238*256*256). We represent this as +; each volue is 15,597,568 bytes (238*256*256), which is too much for +; CP/M 2.2 to handle, so split each into two subvolumes. We represent this as ; tracks of 8192 bytes (64 sectors x 128 bytes) which matches an UFD-DOS -; "cluster". This means there are 1904 tracks. The first track is reserved -; for the system, leaving 1903*64 = 121792 user sectors. -; We use 8K blocks, matching ABC clusters, so there are 1903 user blocks. +; "cluster". This means there are 952 tracks per subvolume. +; The first track is reserved for the system, leaving +; 951*64 = 60864 user sectors. We use 8K blocks, matching ABC clusters, +; so there are 951 user blocks. A smaller block size eats up too much +; memory in the alv tables. dpblk: dw 64 ; SPT: number of 128 byte sectors per track db 6 ; BSH: block shift factor (see manual for table) db 63 ; BLM: block mask (see manual for table) db 3 ; EXM: extent mask (see manual for table, using entries marked N/A turns out to be a bad idea!) - dw 1903 ; DSM: (disk bytes / block bytes) - 1, change alv0x etc if you change this; this is the number of the last sector on the disk, excluding system tracks (ie more system tracks -> this gets smaller) - dw 1023 ; DRM: directory max entries - 1 - db 0xf0 ; AL0: directory sector allocation bitmask byte 0 + dw 950 ; DSM: (disk bytes / block bytes) - 1, change alv0x etc if you change this; this is the number of the last sector on the disk, excluding system tracks (ie more system tracks -> this gets smaller) + dw 511 ; DRM: directory max entries - 1 + db 0xc0 ; AL0: directory sector allocation bitmask byte 0 db 0x00 ; AL1: directory sector allocation bitmask byte 1 dw 0 ; CKS: check size (change chk0x etc if you change this) dw 1 ; OFF: track offset (number of system tracks) @@ -153,12 +122,16 @@ boot: ; Cold boot out (7),a ; Map 3, NMI disabled ld sp,0x100 ; Put our stack in the default DMA buffer - ; Zero all memory (just in case) - ld hl,0 - ld de,1 - ld bc,bios-1 - ld (hl),l + ; Zero all memory (just in case). This intentionally + ; wraps around the end of memory. + ld ix,(currow) + xor a + ld hl,zero + ld de,zero+1 + ld bc,bios-zero-1 + ld (hl),a ldir + ld (currow),ix ; say hello ld hl,bootmsg @@ -293,6 +266,7 @@ conout: ; write chracter from C to console jr z,con_cr ; Fall through con_print: + and 07Fh call con_getaddr di ld a,4 ; Map 0, NMI off @@ -443,17 +417,24 @@ seldsk: ; select disk indicated by register C ld a, c cp ndisks ret nc ; return (with error code) if C >= ndisks ie illegal drive - ld (curdisk), a ; store current disk + or 24h*2 ; +4 for volume, CP/M mode, C flag <- 0 + rra + ld (curdisk), a ; store current ABC volume number + CP/M flag + ld a,h ; H = 0! + jr nc,sd1 + ld a,119 +sd1: ld (curxtrk), a ; store track offset (+119 for odd volume) ; compute proper disk parameter header address in HL - add a,a ; *2 - add a,a ; *4 - add a,a ; *8 - add a,a ; *16 - add a,dpbase & 0xff - ld l,a - ld h,dpbase/256 - ; HL = dpbase + disk number * 16 - ret + + ; Each allocation vector is 120 bytes long + ld a,120 + ld e,c + ld d,h ; = 0 + ld hl,alv + call multiply_add + ld (dp_alv),hl + ld hl,dpbase + ret home: ld bc, 0 ; fall through into seltrk @@ -477,24 +458,26 @@ setdma: ; set DMA address given by BC ret read: ; read a sector from disk - ; XXX: add error handing! + ; XXX: add error handing before trying to read back data ld c,03h ; READ + SECTOR TO HOST call sendcmd ld hl,(curdmaaddr) ld bc,128*256+0 inir - xor a ; Success! +end_op: + in a,(1) + rrca + jr nc,end_op + in a,(0) ; 0 = OK ret write: ; write sector to disk - ; XXX: add error handing! ld c,0Ch ; SECTOR FROM HOST + WRITE call sendcmd ld hl,(curdmaaddr) ld bc,128*256+0 otir - xor a ; Success! - ret + jr end_op ; Send a controller command, C = K0 command byte ; Clobbers A DE HL, returns with disk selected @@ -503,8 +486,7 @@ sendcmd: out (1),a ; Select disk out (2),a ; Start command - ld a,(curdisk) ; curdisk - or 24h ; +4 for volume, CP/M mode + ld a,(curdisk) ; curdisk + 24h ld e,a ld a,(cursector) srl a @@ -524,6 +506,9 @@ bc1: rr d or d ld h,a + ld a,(curxtrk) + add a,l + ld l,a ; Now: K0 = C, K1 = E, K2 = L, K3 = H sc_wait1: @@ -547,26 +532,34 @@ sc_wait_ok: ret c jr sc_wait_ok -bootmsg: db "CP/M BIOS (H. Peter Anvin, 2014-05-09)\r\n" +multiply_add: ; HL <- HL + DE * A, trashes B + ld b,8 +m1: + rrca + jr nc,m2 + add hl,de +m2: + sla e + rl d + djnz m1 + ret + +bootmsg: db "CP/M BIOS (H. Peter Anvin, 2014-06-01)\r\n" db "CP/M 2.2 Copyright 1979 (c) by Digital Research\r\n" +zero: db 0 -;--------------------------------------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------- -; scratch RAM used by BIOS -curdisk: db 0 -cursector: db 0 -curtrack: dw 0 -curdmaaddr: dw 0 -conflag: db 0 +; scratch RAM (BSS) used by BIOS +curdisk: db 0 +curxtrk: db 0 +cursector: db 0 +curtrack: dw 0 +curdmaaddr: dw 0 +conflag: db 0 ; scratch RAM used by BDOS dirbf: ds 128 ; directory scratch area -alv00: ds 239 ; allocation vector for disk 0, must be (DSM/8)+1 byte -alv01: ds 239 ; allocation vector for disk 1, must be (DSM/8)+1 bytes -alv02: ds 239 ; allocation vector for disk 2, must be (DSM/8)+1 bytes -alv03: ds 239 ; allocation vector for disk 3, must be (DSM/8)+1 bytes -chk00: ds 0 ; check vector for disk 0 (must be CKS bytes long) -chk01: ds 0 ; check vector for disk 1 (must be CKS bytes long) -chk02: ds 0 ; check vector for disk 2 (must be CKS bytes long) -chk03: ds 0 ; check vector for disk 3 (must be CKS bytes long) +alv: ds 120*ndisks ; allocation vectors, each (DSM/8)+1 byte +csv: ds 0*ndisks ; check vectors, each CKS bytes diff --git a/data/cpm.asm b/data/cpm.asm index 061a3c3..0e7bdbd 100644 --- a/data/cpm.asm +++ b/data/cpm.asm @@ -14,8 +14,8 @@ ; CP/M loader for ABC80-DE1 ; HDSEL: equ 36 -RAMSIZE: equ 64 -BIAS: equ (64-20)*1024-512 +RAMSIZE: equ 63 +BIAS: equ (RAMSIZE-20)*1024 CPMBIOS: equ BIAS+4A00h ABCCURSOR: equ 65011 CPMCURSOR: equ 0FFFEh @@ -36,15 +36,6 @@ _start: ld bc,bios_size ldir - ; Zero memory above the BIOS - ld l,e - ld h,d - inc de - ld bc,CPMCURSOR-(CPMBIOS+bios_size)-1 - xor a - ld (hl),a - ldir - jp CPMBIOS bios: diff --git a/data/cpm22.asm b/data/cpm22.asm index 039dc59..90b6c96 100644 --- a/data/cpm22.asm +++ b/data/cpm22.asm @@ -11,8 +11,7 @@ ; Set memory limit here. This is the amount of contigeous ; ram starting from 0000. CP/M will reside at the end of this space. ; -MEM: EQU 64 ;for a 64k system (TS802 TEST - WORKS OK). -XBIOS: EQU 512 ;extra space for BIOS +MEM: EQU 63 ;for a 64k system (TS802 TEST - WORKS OK). ; IOBYTE: EQU 3 ;i/o definition byte. TDRIVE: EQU 4 ;current drive name and user number. @@ -40,7 +39,7 @@ DEL: EQU 7FH ;rubout ; ; Set origin for CP/M ; - ORG (MEM-7)*1024-XBIOS + ORG (MEM-7)*1024 ; CBASE: JP COMMAND ;execute command processor (ccp). JP CLEARBUF ;entry to empty input buffer before starting ccp. |