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