kernel/initrd.68k

155 lines
5.5 KiB
Plaintext
Raw Normal View History

2024-03-19 09:23:45 -05:00
STORAGE_SEC equ $0
STORAGE_CNT equ $4
STORAGE_CMD equ $8
STORAGE_DMADR equ $C
include cards.i
include string.i
include memory.i
section .text,text
; Initialize the initrd reader
public initrd_init
initrd_init:
move.w #$4, d0 ; Get the pointer to the MMU card
jsr find_first_card
move.l a0, storage_card_base
rts
; Get the start byte for a specific file in the initrd
; Pointer to name in a0
; Number returned in d0, or 0 if not found
public initrd_find_file
initrd_find_file:
movem.l d2/a2, -(a7)
move.l a0, a2 ; Save the name pointer in a2
move.l #512, d0 ; Allocate a buffer to read sectors into
jsr malloc
move.l a0, a1 ; Save the buffer pointer in a1
move.l #1, d0 ; Set the first sector to read
iff_loop:
movem.l d0/a1, -(a7)
move.l storage_card_base, a0 ; Read a file header sector
move.l #1, d1
bsr.b read_sectors
movem.l (a7)+, d0/a1
move.l (a1), d2 ; Abort with a 0 return if we have reached the end of the initrd
bne.b .1
move.l #0, d0
bra.b iff_done
.1:
movem.l d0/a1, -(a7)
move.l a2, a0 ; Compare the passed in file name with the one in the header sector
adda.l #12, a1
jsr strcmp
movem.l (a7)+, d0/a1
bne.b .2 ; Continue to the next file if the name doesn't match
addi.l #1, d0 ; Add one to the current sector number to get the start sector of the file
lsl.l #8, d0 ; Shift the sector number left by 9 to get the start byte of the file
lsl.l #1, d0
movem.l (a7)+, d2/a2
rts
.2:
; Add the # of sectors of file data + 1 to the sector number to advance to the next header sector
addi.l #1, d0
move.l (4,a1), d2
add.l d2, d0
bra.b iff_loop
iff_done:
movem.l (a7)+, d2/a2
rts
; Reads bytes of a file from the initrd
; Start byte of file in d0
; Offset in d1
; Length in d2
; Buffer in a0
public initrd_read_bytes
initrd_read_bytes:
add.l d1, d0
move.l d2, d1
move.l a0, a1
move.l storage_card_base, a0
bra.b read_bytes
; Reads sectors from a storage card
; Card base in a0
; Destination in a1
; Start sector in d0.l
; Sector count in d1.l
read_sectors:
cmpi.l #0, d1 ; Do nothing if asked to read 0 sectors
beq.b read_sectors_done
move.l d0, (STORAGE_SEC,a0) ; Set the sector number
move.l d1, (STORAGE_CNT,a0) ; Set the sector count
move.l a1, (STORAGE_DMADR,a0) ; Set the destination address
move.w #$1, (STORAGE_CMD,a0) ; Issue a DMA read command
read_sectors_done:
rts
; Reads bytes off a storage card
; Card base in a0
; Destination in a1
; Start byte in d0.l
; Byte count in d1.l
read_bytes:
movem.l d2-d5/a2/a3,-(a7) ; Save callee preserved registers
move.l d0, d4 ; Save start byte in d4
move.l d1, d5 ; Save byte count in d5
move.l a1, a3 ; Save destination in a6
lsr.l #8, d0 ; Divide start byte by 512 to compute starting sector
lsr.l #1, d0
move.l d0, d3 ; Save the starting sector in d3
move.l #1, d1 ; Read the starting sector into the sector buffer
move.l #sec_buf, a1
bsr.b read_sectors
move.l a3, a2 ; Load the destination into a2
move.l d4, d0 ; Load the start byte into d0
andi.l #$1FF, d0 ; Modulus start byte by 512 to compute sector data offset
adda.l d0, a1 ; Add the offset to the start of the sector buffer
move.l #$200, d1 ; Compute the number of bytes to transfer by subtracting the offset from 512
sub.l d0, d1
cmp d5, d1 ; Compare the number of bytes to transfer with the byte count
ble.b count_ok ; If it was less than the byte count, do not adjust the bytes to transfer
move.l d5, d1 ; Otherwise, cap the transfer count to the total byte count
count_ok:
move.l d1, d4 ; Save the number of bytes in d4
subi.l #1, d1 ; Subtract 1 from the number of bytes to account for the extra loop done by dbra
start_sec_loop: ; Transfer the required bytes from the start sector to the destination buffer
move.b (a1)+, (a2)+
dbra d1, start_sec_loop
move.l d3, d0 ; Load the starting sector into d0
addi #1, d0 ; Compute the start of the middle sectors by adding 1 to the starting sector
move.l d4, d2 ; Load the number of bytes transferred into d2
move.l d5, d1 ; Load the byte count into d1
sub.l d2, d1 ; Compute the number of remaining bytes by subtracting the number of transferred bytes from the byte count
cmpi.l #0, d1 ; If there are no more bytes to read, end early
beq.b read_bytes_done
move.l d1, d4 ; Save the number of remaining bytes in d4
lsr.l #8, d1 ; Divide remaining bytes by 512 to compute the number of middle sectors
lsr.l #1, d1
move.l a2, a1 ; Transfer the sector data to the end of the start sector bytes
bsr.b read_sectors ; Read the middle sectors
move.l d1, d3 ; Save the number of middle sectors in d3
lsl.l #8, d1 ; Multiply the number of middle sectors by 512 to compute the number of bytes transferred
lsl.l #1, d1
sub.l d1, d4 ; Subtract the number of transferred bytes from the number of remaining bytes
cmpi.l #0, d4 ; If there are no more bytes to read, end early
beq.b read_bytes_done
adda.l d1, a2 ; Add the number of bytes transferred to a2
add.l d3, d0 ; Compute the end sector number by adding the start and count of the middle sectors
move.l #1, d1 ; Set the number of sectors to read to 1
move.l #sec_buf, a1 ; Set the read address of the sector to the sector buffer
bsr.w read_sectors ; Read the end sector
move.l d4, d1 ; Load the number of remaining bytes into d1
end_sec_loop: ; Transfer the required bytes from the start sector to the destination buffer
move.b (a1)+, (a2)+
dbra d1, end_sec_loop
read_bytes_done:
movem.l (a7)+, d2-d5/a2/a3 ; Restore callee preserved registers
rts
section .bss,bss
storage_card_base: ds.b 4
sec_buf: ds.b 512