📄 bus.c
字号:
/* * ---------------------------------------------------------------- * * Memory and IO-Memory Access for 32 Bit bus with * IO-Handler registration and Translation Tables from Targets Physical * address (TPA) to hosts virtual Address (HVA) * * (C) 2004 Lightmaze Solutions AG * Author: Jochen Karrer * * Status: * working * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * ---------------------------------------------------------------- */#include <stdint.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <bus.h>extern char * ppc_memory;Bus *MainBus;/* * ------------------------------------ * Hash for single IO-Ports * ------------------------------------ */IOHandler **iohandlerHash;/* * ------------------------------------ * Map for large IO-Windows * ------------------------------------ */IOHandler **iohandlerMap;/* * ------------------------------------ * Two level Map for small IO-Windows * ------------------------------------ */IOHandler ***iohandlerFlvlMap;static unsigned int ioh_flvl_use_count[IOH_FLVL_SZ]={0,};/* * ------------------------------------------- * One level memory translation table vars * ------------------------------------------- */uint8_t **mem_map_read;uint8_t **mem_map_write;/* * ----------------------------------------- * Two level memory translation table vars * ----------------------------------------- */TwoLevelMMap twoLevelMMap;InvalidateCallback *InvalidateProc;static inline uint8_t *twolevel_translate_r(uint32_t addr) { int index; uint8_t *base; uint8_t **slvl_map; index = addr >> twoLevelMMap.frst_lvl_shift; if(unlikely(!(slvl_map = twoLevelMMap.flvlmap_read[index]))) { return NULL; } index = (addr & twoLevelMMap.scnd_lvl_mask) >> twoLevelMMap.scnd_lvl_shift; base = slvl_map[index]; if(likely(base)) { return base+(addr&(twoLevelMMap.scnd_lvl_blockmask)); } else { return NULL; }}static inline uint8_t *twolevel_translate_w(uint32_t addr) { int index; uint8_t *base; uint8_t **slvl_map; index = addr >> twoLevelMMap.frst_lvl_shift; if(unlikely(!(slvl_map = twoLevelMMap.flvlmap_write[index]))) { return NULL; } index = (addr & twoLevelMMap.scnd_lvl_mask) >> twoLevelMMap.scnd_lvl_shift; base = slvl_map[index]; if(likely(base)) { if(unlikely(((unsigned long)base) & PG_TRACED)) { base -= PG_TRACED; slvl_map[index] = base; IO_Write8(0,addr); } return base +(addr & (twoLevelMMap.scnd_lvl_blockmask)); } else { return NULL; }}/* * ----------------------------------------------- * Bus Read * Read from Memory or call an MMIO handler * ----------------------------------------------- */uint64_tBus_Read64(uint32_t addr) { uint32_t index=(addr>>MEM_MAP_SHIFT); uint8_t *base=mem_map_read[index]; if(likely(base)) { return HMemRead64(base+(addr&(MEM_MAP_BLOCKMASK))); } else { uint8_t *taddr = twolevel_translate_r(addr); if(taddr) { return HMemRead64(taddr); } return IO_Read64(addr); }}uint32_tBus_Read32(uint32_t addr) { /* uint32_t index = (addr >> MEM_MAP_SHIFT); uint8_t *base = mem_map_read[index]; if(likely(base)) { return HMemRead32(base+(addr&(MEM_MAP_BLOCKMASK))); } else { uint8_t *taddr = twolevel_translate_r(addr); if(taddr) { return HMemRead32(taddr); } return IO_Read32(addr); }*/ //return host32_to_target(*(uint32_t *)(&ppc_memory[addr])); int base = 0xc0000000; /* Fixme */ printf("KSDBG:addr=0x%x\n", addr); return 0; //return __bswap_32(*(uint32_t *)(&ppc_memory[addr - base]));}uint16_tBus_Read16(uint32_t addr) { uint32_t index = (addr >> MEM_MAP_SHIFT); uint8_t *base = mem_map_read[index]; if(likely(base)) { return HMemRead16(base+(addr&(MEM_MAP_BLOCKMASK))); } else { uint8_t *taddr = twolevel_translate_r(addr); if(taddr) { return HMemRead16(taddr); } return IO_Read16(addr); }}uint8_tBus_Read8(uint32_t addr) { /* uint32_t index=(addr>>MEM_MAP_SHIFT); uint8_t *base=mem_map_read[index]; if(likely(base)) { return HMemRead8(base+(addr&(MEM_MAP_BLOCKMASK))); } else { uint8_t *taddr = twolevel_translate_r(addr); if(taddr) { return HMemRead8(taddr); } return IO_Read8(addr); }*/ //fprintf(stderr, "KSDBG:read addr=0x%x\n",addr); return ppc_memory[addr];}/* * -------------------------------------------- * Bus Read * Write to Memory or call an MMIO handler * -------------------------------------------- */voidBus_Write64(uint64_t value,uint32_t addr) { uint32_t index=(addr>>MEM_MAP_SHIFT); uint8_t *base=mem_map_write[index]; if(likely(base)) { HMemWrite64(value,(base+(addr&(MEM_MAP_BLOCKMASK)))); } else { uint8_t *taddr = twolevel_translate_w(addr); if(taddr) { return HMemWrite64(value,taddr); } //return IO_Write64(value,addr); return; }}voidBus_Write32(uint32_t value,uint32_t addr) { uint32_t index=(addr>>MEM_MAP_SHIFT); uint8_t *base=mem_map_write[index]; if(likely(base)) { HMemWrite32(value,(base+(addr&(MEM_MAP_BLOCKMASK)))); } else { uint8_t *taddr = twolevel_translate_w(addr); if(taddr) { return HMemWrite32(value,taddr); } return IO_Write32(value,addr); }}voidBus_Write16(uint16_t value,uint32_t addr) { uint32_t index=(addr>>MEM_MAP_SHIFT); uint8_t *base=mem_map_write[index]; if(likely(base)) { HMemWrite16(value,(base+(addr&(MEM_MAP_BLOCKMASK)))); } else { uint8_t *taddr = twolevel_translate_w(addr); if(taddr) { return HMemWrite16(value,taddr); } return IO_Write16(value,addr); }}voidBus_Write8(uint8_t value,uint32_t addr) { /* uint32_t index = (addr>>MEM_MAP_SHIFT); uint8_t * base = mem_map_write[index]; if(likely(base)) { HMemWrite8(value,(base+(addr&(MEM_MAP_BLOCKMASK)))); } else { uint8_t *taddr = twolevel_translate_w(addr); if(taddr) { return HMemWrite8(value,taddr); } return IO_Write8(value,addr); }*/ //fprintf(stderr, "KSDBG:write addr=0x%x\n",addr); ppc_memory[addr] = value; return ; }/* * -------------------------------------------- * Generic Bus Access Functions for Transfer * of any block size. Mainly used for * non CPU bus masters. * -------------------------------------------- */voidBus_Write(uint32_t addr,uint8_t *buf,uint32_t count) { while(count) { Bus_Write8(*buf++,addr++); count--; }}voidBus_WriteSwap32(uint32_t addr,uint8_t *buf,int count) { while(count) { Bus_Write8(*buf++,(addr^3)); addr++; count--; }}voidBus_Read(uint8_t *buf,uint32_t addr,uint32_t count) { while(count) { *buf=Bus_Read8(addr++); buf++;count--; }}voidBus_ReadSwap32(uint8_t *buf,uint32_t addr,int count) { while(count) { *buf=Bus_Read8(addr^3); addr++; buf++;count--; }}/* * ------------------------------------------------------------ * Map/Unmap single 1MB Blocks * ------------------------------------------------------------ */static voidMem_MapBlock(uint32_t addr,uint8_t *host_mem,uint32_t flags) { uint32_t index=(addr>>MEM_MAP_SHIFT); if(flags & MEM_FLAG_READABLE) { mem_map_read[index]=host_mem; } if(flags & MEM_FLAG_WRITABLE) { mem_map_write[index]=host_mem; }}/* * -------------------------------------------- * Unmap a (large) block * If nothing is mapped return 0 else 1 * -------------------------------------------- */static inline int Mem_UnMapBlock(uint32_t addr) { uint32_t index=(addr>>MEM_MAP_SHIFT); if(mem_map_read[index] || mem_map_write[index]) { mem_map_read[index]= mem_map_write[index]=NULL; return 1; } else { return 0; }}/* * ------------------------------------------------------------ * Map/Unmap variable sized blocks in 2-Level Translation table * ------------------------------------------------------------ */static voidMem_Map2LvlBlock(uint32_t addr,uint8_t *host_mem,uint32_t flags) { uint8_t **slvl_map_w; uint8_t **slvl_map_r; int index = addr >> twoLevelMMap.frst_lvl_shift; int sl_index = (addr & twoLevelMMap.scnd_lvl_mask) >> twoLevelMMap.scnd_lvl_shift; if(flags & MEM_FLAG_READABLE) { slvl_map_r = twoLevelMMap.flvlmap_read[index]; if(unlikely(!slvl_map_r)) { slvl_map_r = twoLevelMMap.flvlmap_read[index]=malloc(sizeof(uint8_t*)*twoLevelMMap.scnd_lvl_sz); if(unlikely(!slvl_map_r)) { fprintf(stderr,"Out of memory in Map2LvlBlock\n"); exit(4324); } else { memset(slvl_map_r,0,sizeof(uint8_t*)*twoLevelMMap.scnd_lvl_sz); /* assert use count of 0 */ } } twoLevelMMap.flvl_map_read_use_count[index]++; slvl_map_r[sl_index]=host_mem; } if(flags & MEM_FLAG_WRITABLE) { slvl_map_w = twoLevelMMap.flvlmap_write[index]; if(unlikely(!slvl_map_w)) { slvl_map_w = twoLevelMMap.flvlmap_write[index]=malloc(sizeof(uint8_t*)*twoLevelMMap.scnd_lvl_sz); if(unlikely(!slvl_map_w)) { fprintf(stderr,"Out of memory in Map2LvlBlock\n"); exit(4329); } else { memset(slvl_map_w,0,sizeof(uint8_t*)*twoLevelMMap.scnd_lvl_sz); } } twoLevelMMap.flvl_map_write_use_count[index]++; slvl_map_w[sl_index]=host_mem; } }static voidMem_UnMap2LvlBlock(uint32_t addr) { uint8_t **slvl_map_w; uint8_t **slvl_map_r; int index = addr >> twoLevelMMap.frst_lvl_shift; int sl_index = (addr & twoLevelMMap.scnd_lvl_mask) >> twoLevelMMap.scnd_lvl_shift; slvl_map_r = twoLevelMMap.flvlmap_read[index]; slvl_map_w = twoLevelMMap.flvlmap_write[index]; if(slvl_map_r) { if(slvl_map_r[sl_index]) { slvl_map_r[sl_index]=NULL; twoLevelMMap.flvl_map_read_use_count[index]--; if(twoLevelMMap.flvl_map_read_use_count[index]==0) { free(slvl_map_r); slvl_map_r = twoLevelMMap.flvlmap_read[index]=NULL; } } } if(slvl_map_w) { if(slvl_map_w[sl_index]) { slvl_map_w[sl_index]=NULL; twoLevelMMap.flvl_map_write_use_count[index]--; if(twoLevelMMap.flvl_map_write_use_count[index]==0) { free(slvl_map_w); slvl_map_w = twoLevelMMap.flvlmap_write[index]=NULL; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -