151 lines
4.8 KiB
Plaintext
151 lines
4.8 KiB
Plaintext
include vmem.i
|
|
include term.i
|
|
include cards.i
|
|
include string.i
|
|
xref _kernel_end_page
|
|
section .text, text
|
|
public pmem_init
|
|
; Initialize the physical memory manager
|
|
pmem_init:
|
|
movem.l d2/d3/d4, -(a7) ; Save old values of d2, d3, and d4 (callee preserved)
|
|
clrfo
|
|
pmem_init.buf: fo.b 12
|
|
link a6, #__FO ; Create a 12-byte stack frame to use as a buffer for hex_to_ascii
|
|
move.w #$1, d0 ; Get the pointer to the ROM card
|
|
jsr find_first_card
|
|
move.w #$C000, ($F0,a0) ; Enable the card at physical address $C0000000
|
|
move.b #$1, ($F3,a0)
|
|
move.l #0, d2 ; Map the beginning of the ROM card's RAM into virtual memory
|
|
move.l #$C0008000, d0
|
|
move.l #$1, d1
|
|
move.l #$2, d3
|
|
jsr vmem_map_free_to
|
|
move.l a0, -(a7) ; Save a0
|
|
move.l a0, a1
|
|
move.l #$1, d0
|
|
jsr vmem_get_free_kernel_pages ; Alocate the stack page
|
|
move.l a0, stack_page_addr
|
|
move.l a0, a1
|
|
move.l #kernel_address_space, a0
|
|
move.l (a7)+, a0 ; Restore a0
|
|
adda.l #($100-$4), a0
|
|
move.l #1, d0 ; d0 holds the physical base address of the RAM card (+ 1 for the enable flag)
|
|
move.l #_kernel_end_page, d4 ; Put the physical address of the last kernel page into d4
|
|
sub.l #$C01000, d4
|
|
ramcard_map_loop:
|
|
lea ($4,a0), a0 ; Move to the next RAM card
|
|
move.l (a0), a1 ; Load the IO base pointer into a1
|
|
cmpa.l #0, a1
|
|
beq.w ramcard_map_loop_done ; If the pointer is 0, we have reached the end of the list, so exit the loop
|
|
move.l d0, (a1) ; Map the card to the base address in d0
|
|
move.l d0, d3 ; Save the base address in d3 for later use
|
|
move.l ($4,a1), d1 ; Advance d0 by the size of the card
|
|
move.l d1, d2 ; Save the card size in d2 for later use
|
|
add.l d1, d0
|
|
movem.l d0/a0, -(a7) ; Save base address and RAM card pointer
|
|
move.l #pmem_log_name, a0 ; Log the mapped RAM card
|
|
jsr term_print
|
|
lea.l (pmem_init.buf,a6), a0 ; Print the card size in bytes
|
|
move.l d2, d0
|
|
jsr hex_to_ascii
|
|
lea.l (pmem_init.buf,a6), a0
|
|
jsr term_print
|
|
move.l #ramcard_log_msg, a0 ; Print " byte RAM card at "
|
|
jsr term_print
|
|
lea.l (pmem_init.buf,a6), a0 ; Print the card base address
|
|
move.l d3, d0
|
|
subi.l #1, d0
|
|
jsr hex_to_ascii
|
|
lea.l (-12,a6), a0
|
|
jsr term_println
|
|
subi.l #1, d3
|
|
rc_map_page_push_loop:
|
|
cmp.l d4, d3 ; If the current physical page is used by the kernel binary, skip it
|
|
bhi.b .1
|
|
add.l #$1000, d3
|
|
sub.l #$1000, d2
|
|
bra.b rc_map_page_push_loop
|
|
.1:
|
|
move.l d3, d0 ; Push the frame in d3 and move to the next one
|
|
jsr pmem_push_frame
|
|
add.l #$1000, d3
|
|
sub.l #$1000, d2
|
|
bne.b rc_map_page_push_loop ; Loop back if this card has more pages to push
|
|
rc_map_pages_pushed:
|
|
movem.l (a7)+, d0/a0 ; Restore base address and RAM card pointer
|
|
bra.w ramcard_map_loop ; Loop back and map the next card
|
|
ramcard_map_loop_done:
|
|
move.l a0, d0
|
|
andi.l #(~$FFF), d0
|
|
move.l d0, a0
|
|
move.l #0, d0
|
|
jsr vmem_unmap_page
|
|
unlk a6 ; Tear down the stack frame
|
|
movem.l (a7)+, d2/d3/d4 ; Restore d2, d3, and d4 (callee preserved)
|
|
rts
|
|
|
|
public pmem_push_frame
|
|
; Pushes a frame onto the stack
|
|
; Frame to push in d0
|
|
pmem_push_frame:
|
|
move.l d0, -(a7)
|
|
move.l #0, d0
|
|
move.l stack_page_addr, a0
|
|
jsr vmem_get_map_ptr
|
|
move.l (a7)+, d0
|
|
move.l (a0), d1 ; Read the mapping entry into d1
|
|
andi.l #(~$FFF), d1 ; Clear the entry's flags to get the pointer to its physical page
|
|
movem.l d1/d2/d3, -(a7)
|
|
; Map the stack page to the frame to push
|
|
move.l #0, d2
|
|
move.l stack_page_addr, a0
|
|
move.l #1, d1
|
|
move.l #$2, d3
|
|
jsr vmem_map_to
|
|
move.l stack_page_addr, a0 ; Clear the TLB entry for the mapping page
|
|
jsr vmem_clear_tlb_entry
|
|
movem.l (a7)+, d1/d2/d3
|
|
move.l stack_page_addr, a0 ; Load the address of the stack page into a0
|
|
move.l d1, (a0) ; Write the address of the old top frame to the next pointer of the new top
|
|
rts
|
|
|
|
public pmem_pop_frame
|
|
; Pops a frame off the stack
|
|
; Returns frame address in d0
|
|
pmem_pop_frame:
|
|
move.l #0, d0 ; Read the mapping entry into d0
|
|
move.l stack_page_addr, a0
|
|
jsr vmem_get_map_ptr
|
|
move.l (a0), d0
|
|
andi.l #(~$FFF), d0 ; Clear the entry's flags to get the pointer to its physical frame
|
|
move.l stack_page_addr, a1 ; Load the address of the stack page into a1
|
|
move.l (a1), d1 ; Get the address of the frame pointed to by the top of the stack
|
|
beq.b pop_no_page ; If the pointed-to frame is the null frame, OOM
|
|
movem.l d0/d2/d3, -(a7)
|
|
; Map the stack page to the pointed-to-frame
|
|
move.l d1, d0
|
|
move.l #0, d2
|
|
move.l stack_page_addr, a0
|
|
move.l #1, d1
|
|
move.l #$2, d3
|
|
jsr vmem_map_to
|
|
move.l stack_page_addr, a0 ; Clear the TLB entry for the mapping page
|
|
jsr vmem_clear_tlb_entry
|
|
movem.l (a7)+, d0/d2/d3
|
|
rts
|
|
pop_no_page:
|
|
move.l #oom_error_str, a0
|
|
jsr term_println
|
|
stop #$2700
|
|
|
|
section .data,data
|
|
pmem_log_name: dc.b "[PMEM] ",0
|
|
ramcard_log_msg: dc.b " byte RAM card at ",0
|
|
oom_error_str: dc.b "Out of physical memory",0
|
|
|
|
|
|
section .bss,bss
|
|
align 1
|
|
stack_page_addr:
|
|
ds.b 4
|