155 lines
5.5 KiB
Plaintext
155 lines
5.5 KiB
Plaintext
|
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
|