os-z80/initrd_driver.z80
2023-09-03 10:03:51 -05:00

207 lines
3.2 KiB
Z80 Assembly

.global _start
_start:
call find_disk
call get_free_mailbox
push hl
ld de, 0
pms_call:
call proc_map_set
pop hl
ld (mailbox_num), hl
msg_loop:
call yield
yield_back:
ld hl, (mailbox_num)
call mb_read
mb_read_done:
ld a, b
cp 1
jp z, msg_loop
msg_read:
push bc
push de
push hl
ld b, c
ld c, 0xB
call set_frame
set_frame_done:
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, (0xB004) ; Load destination mailbox into HL and save it on the stack
push hl
ld hl, 0xB000
call read_bytes
pop hl
pop ix
pop de
pop bc
ld a, 5
call 0xdffd
jp msg_loop
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
ld b, 0 ; Load bc with the value in A
ld c, a
inc bc
push de
ld de, (byte_count)
ld a, b
cp d
jp c, count_ok_1
ld a, c
cp e
jp c, count_ok_1
push de
pop bc
count_ok_1:
pop de
ld a, b
cp 0
jp nz, nz_ok
ld a, c
cp 0
jp nz, nz_ok
jp no_transfer
nz_ok:
ldir
no_transfer:
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
ld b, 0 ; Load bc with the value in A
ld c, a
inc bc
push de
ld de, (byte_count)
ld a, b
cp d
jp c, count_ok_2
ld a, c
cp e
jp c, count_ok_2
push de
pop bc
count_ok_2:
pop de
ld hl, (byte_count)
scf
ccf
sbc hl, bc
ld (rem_bytes), hl
ld a, h
cp 0
jp z, no_transfer_2
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
no_transfer_2:
ld a, (rem_bytes)
cp 0
jp z, read_bytes_done
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 */