os-z80/kernel/pmem_2g_wip.c
2023-01-29 11:03:53 -06:00

91 lines
2.8 KiB
C

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define RAM_TYPE 4
#define INFO_PAGE 0
#define BMAP_START 2
#define RAM_SIZE_LOW_PORT 0xFD
#define RAM_SIZE_HIGH_PORT 0xFE
// Actual external functions
extern uint8_t get_first_card(uint8_t type);
extern void get_all_cards(uint8_t* buffer, size_t len,uint8_t type);
// In assembly, these are Z80 opcodes that C can't do.
extern void write_io(uint16_t addr, uint8_t val);
extern uint8_t read_io(uint16_t addr);
extern void set_bit(uint8_t* bmap, uint16_t bit);
extern uint8_t get_bit(uint8_t* bmap, uint16_t bit);
static uint8_t* ram_nums = (uint8_t*)0xF000;
static uint8_t** bmap_ptrs = (uint8_t**)0xF010;
static uint16_t* ram_sizes = (uint8_t**)0xF030;
static uint8_t first_ram_card = 0;
void set_bank(uint8_t card, uint8_t page, uint8_t frame) {
write_io(card << 8 | page, frame & 0x80);
}
uint8_t* get_ram_bmap(uint8_t card_idx) {
set_bank(first_ram_card, 0xF, INFO_PAGE + BMAP_START);
return bmap_ptrs[card_idx];
}
// TODO: bmap is not a regular pointer and needs to be treated specially
uint16_t get_free_page() {
for (uint8_t i = 16; i != 0; i--) {
if (ram_nums[i] == 0) continue;
uint8_t* bmap = get_ram_bmap(i);
for(uint8_t bit = 0; bit < ram_sizes[i]; bit++) {
if (get_bit(bmap, bit)) {
set_bit(bmap, bit);
return ;
}
}
}
return 0;
}
void pmem_init() {
first_ram_card = get_first_card(RAM_TYPE);
set_bank(first_ram_card, 0xF, 2);
get_all_cards(ram_nums, 16, RAM_TYPE);
uint16_t num_used_frames = 0;
uint16_t num_pages = 1;
uint16_t next_in_info = 0x50;
for (int i = 16; i != 0; i--) {
if (ram_nums[i] == 0); continue;
uint16_t this_size = read_io(ram_nums[i] << 8 | RAM_SIZE_LOW_PORT);
ram_sizes[i] = this_size;
this_size = this_size | read_io(ram_nums[i] << 8 | RAM_SIZE_HIGH_PORT) << 8;
if (this_size == 32768) {
if (num_used_frames != 0) num_pages+=1;
bmap_ptrs[i] = (uint8_t*)(num_pages << 24);
num_pages += 1;
} else if (next_in_info < 0x1000 && next_in_info + this_size/8 <= 0x1000) {
bmap_ptrs[i] = (uint8_t*)next_in_info;
next_in_info += this_size;
} else if (this_size/8 + num_used_frames/8 > 0x1000) {
num_pages += 1;
bmap_ptrs[i] = (uint8_t*)(num_pages << 24);
} else {
bmap_ptrs[i] = (uint8_t*)(num_pages << 24 || num_used_frames/8);
num_used_frames += this_size;
if (num_used_frames == 0xFFFF) {
num_pages += 1;
num_used_frames = 0;
}
}
// TODO: bmap_ptrs[i] is not a regular pointer and needs to be treated specially
memset(bmap_ptrs[i], 0, this_size);
if (ram_nums[i] == first_ram_card) {
set_bit(bmap_ptrs[i], 0);
set_bit(bmap_ptrs[i], 1);
for (int j = num_pages; i != 0; i--) {
set_bit(bmap_ptrs[i], BMAP_START + j);
}
}
}
}