?? ppc405_uc.c
字號:
/* * QEMU PowerPC 405 embedded processors emulation * * Copyright (c) 2007 Jocelyn Mayer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "hw.h"#include "ppc.h"#include "ppc405.h"#include "pc.h"#include "qemu-timer.h"#include "sysemu.h"extern int loglevel;extern FILE *logfile;#define DEBUG_OPBA#define DEBUG_SDRAM#define DEBUG_GPIO#define DEBUG_SERIAL#define DEBUG_OCM//#define DEBUG_I2C#define DEBUG_GPT#define DEBUG_MAL#define DEBUG_CLOCKS//#define DEBUG_CLOCKS_LLram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, uint32_t flags){ ram_addr_t bdloc; int i, n; /* We put the bd structure at the top of memory */ if (bd->bi_memsize >= 0x01000000UL) bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t); else bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); stl_raw(phys_ram_base + bdloc + 0x00, bd->bi_memstart); stl_raw(phys_ram_base + bdloc + 0x04, bd->bi_memsize); stl_raw(phys_ram_base + bdloc + 0x08, bd->bi_flashstart); stl_raw(phys_ram_base + bdloc + 0x0C, bd->bi_flashsize); stl_raw(phys_ram_base + bdloc + 0x10, bd->bi_flashoffset); stl_raw(phys_ram_base + bdloc + 0x14, bd->bi_sramstart); stl_raw(phys_ram_base + bdloc + 0x18, bd->bi_sramsize); stl_raw(phys_ram_base + bdloc + 0x1C, bd->bi_bootflags); stl_raw(phys_ram_base + bdloc + 0x20, bd->bi_ipaddr); for (i = 0; i < 6; i++) stb_raw(phys_ram_base + bdloc + 0x24 + i, bd->bi_enetaddr[i]); stw_raw(phys_ram_base + bdloc + 0x2A, bd->bi_ethspeed); stl_raw(phys_ram_base + bdloc + 0x2C, bd->bi_intfreq); stl_raw(phys_ram_base + bdloc + 0x30, bd->bi_busfreq); stl_raw(phys_ram_base + bdloc + 0x34, bd->bi_baudrate); for (i = 0; i < 4; i++) stb_raw(phys_ram_base + bdloc + 0x38 + i, bd->bi_s_version[i]); for (i = 0; i < 32; i++) stb_raw(phys_ram_base + bdloc + 0x3C + i, bd->bi_s_version[i]); stl_raw(phys_ram_base + bdloc + 0x5C, bd->bi_plb_busfreq); stl_raw(phys_ram_base + bdloc + 0x60, bd->bi_pci_busfreq); for (i = 0; i < 6; i++) stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); n = 0x6A; if (flags & 0x00000001) { for (i = 0; i < 6; i++) stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]); } stl_raw(phys_ram_base + bdloc + n, bd->bi_opbfreq); n += 4; for (i = 0; i < 2; i++) { stl_raw(phys_ram_base + bdloc + n, bd->bi_iic_fast[i]); n += 4; } return bdloc;}/*****************************************************************************//* Shared peripherals *//*****************************************************************************//* Peripheral local bus arbitrer */enum { PLB0_BESR = 0x084, PLB0_BEAR = 0x086, PLB0_ACR = 0x087,};typedef struct ppc4xx_plb_t ppc4xx_plb_t;struct ppc4xx_plb_t { uint32_t acr; uint32_t bear; uint32_t besr;};static target_ulong dcr_read_plb (void *opaque, int dcrn){ ppc4xx_plb_t *plb; target_ulong ret; plb = opaque; switch (dcrn) { case PLB0_ACR: ret = plb->acr; break; case PLB0_BEAR: ret = plb->bear; break; case PLB0_BESR: ret = plb->besr; break; default: /* Avoid gcc warning */ ret = 0; break; } return ret;}static void dcr_write_plb (void *opaque, int dcrn, target_ulong val){ ppc4xx_plb_t *plb; plb = opaque; switch (dcrn) { case PLB0_ACR: /* We don't care about the actual parameters written as * we don't manage any priorities on the bus */ plb->acr = val & 0xF8000000; break; case PLB0_BEAR: /* Read only */ break; case PLB0_BESR: /* Write-clear */ plb->besr &= ~val; break; }}static void ppc4xx_plb_reset (void *opaque){ ppc4xx_plb_t *plb; plb = opaque; plb->acr = 0x00000000; plb->bear = 0x00000000; plb->besr = 0x00000000;}void ppc4xx_plb_init (CPUState *env){ ppc4xx_plb_t *plb; plb = qemu_mallocz(sizeof(ppc4xx_plb_t)); if (plb != NULL) { ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); ppc4xx_plb_reset(plb); qemu_register_reset(ppc4xx_plb_reset, plb); }}/*****************************************************************************//* PLB to OPB bridge */enum { POB0_BESR0 = 0x0A0, POB0_BESR1 = 0x0A2, POB0_BEAR = 0x0A4,};typedef struct ppc4xx_pob_t ppc4xx_pob_t;struct ppc4xx_pob_t { uint32_t bear; uint32_t besr[2];};static target_ulong dcr_read_pob (void *opaque, int dcrn){ ppc4xx_pob_t *pob; target_ulong ret; pob = opaque; switch (dcrn) { case POB0_BEAR: ret = pob->bear; break; case POB0_BESR0: case POB0_BESR1: ret = pob->besr[dcrn - POB0_BESR0]; break; default: /* Avoid gcc warning */ ret = 0; break; } return ret;}static void dcr_write_pob (void *opaque, int dcrn, target_ulong val){ ppc4xx_pob_t *pob; pob = opaque; switch (dcrn) { case POB0_BEAR: /* Read only */ break; case POB0_BESR0: case POB0_BESR1: /* Write-clear */ pob->besr[dcrn - POB0_BESR0] &= ~val; break; }}static void ppc4xx_pob_reset (void *opaque){ ppc4xx_pob_t *pob; pob = opaque; /* No error */ pob->bear = 0x00000000; pob->besr[0] = 0x0000000; pob->besr[1] = 0x0000000;}void ppc4xx_pob_init (CPUState *env){ ppc4xx_pob_t *pob; pob = qemu_mallocz(sizeof(ppc4xx_pob_t)); if (pob != NULL) { ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); qemu_register_reset(ppc4xx_pob_reset, pob); ppc4xx_pob_reset(env); }}/*****************************************************************************//* OPB arbitrer */typedef struct ppc4xx_opba_t ppc4xx_opba_t;struct ppc4xx_opba_t { target_phys_addr_t base; uint8_t cr; uint8_t pr;};static uint32_t opba_readb (void *opaque, target_phys_addr_t addr){ ppc4xx_opba_t *opba; uint32_t ret;#ifdef DEBUG_OPBA printf("%s: addr " PADDRX "\n", __func__, addr);#endif opba = opaque; switch (addr - opba->base) { case 0x00: ret = opba->cr; break; case 0x01: ret = opba->pr; break; default: ret = 0x00; break; } return ret;}static void opba_writeb (void *opaque, target_phys_addr_t addr, uint32_t value){ ppc4xx_opba_t *opba;#ifdef DEBUG_OPBA printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);#endif opba = opaque; switch (addr - opba->base) { case 0x00: opba->cr = value & 0xF8; break; case 0x01: opba->pr = value & 0xFF; break; default: break; }}static uint32_t opba_readw (void *opaque, target_phys_addr_t addr){ uint32_t ret;#ifdef DEBUG_OPBA printf("%s: addr " PADDRX "\n", __func__, addr);#endif ret = opba_readb(opaque, addr) << 8; ret |= opba_readb(opaque, addr + 1); return ret;}static void opba_writew (void *opaque, target_phys_addr_t addr, uint32_t value){#ifdef DEBUG_OPBA printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);#endif opba_writeb(opaque, addr, value >> 8); opba_writeb(opaque, addr + 1, value);}static uint32_t opba_readl (void *opaque, target_phys_addr_t addr){ uint32_t ret;#ifdef DEBUG_OPBA printf("%s: addr " PADDRX "\n", __func__, addr);#endif ret = opba_readb(opaque, addr) << 24; ret |= opba_readb(opaque, addr + 1) << 16; return ret;}static void opba_writel (void *opaque, target_phys_addr_t addr, uint32_t value){#ifdef DEBUG_OPBA printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);#endif opba_writeb(opaque, addr, value >> 24); opba_writeb(opaque, addr + 1, value >> 16);}static CPUReadMemoryFunc *opba_read[] = { &opba_readb, &opba_readw, &opba_readl,};static CPUWriteMemoryFunc *opba_write[] = { &opba_writeb, &opba_writew, &opba_writel,};static void ppc4xx_opba_reset (void *opaque){ ppc4xx_opba_t *opba; opba = opaque; opba->cr = 0x00; /* No dynamic priorities - park disabled */ opba->pr = 0x11;}void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, target_phys_addr_t offset){ ppc4xx_opba_t *opba; opba = qemu_mallocz(sizeof(ppc4xx_opba_t)); if (opba != NULL) { opba->base = offset;#ifdef DEBUG_OPBA printf("%s: offset " PADDRX "\n", __func__, offset);#endif ppc4xx_mmio_register(env, mmio, offset, 0x002, opba_read, opba_write, opba); qemu_register_reset(ppc4xx_opba_reset, opba); ppc4xx_opba_reset(opba); }}/*****************************************************************************//* Code decompression controller *//* XXX: TODO *//*****************************************************************************//* SDRAM controller */typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;struct ppc4xx_sdram_t { uint32_t addr; int nbanks; target_phys_addr_t ram_bases[4]; target_phys_addr_t ram_sizes[4]; uint32_t besr0; uint32_t besr1; uint32_t bear; uint32_t cfg; uint32_t status; uint32_t rtr; uint32_t pmit; uint32_t bcr[4]; uint32_t tr; uint32_t ecccfg; uint32_t eccesr; qemu_irq irq;};enum { SDRAM0_CFGADDR = 0x010, SDRAM0_CFGDATA = 0x011,};/* XXX: TOFIX: some patches have made this code become inconsistent: * there are type inconsistencies, mixing target_phys_addr_t, target_ulong * and uint32_t */static uint32_t sdram_bcr (target_phys_addr_t ram_base, target_phys_addr_t ram_size){ uint32_t bcr; switch (ram_size) { case (4 * 1024 * 1024): bcr = 0x00000000; break; case (8 * 1024 * 1024): bcr = 0x00020000; break; case (16 * 1024 * 1024): bcr = 0x00040000; break; case (32 * 1024 * 1024): bcr = 0x00060000; break; case (64 * 1024 * 1024): bcr = 0x00080000; break; case (128 * 1024 * 1024): bcr = 0x000A0000; break; case (256 * 1024 * 1024): bcr = 0x000C0000; break; default: printf("%s: invalid RAM size " PADDRX "\n", __func__, ram_size); return 0x00000000; } bcr |= ram_base & 0xFF800000; bcr |= 1; return bcr;}static always_inline target_phys_addr_t sdram_base (uint32_t bcr){ return bcr & 0xFF800000;}static target_ulong sdram_size (uint32_t bcr){ target_ulong size; int sh; sh = (bcr >> 17) & 0x7; if (sh == 7) size = -1; else size = (4 * 1024 * 1024) << sh; return size;}static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled){ if (*bcrp & 0x00000001) { /* Unmap RAM */#ifdef DEBUG_SDRAM printf("%s: unmap RAM area " PADDRX " " ADDRX "\n", __func__, sdram_base(*bcrp), sdram_size(*bcrp));#endif cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp), IO_MEM_UNASSIGNED); } *bcrp = bcr & 0xFFDEE001; if (enabled && (bcr & 0x00000001)) {#ifdef DEBUG_SDRAM printf("%s: Map RAM area " PADDRX " " ADDRX "\n",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -