From 73c3fc79474e450bbd37ef9d07072849458edf50 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 2 Jun 2019 10:50:18 -0400 Subject: [PATCH] shell/stdio: decouple from blkdev (again) Move load/save to blkdev_cmds and add a new "poke" builtin shell cmd that is the mirror of "peek" and strictly uses stdio (no blkdev involved). This allows us to slim the minimal OS size but, more importantly, change the behavior of "load" so that we don't expect GetC to block until Z is set. This way, using "load X" with X being larger than the blkdev size won't block forever. This also brings our RC2014 minimal kernel below the 1K mark again. --- kernel/blockdev.asm | 2 ++ kernel/blockdev_cmds.asm | 57 +++++++++++++++++++++++++++++++++++ kernel/shell.asm | 60 ++++++++++--------------------------- kernel/stdio.asm | 17 ++++------- recipes/rc2014/glue.asm | 13 ++------ tools/emul/shell/shell_.asm | 18 +++++------ tools/upload.py | 6 ++-- 7 files changed, 92 insertions(+), 81 deletions(-) diff --git a/kernel/blockdev.asm b/kernel/blockdev.asm index baa8f7a..b9d0544 100644 --- a/kernel/blockdev.asm +++ b/kernel/blockdev.asm @@ -150,7 +150,9 @@ blkGetC: blkGetCW: ld ix, (BLOCKDEV_GETC) .loop: + push ix ; fs messes with IX a lot call callIX + pop ix jr nz, .loop ret diff --git a/kernel/blockdev_cmds.asm b/kernel/blockdev_cmds.asm index 7d8a4d2..a957414 100644 --- a/kernel/blockdev_cmds.asm +++ b/kernel/blockdev_cmds.asm @@ -44,3 +44,60 @@ blkSeekCmd: xor a ret +; Load the specified number of bytes (max 0xff) from IO and write them in the +; current memory pointer (which doesn't change). This gets chars from +; blkGetCW. +; Control is returned to the shell only after all bytes are read. +; +; Example: load 42 +blkLoadCmd: + .db "load", 0b001, 0, 0 +blkLoad: + push bc + push hl + + ld a, (hl) + ld b, a + ld hl, (SHELL_MEM_PTR) +.loop: call blkGetCW + jr nz, .ioError + ld (hl), a + inc hl + djnz .loop + ; success + xor a + jr .end +.ioError: + ld a, SHELL_ERR_IO_ERROR +.end: + pop hl + pop bc + ret + +; Load the specified number of bytes (max 0xff) from the current memory pointer +; and write them to I/O. Memory pointer doesn't move. This puts chars to +; blkPutC. +; Control is returned to the shell only after all bytes are written. +; +; Example: save 42 +blkSaveCmd: + .db "save", 0b001, 0, 0 +blkSave: + push bc + push hl + + ld a, (hl) + ld b, a + ld hl, (SHELL_MEM_PTR) +.loop: + ld a, (hl) + inc hl + call blkPutC + djnz .loop + +.end: + pop hl + pop bc + xor a + ret + diff --git a/kernel/shell.asm b/kernel/shell.asm index 3f6c28e..ef75807 100644 --- a/kernel/shell.asm +++ b/kernel/shell.asm @@ -22,7 +22,6 @@ ; *** REQUIREMENTS *** ; parse ; stdio -; blkdev ; *** DEFINES *** ; SHELL_EXTRA_CMD_COUNT: Number of extra cmds to be expected after the regular @@ -32,7 +31,7 @@ ; *** CONSTS *** ; number of entries in shellCmdTbl -.equ SHELL_CMD_COUNT 7+SHELL_EXTRA_CMD_COUNT +.equ SHELL_CMD_COUNT 6+SHELL_EXTRA_CMD_COUNT ; maximum number of bytes to receive as args in all commands. Determines the ; size of the args variable. @@ -411,58 +410,29 @@ shellPeek: xor a ret -; Load the specified number of bytes (max 0xff) from IO and write them in the -; current memory pointer (which doesn't change). This gets chars from -; blkGetCW. -; Control is returned to the shell only after all bytes are read. -; -; Example: load 42 -shellLoadCmd: - .db "load", 0b001, 0, 0 -shellLoad: +; poke byte where memory pointer points and set them to bytes types through +; stdioGetC. If the optional numerical byte arg is supplied, this number of +; bytes will be expected from stdioGetC. Blocks until all bytes have been +; fetched. +shellPokeCmd: + .db "poke", 0b101, 0, 0 +shellPoke: push bc push hl ld a, (hl) + or a ; cp 0 + jr nz, .arg1isset ; if arg1 is set, no need for a default + ld a, 1 ; default for arg1 +.arg1isset: ld b, a ld hl, (SHELL_MEM_PTR) -.loop: call blkGetCW - jr nz, .ioError +.loop: call stdioGetC + jr nz, .loop ; nothing typed? loop ld (hl), a inc hl djnz .loop - ; success - xor a - jr .end -.ioError: - ld a, SHELL_ERR_IO_ERROR -.end: - pop hl - pop bc - ret -; Load the specified number of bytes (max 0xff) from the current memory pointer -; and write them to I/O. Memory pointer doesn't move. This puts chars to -; blkPutC. -; Control is returned to the shell only after all bytes are written. -; -; Example: save 42 -shellSaveCmd: - .db "save", 0b001, 0, 0 -shellSave: - push bc - push hl - - ld a, (hl) - ld b, a - ld hl, (SHELL_MEM_PTR) -.loop: - ld a, (hl) - inc hl - call blkPutC - djnz .loop - -.end: pop hl pop bc xor a @@ -530,6 +500,6 @@ shellIOWRCmd: ; This table is at the very end of the file on purpose. The idea is to be able ; to graft extra commands easily after an include in the glue file. shellCmdTbl: - .dw shellMptrCmd, shellPeekCmd, shellLoadCmd, shellSaveCmd, shellCallCmd + .dw shellMptrCmd, shellPeekCmd, shellPokeCmd, shellCallCmd .dw shellIORDCmd, shellIOWRCmd diff --git a/kernel/stdio.asm b/kernel/stdio.asm index 683e064..8b79d27 100644 --- a/kernel/stdio.asm +++ b/kernel/stdio.asm @@ -1,12 +1,9 @@ ; stdio ; -; Allows other modules to print to "standard out", that is, the console through -; which the user is connected in a decoupled manner. +; Allows other modules to print to "standard out", and get data from "stamdard +; in", that is, the console through which the user is connected in a decoupled +; manner. ; -; *** REQUIREMENTS *** -; blkdev. select the block device you want to use as stdio just before you call -; stdioInit. - ; *** VARIABLES *** ; Used to store formatted hex values just before printing it. .equ STDIO_HEX_FMT STDIO_RAMSTART @@ -14,14 +11,10 @@ .equ STDIO_PUTC STDIO_GETC+2 .equ STDIO_RAMEND STDIO_PUTC+2 -; Select the blockdev to use as stdio before calling this. +; Sets GetC to the routine where HL points to and PutC to DE. stdioInit: - push hl - ld hl, (BLOCKDEV_GETC) ld (STDIO_GETC), hl - ld hl, (BLOCKDEV_PUTC) - ld (STDIO_PUTC), hl - pop hl + ld (STDIO_PUTC), de ret stdioGetC: diff --git a/recipes/rc2014/glue.asm b/recipes/rc2014/glue.asm index 7a55b04..da1c3ed 100644 --- a/recipes/rc2014/glue.asm +++ b/recipes/rc2014/glue.asm @@ -16,13 +16,7 @@ jp aciaInt .equ ACIA_RAMSTART RAMSTART #include "acia.asm" -.equ BLOCKDEV_RAMSTART ACIA_RAMEND -.equ BLOCKDEV_COUNT 1 -#include "blockdev.asm" -; List of devices -.dw aciaGetC, aciaPutC, 0, 0 - -.equ STDIO_RAMSTART BLOCKDEV_RAMEND +.equ STDIO_RAMSTART ACIA_RAMEND #include "stdio.asm" .equ SHELL_RAMSTART STDIO_RAMEND @@ -37,9 +31,8 @@ init: im 1 call aciaInit - xor a - ld de, BLOCKDEV_GETC - call blkSel + ld hl, aciaGetC + ld de, aciaPutC call stdioInit call shellInit ei diff --git a/tools/emul/shell/shell_.asm b/tools/emul/shell/shell_.asm index cc139b0..643a89d 100644 --- a/tools/emul/shell/shell_.asm +++ b/tools/emul/shell/shell_.asm @@ -17,10 +17,9 @@ #include "parse.asm" .equ BLOCKDEV_RAMSTART RAMSTART -.equ BLOCKDEV_COUNT 4 +.equ BLOCKDEV_COUNT 3 #include "blockdev.asm" ; List of devices -.dw emulGetC, emulPutC, 0, 0 .dw fsdevGetC, fsdevPutC, fsdevSeek, fsdevTell .dw stdoutGetC, stdoutPutC, stdoutSeek, stdoutTell .dw stdinGetC, stdinPutC, stdinSeek, stdinTell @@ -36,9 +35,10 @@ #include "fs_cmds.asm" .equ SHELL_RAMSTART FS_RAMEND -.equ SHELL_EXTRA_CMD_COUNT 7 +.equ SHELL_EXTRA_CMD_COUNT 9 #include "shell.asm" -.dw blkBselCmd, blkSeekCmd, fsOnCmd, flsCmd, fnewCmd, fdelCmd, fopnCmd +.dw blkBselCmd, blkSeekCmd, blkLoadCmd, blkSaveCmd +.dw fsOnCmd, flsCmd, fnewCmd, fdelCmd, fopnCmd .equ PGM_CODEADDR USERCODE #include "pgm.asm" @@ -48,18 +48,14 @@ init: ; setup stack ld hl, KERNEL_RAMEND ld sp, hl - xor a - ld de, BLOCKDEV_GETC - call blkSel + ld hl, emulGetC + ld de, emulPutC call stdioInit call fsInit - ld a, 1 ; select fsdev + ld a, 0 ; select fsdev ld de, BLOCKDEV_GETC call blkSel call fsOn - xor a ; select ACIA - ld de, BLOCKDEV_GETC - call blkSel call shellInit ld hl, pgmShellHook ld (SHELL_CMDHOOK), hl diff --git a/tools/upload.py b/tools/upload.py index 0f8a27c..58f0931 100755 --- a/tools/upload.py +++ b/tools/upload.py @@ -32,8 +32,8 @@ def main(): print("File too big. 0xff bytes max") return 1 fd = os.open(args.device, os.O_RDWR) - sendcmd(fd, 'load {:x}'.format(st.st_size).encode()) - print("Loading...") + sendcmd(fd, 'poke {:x}'.format(st.st_size).encode()) + print("Poking...") with open(args.filename, 'rb') as fp: fcontents = fp.read() for c in fcontents: @@ -41,7 +41,7 @@ def main(): # Let's give the machine a bit of time to breathe. We ain't in a # hurry now, are we? time.sleep(0.0001) - print("Loaded") + print("Poked") os.read(fd, 5) print("Peeking back...") sendcmd(fd, 'peek {:x}'.format(st.st_size).encode())