diff options
Diffstat (limited to '')
| -rw-r--r-- | src/blk.asm | 161 | ||||
| -rw-r--r-- | src/boot.asm | 9 | ||||
| -rw-r--r-- | src/programs.asm | 7 | ||||
| -rw-r--r-- | src/syscall.asm | 2 |
4 files changed, 178 insertions, 1 deletions
diff --git a/src/blk.asm b/src/blk.asm new file mode 100644 index 0000000..ea04e95 --- /dev/null +++ b/src/blk.asm @@ -0,0 +1,161 @@ +; ============================================================================= +; blk.asm - persistent block device on battery-backed cart RAM. +; +; The "disk" is cart-RAM banks FS_BANK0.. (256-byte blocks). Blocks are read +; and written through a WRAM bounce buffer, so only read_block/write_block ever +; touch cart-RAM banking; the rest of the filesystem works on WRAM buffers. +; +; block B lives in cart-RAM bank FS_BANK0 + B/32, at $A000 + (B & 31)*256. +; +; After each transfer we remap the current process's own RAM bank, so a syscall +; that does disk I/O leaves the caller's $A000 window exactly as it found it. +; ============================================================================= +INCLUDE "include/gbos.inc" + +SECTION "blk", ROM0 + +; A process's stack lives in the $A000 window too, so while the disk bank is +; mapped there NOTHING may touch the stack (no call/ret/push/pop). The block +; routines therefore inline the "restore my bank" step instead of calling it. +; (MACRO because it must not be a `call`.) +MACRO restore_bank + ld a, [wCurProc] + add PROC_RAMB + ld l, a + ld a, [wCurProc+1] + adc 0 + ld h, a + ld a, [hl] + ld [MBC5_RAMB], a +ENDM + +; ----------------------------------------------------------------------------- +; read_block - in: A = block, HL = dest (WRAM buffer, 256 bytes) +; ----------------------------------------------------------------------------- +read_block:: + ld c, a + srl a + srl a + srl a + srl a + srl a ; A = block / 32 + add FS_BANK0 + ld [MBC5_RAMB], a ; map the disk bank (stack now hidden!) + ld a, c + and 31 + add $A0 + ld d, a + ld e, 0 ; DE = $A000 + (block&31)*256 + ld b, 0 ; 256 bytes +.cp + ld a, [de] + ld [hl+], a + inc de + dec b + jr nz, .cp + restore_bank ; inline - no stack while the disk bank is mapped + ret + +; ----------------------------------------------------------------------------- +; write_block - in: A = block, HL = src (WRAM buffer, 256 bytes) +; ----------------------------------------------------------------------------- +write_block:: + ld c, a + srl a + srl a + srl a + srl a + srl a + add FS_BANK0 + ld [MBC5_RAMB], a + ld a, c + and 31 + add $A0 + ld d, a + ld e, 0 ; DE = dest in the disk bank + ld b, 0 +.cp + ld a, [hl+] + ld [de], a + inc de + dec b + jr nz, .cp + restore_bank + ret + +; ----------------------------------------------------------------------------- +; blk_format - write a fresh superblock (magic) to block 0. (mkfs, stage 1) +; ----------------------------------------------------------------------------- +blk_format:: + ld hl, wCopyBuf ; zero the buffer + ld b, 0 + xor a +.z + ld [hl+], a + dec b + jr nz, .z + ld hl, wCopyBuf + ld a, SUPER_MAG0 + ld [hl+], a + ld a, SUPER_MAG1 + ld [hl+], a + ld a, SUPER_MAG2 + ld [hl+], a + ld a, SUPER_MAG3 + ld [hl], a + ld a, SUPER_BLOCK + ld hl, wCopyBuf + call write_block + ret + +; ----------------------------------------------------------------------------- +; blk_init - format the disk only if it isn't already formatted (magic check). +; Called at boot; the disk otherwise persists across power cycles (.sav). +; ----------------------------------------------------------------------------- +blk_init:: + ld a, SUPER_BLOCK + ld hl, wCopyBuf + call read_block + ld hl, wCopyBuf + ld a, [hl+] + cp SUPER_MAG0 + jr nz, .fmt + ld a, [hl+] + cp SUPER_MAG1 + jr nz, .fmt + ld a, [hl+] + cp SUPER_MAG2 + jr nz, .fmt + ld a, [hl] + cp SUPER_MAG3 + jr nz, .fmt + ret ; already formatted +.fmt + call blk_format + ret + +; ============================================================================= +; [debug] block poke/peek syscalls, to validate the layer + persistence. +; ============================================================================= +; sys_bfill(B = block, E = byte) - fill the whole block with a byte +sys_bfill:: + ld a, e + ld hl, wCopyBuf + ld c, 0 +.f + ld [hl+], a + dec c + jr nz, .f + ld a, b + ld hl, wCopyBuf + call write_block + xor a + ret + +; sys_bpeek(B = block) -> A = block's first byte +sys_bpeek:: + ld a, b + ld hl, wCopyBuf + call read_block + ld a, [wCopyBuf] + ret diff --git a/src/boot.asm b/src/boot.asm index 7c175ce..1f4a048 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -49,7 +49,14 @@ KernelInit: call ClearKernelRAM call CopyHramCode ; move context-switch trampoline into HRAM call ProcInit ; wipe process table - call fs_init ; set up the RAM filesystem + ; point wCurProc at the (zeroed) kernel PCB so disk I/O during boot restores + ; RAM bank 0 after each block transfer (wKernelPCB.PROC_RAMB = 0). + ld a, LOW(wKernelPCB) + ld [wCurProc], a + ld a, HIGH(wKernelPCB) + ld [wCurProc+1], a + call blk_init ; format the disk if needed (persists otherwise) + call fs_init ; (legacy WRAMX filesystem, still used by tools) ; --- spawn the init task (pid 1); it fork()s the rest --- ld hl, TaskInit diff --git a/src/programs.asm b/src/programs.asm index e83d29e..53142ec 100644 --- a/src/programs.asm +++ b/src/programs.asm @@ -97,6 +97,9 @@ ProgKill: SECTION "prog_spin", ROMX[$4000], BANK[20] ProgSpin: INCBIN "c/spin.bin" +SECTION "prog_blk", ROMX[$4000], BANK[21] +ProgBlk: + INCBIN "c/blk.bin" ; ----------------------------------------------------------------------------- ; PROG_SH (bank 3) - the shell, now written in C (c/sh.c): parses >/</| and @@ -177,6 +180,8 @@ ProgramTable:: dw ProgKill db LOW(BANK(ProgSpin)), HIGH(BANK(ProgSpin)) dw ProgSpin + db LOW(BANK(ProgBlk)), HIGH(BANK(ProgBlk)) + dw ProgBlk ; ----------------------------------------------------------------------------- ; NameTable (ROM0) - command name -> program id, searched by sys_lookup. @@ -221,4 +226,6 @@ NameTable:: db PROG_KILL db "spin", 0 db PROG_SPIN + db "blk", 0 + db PROG_BLK db 0 diff --git a/src/syscall.asm b/src/syscall.asm index 2fc66b6..29dc2b0 100644 --- a/src/syscall.asm +++ b/src/syscall.asm @@ -57,6 +57,8 @@ SyscallTable: dw sys_ps ; 20 PS dw sys_progname ; 21 PROGNAME dw sys_reap ; 22 REAP + dw sys_bfill ; 23 BFILL (debug) + dw sys_bpeek ; 24 BPEEK (debug) ; ----------------------------------------------------------------------------- sys_nosys: |
