os-z80/kernel/ipc.z80

299 lines
3.6 KiB
Z80 Assembly

.global mb_send
; Sends a message to the MB whose ID is in HL,
; with the message pointer in C:DE:IX
; Returns 0 in B if it sent the mesage, of 1 if the box was full
mb_send:
push de
push bc
push ix
call get_mb_ptr
pop ix
pop bc
pop de
push ix
push hl
pop ix
pop hl
ld ixl, 0xFC
ld a, (ix+0)
inc a
cp 42
jp nz, no_wrap
ld a, 0
no_wrap:
ld b, (ix+1)
cp b
jp nz, mb_not_full
ld b, 1
ret
mb_not_full:
ld a, (ix+0)
ld ixl, 0
ld b, a
sla a
sla a
sla b
add a, b
ld ixl, a
ld (ix+0), c
ld (ix+1), e
ld (ix+2), d
ld (ix+3), l
ld (ix+4), h
ld ixl, 0xFC
ld a, (ix+0)
inc a
cp 42
jp nz, mbs_no_wrap
ld a, 0
mbs_no_wrap:
ld (ix+0), a
ld b, 0
ret
.global mb_read
;Reads a message from the MB specified in HL,
; and returns the pointer in C:DE:HL.
; Returns 0 in B if the mailbox had a message, and 1 if it was full
mb_read:
call get_mb_ptr
mb_read_gmbp_done:
push hl
pop ix
ld ixl, 0xFC
ld a, (ix+1)
ld b, (ix+0)
ld ixl, 0x0
cp b
jp nz, mb_not_empty
ld b, 1
ret
mb_not_empty:
ld b, a
sla a
sla a
sla b
add a, b
ld ixl, a
ld c, (ix+0)
ld e, (ix+1)
ld d, (ix+2)
ld l, (ix+3)
ld h, (ix+4)
ld ixl, 0xFC
ld a, (ix+1)
inc a
cp 42
jp nz, mbr_no_wrap
ld a, 0
mbr_no_wrap:
ld (ix+1), a
ld b, 0
ret
.global get_free_mailbox
; Gets a free mailbox
; ID is returned in HL
get_free_mailbox:
ld a, (mb_free_list)
cp 0
jp nz, gfm_list_not_empty
ld a, (mb_free_list+1)
cp 0
jp nz, gfm_list_not_empty
gfm_list_empty:
ld hl, (mb_next_frame_num)
add hl, hl
add hl, hl
add hl, hl
add hl, hl
push hl
ld bc, (mb_next_frame_num)
inc bc
ld (mb_next_frame_num), bc
call get_mb_ptr
push hl
pop ix
pop hl
push hl
inc hl
/* push hl */
/* pop iy */
link_loop:
ld (ix + 0), l
ld (ix + 1), h
inc hl
inc ixh
ld a, ixh
cp 0xef
jp nz, link_loop
link_loop_done:
ld (ix + 0), 0
ld (ix + 1), 0
pop hl
ld (mb_free_list), hl
ld bc, (mb_free_list)
inc bc
ld (mb_free_list), bc
ret
gfm_list_not_empty:
ld a, (mb_free_list)
ld (temp), a
ld a, (mb_free_list + 1)
ld (temp + 1), a
ld hl, (mb_free_list)
call get_mb_ptr
push hl
pop ix
ld a, (ix + 0)
ld (mb_free_list), a
ld a, (ix + 1)
ld (mb_free_list + 1), a
ld hl, (temp)
ret
; Clobbers A, BC, DE, and IX
get_mb_ptr:
ld a, h
srl a
srl a
srl a
srl a
srl a
srl a
ld b, a
sla a
add a, b
ld ix, mb_frame_list_frames
ld b, 0
ld c, a
add ix, bc
ld b, (ix + 0)
ld a, b
cp 0
jp z, gmbp_no_frame_list_frame
ld b, (ix + 0)
ld e, (ix + 1)
ld d, (ix + 2)
ld c, 0xE
push ix
call set_frame
pop ix
gmbp_has_frame_list_frame:
push hl
ld a, h
and 0x3F
ld h, a
srl h
rr l
srl h
rr l
ld a, l
and 0xFC
ld l, a
ld a, h
or 0xE0
ld h, a
ld b, (hl)
ld a, b
cp 0
jp z, gmbp_no_frame
inc hl
ld e, (hl)
inc hl
ld d, (hl)
ld c, 0xE
call set_frame
gmbp_has_frame:
pop hl
ld a, l
and 0xF
or 0xE0
ld h, a
ld l, 0x0
gmbp_done:
ret
gmbp_no_frame_list_frame:
push hl
push ix
call get_free_frame
pop ix
push hl
pop de
ld (ix + 0), c
ld (ix + 1), e
ld (ix + 2), d
pop hl
ld b, c
ld c, 0xE
push ix
call set_frame
pop ix
push bc
push de
push hl
ld bc, 0x1000
ld de, 0xE000
ld h, d
ld l, e
ld (hl), 0 ; Zero out the first byte in the segment ( Acts as a 'seed' for the zeroing )
ldir
gbmp_no_flf_zeroed:
pop hl
pop de
pop bc
jp gmbp_has_frame_list_frame
gmbp_no_frame:
push hl
push ix
call get_free_frame
pop ix
push hl
pop de
pop hl
push bc
push de
ld b, (ix + 0)
ld e, (ix + 1)
ld d, (ix + 2)
ld c, 0xE
call set_frame
pop de
pop bc
ld (hl), c
inc hl
ld (hl), e
inc hl
ld (hl), d
dec hl
dec hl
ld b, c
ld c, 0xE
push ix
call set_frame
pop ix
push bc
push de
push hl
ld bc, 0x1000
ld de, 0xE000
ld h, d
ld l, e
ld (hl), 0 ; Zero out the first byte in the segment ( Acts as a 'seed' for the zeroing )
ldir
gbmp_no_f_zeroed:
pop hl
pop de
pop bc
jp gmbp_has_frame
temp: .ds.b 5
mb_free_list: .ds.b 2
mb_frame_list_frames: .ds.b 3*4
mb_next_frame_num: .ds.b 2