/* * mii_bank.c * * Copyright (C) 2023 Michel Pollet * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "mii.h" #include "mii_bank.h" void mii_bank_init( mii_bank_t *bank) { if (bank->mem) return; if (bank->mem_offset == 0 && !bank->no_alloc) { bank->mem = calloc(1, bank->size * 256); bank->alloc = 1; } } void mii_bank_dispose( mii_bank_t *bank) { if (bank->alloc) free(bank->mem); bank->mem = NULL; bank->alloc = 0; if (bank->access) { // Allow callback to free anything it wants for (int i = 0; i < bank->size; i++) if (bank->access[i].cb) bank->access[i].cb(NULL, bank->access[i].param, 0, NULL, false); free(bank->access); } bank->access = NULL; } void mii_bank_write( mii_bank_t *bank, uint16_t addr, const uint8_t *data, uint16_t len) { uint32_t end = bank->base + (bank->size << 8); if (unlikely(addr < bank->base || (addr + len) > end)) { printf("%s %s INVALID write addr %04x len %d %04x:%04x\n", __func__, bank->name, addr, (int)len, bank->base, end); abort(); return; } uint8_t page_index = (addr - bank->base) >> 8; if (bank->access && bank->access[page_index].cb) { if (bank->access[page_index].cb(bank, bank->access[page_index].param, addr, (uint8_t *)data, true)) return; } uint32_t phy = bank->mem_offset + addr - bank->base; do { bank->mem[phy++] = *data++; } while (likely(--len)); } void mii_bank_read( mii_bank_t *bank, uint16_t addr, uint8_t *data, uint16_t len) { #if 1 // rather expensive test when profiling! uint32_t end = bank->base + (bank->size << 8); if (unlikely(addr < bank->base) || unlikely((addr + len) > end)) { printf("%s %s INVALID read addr %04x len %d %04x-%04x\n", __func__, bank->name, addr, (int)len, bank->base, end); return; } #endif uint8_t page_index = (addr - bank->base) >> 8; if (bank->access && bank->access[page_index].cb) { if (bank->access[page_index].cb(bank, bank->access[page_index].param, addr, data, false)) return; } uint32_t phy = bank->mem_offset + addr - bank->base; do { *data++ = bank->mem[phy++]; } while (likely(--len)); } void mii_bank_install_access_cb( mii_bank_t *bank, mii_bank_access_cb cb, void *param, uint8_t page, uint8_t end) { if (!end) end = page; if ((page << 8) < bank->base || (end << 8) > (bank->base + bank->size * 256)) { printf("%s %s INVALID install access cb %p param %p page %02x-%02x\n", __func__, bank->name, cb, param, page, end); return; } page -= bank->base >> 8; end -= bank->base >> 8; if (!bank->access) { bank->access = calloc(1, bank->size * sizeof(bank->access[0])); } printf("%s %s install access cb page %02x:%02x\n", __func__, bank->name, page, end); for (int i = page; i <= end; i++) { if (bank->access[i].cb) printf("%s %s page %02x already has a callback\n", __func__, bank->name, i); bank->access[i].cb = cb; bank->access[i].param = param; } }