1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-08 14:48:08 +11:00
collapseos/parts/blockdev.asm

112 lines
2.3 KiB
NASM
Raw Normal View History

; blockdev
;
; A block device is an abstraction over something we can read from, write to.
;
; A device that fits this abstraction puts the properly hook into itself, and
; then the glue code assigns a blockdev ID to that device. It then becomes easy
; to access arbitrary devices in a convenient manner.
;
; This part exposes a new "bsel" command to select the currently active block
; device.
; *** DEFINES ***
; BLOCKDEV_COUNT: The number of devices we manage.
; *** CONSTS ***
2019-04-16 10:38:25 +10:00
BLOCKDEV_ERR_OUT_OF_BOUNDS .equ 0x03
; *** VARIABLES ***
; A memory pointer to a device table. A device table is a list of addresses
; pointing to GetC, PutC and Seek routines.
BLOCKDEV_TBL .equ BLOCKDEV_RAMSTART
; Pointer to the selected block device. A block device is a 6 bytes block of
; memory with pointers to GetC, PutC and Seek routines, in that order. 0 means
; unsupported.
BLOCKDEV_SEL .equ BLOCKDEV_TBL+(BLOCKDEV_COUNT*2)
BLOCKDEV_RAMEND .equ BLOCKDEV_SEL+2
; *** CODE ***
; set DE to point to the table entry at index A.
blkFind:
ld de, BLOCKDEV_TBL
cp 0
ret z ; index is zero? don't loop
push bc
ld b, a
.loop:
inc de
inc de
djnz .loop
pop bc
ret
; Set the pointer of device id A to the value in HL
blkSet:
call blkFind
call writeHLinDE
ret
; Select block index specified in A
blkSel:
push de
push hl
call blkFind
ld hl, BLOCKDEV_SEL
ex hl, de
ldi
pop hl
pop de
ret
blkBselCmd:
.db "bsel", 0b001, 0, 0
blkBsel:
ld a, (hl) ; argument supplied
cp BLOCKDEV_COUNT
2019-04-16 10:38:25 +10:00
jr nc, .error ; if selection >= device count, error
call blkSel
2019-04-16 10:38:25 +10:00
xor a
ret
.error:
ld a, BLOCKDEV_ERR_OUT_OF_BOUNDS
ret
; In those routines below, IY is destroyed (we don't push it to the stack). We
; seldom use it anyways...
; call routine in BLOCKDEV_SEL with offset IYL.
_blkCall:
push ix
push de
ld de, (BLOCKDEV_SEL)
; DE now points to the *address table*, not the routine addresses
; themselves. One layer of indirection left.
; slide by offset
push af
ld a, iyl
call addDE ; slide by offset
pop af
call intoDE
; Alright, now de points to what we want to call
ld ixh, d
ld ixl, e
pop de
call callIX
pop ix
ret
; Reads one character from blockdev ID specified at A and returns its value
; in A. Always returns a character and waits until read if it has to.
blkGetC:
ld iyl, 0
jr _blkCall
blkPutC:
ld iyl, 2
jr _blkCall
blkSeek:
ld iyl, 4
jr _blkCall