os-z80/initrd_driver.z80
2023-02-03 09:24:28 -06:00

163 lines
2.7 KiB
Z80 Assembly

.global _start
_start:
call find_disk
ld a, 7
call 0xdffd
push hl
ld de, 0
ld a, 8
call 0xdffd
pop hl
ld (mailbox_num), hl
msg_loop:
call yield
yield_back:
ld hl, (mailbox_num)
ld a, 6
call 0xdffd
msg_read:
push bc
push de
push hl
ld b, c
ld c, 0xB
call set_frame
ld a, h
or 0xB0
ld h, a
ld c, (hl)
inc hl
ld b, (hl)
inc hl
ld e, (hl)
inc hl
ld d, (hl)
ld hl, 0xB000
jp read_bytes
ld hl, (0xB004) ; Load destination mailbox into HL
pop ix
pop de
pop bc
ld a, 5
call 0xdffd
halt
jp msg_loop
halt
read_buf: .ds.b 512
;Given a starting byte number in BC, a byte count in DE, and a destination address in HL, reads those bytes off the disk
read_bytes:
ld (start_byte), bc
ld (byte_count), de
ld (dest_addr), hl
ld c, 0
ld d, 0
ld e, b
ld hl, sec_buf
call read_sector
ld hl, sec_buf
ld b, 0 ; Load BC with lower byte of start_byte (sector offset)
ld a, (start_byte)
ld c, a
add hl, bc ; Add the offset to the buffer address
ld de, (dest_addr)
ld a, (start_byte) ; A = 255 - offset + 1 (256-offset)
ld b, a
ld a, 0xFF
sub b
inc a
ld b, 0 ; Load bc with the value in A
ld c, a
ldir
start_sec_trns_done:
ld (dest_addr), de
ld a, (start_byte) ; A = 255 - offset + 1 (256-offset)
ld b, a
ld a, 0xFF
sub b
inc a
ld b, 0 ; Load bc with the value in A
ld c, a
ld hl, (byte_count)
scf
ccf
sbc hl, bc
ld (rem_bytes), hl
ld b, h
ld c, 0
ld d, 0
ld a, (start_byte+1)
inc a
ld e, a
ld hl, (dest_addr)
sector_loop:
push bc
call read_sector
inc de
pop bc
djnz sector_loop
ld (dest_addr), hl
ld hl, (sec_buf)
call read_sector
ld hl, (sec_buf)
ld de, (dest_addr)
ld b, 0
ld a, (rem_bytes)
ld c, a
ldir
read_bytes_done:
ret
start_byte: .ds.b 2
byte_count: .ds.b 2
dest_addr: .ds.b 2
rem_bytes: .ds.b 2
sec_buf: .ds.b 256
; Given a sector number in C:DE and a buffer address in HL, reads the sector off disk.
; Clobbers A, BC, HL
read_sector:
push bc
ld c,0xFF ; Force the top half of the IO address to be the id of the card,
ld a, (disk_num) ; so the block transfer instructions can be used
out (c), a
pop bc
ld a, c
ld c, 0
out (c), e
inc c
out (c), d
inc c
out (c), a
ld b, 0x0 ; Setup a transfer of 256 bytes (1 sector) at a time
ld c, 0x3 ; from the storage device's data port
inir
ld c,0xFF ; Unforce the top half of the IO address
in a,(c)
read_sec_done:
ret
.global find_disk
; Clobbers A and HL
find_disk:
ld b,0x4
call find_first_card
ld a, l
ld (disk_num), a
ret
disk_num: .ds.b 1
mailbox_num: .ds.b 2
/* Start sector: Start byte / 256 */
/* Offset in start sector: Start byte % 256 */
/* Rem bytes: Byte count - (256 - Offset in start sector) */
/* Middle sectors start: start sector + 1 */
/* Middle sectors count: Rem bytes / 256 */
/* End sector: Middle sectors start + Middle sectors count */
/* End sector copy length: Rem bytes % 256 */