📄 ppc_prep.c
字号:
/* * QEMU PPC PREP hardware System Emulator * * Copyright (c) 2003-2004 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 "vl.h"//#define HARD_DEBUG_PPC_IO//#define DEBUG_PPC_IO#define BIOS_FILENAME "ppc_rom.bin"#define KERNEL_LOAD_ADDR 0x01000000#define INITRD_LOAD_ADDR 0x01800000extern int loglevel;extern FILE *logfile;#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)#define DEBUG_PPC_IO#endif#if defined (HARD_DEBUG_PPC_IO)#define PPC_IO_DPRINTF(fmt, args...) \do { \ if (loglevel & CPU_LOG_IOPORT) { \ fprintf(logfile, "%s: " fmt, __func__ , ##args); \ } else { \ printf("%s : " fmt, __func__ , ##args); \ } \} while (0)#elif defined (DEBUG_PPC_IO)#define PPC_IO_DPRINTF(fmt, args...) \do { \ if (loglevel & CPU_LOG_IOPORT) { \ fprintf(logfile, "%s: " fmt, __func__ , ##args); \ } \} while (0)#else#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)#endif/* Constants for devices init */static const int ide_iobase[2] = { 0x1f0, 0x170 };static const int ide_iobase2[2] = { 0x3f6, 0x376 };static const int ide_irq[2] = { 13, 13 };#define NE2000_NB_MAX 6static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };//static PITState *pit;/* ISA IO ports bridge */#define PPC_IO_BASE 0x80000000/* Speaker port 0x61 */int speaker_data_on;int dummy_refresh_clock;static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val){#if 0 speaker_data_on = (val >> 1) & 1; pit_set_gate(pit, 2, val & 1);#endif}static uint32_t speaker_ioport_read(void *opaque, uint32_t addr){#if 0 int out; out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); dummy_refresh_clock ^= 1; return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | (dummy_refresh_clock << 4);#endif return 0;}static void pic_irq_request(void *opaque, int level){ if (level) cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD); else cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);}/* PCI intack register *//* Read-only register (?) */static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value){ // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);}static inline uint32_t _PPC_intack_read (target_phys_addr_t addr){ uint32_t retval = 0; if (addr == 0xBFFFFFF0) retval = pic_intack_read(isa_pic); // printf("%s: 0x%08x <= %d\n", __func__, addr, retval); return retval;}static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr){ return _PPC_intack_read(addr);}static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr){#ifdef TARGET_WORDS_BIGENDIAN return bswap16(_PPC_intack_read(addr));#else return _PPC_intack_read(addr);#endif}static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr){#ifdef TARGET_WORDS_BIGENDIAN return bswap32(_PPC_intack_read(addr));#else return _PPC_intack_read(addr);#endif}static CPUWriteMemoryFunc *PPC_intack_write[] = { &_PPC_intack_write, &_PPC_intack_write, &_PPC_intack_write,};static CPUReadMemoryFunc *PPC_intack_read[] = { &PPC_intack_readb, &PPC_intack_readw, &PPC_intack_readl,};/* PowerPC control and status registers */#if 0 // Not usedstatic struct { /* IDs */ uint32_t veni_devi; uint32_t revi; /* Control and status */ uint32_t gcsr; uint32_t xcfr; uint32_t ct32; uint32_t mcsr; /* General purpose registers */ uint32_t gprg[6]; /* Exceptions */ uint32_t feen; uint32_t fest; uint32_t fema; uint32_t fecl; uint32_t eeen; uint32_t eest; uint32_t eecl; uint32_t eeint; uint32_t eemck0; uint32_t eemck1; /* Error diagnostic */} XCSR;static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value){ printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);}static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value){#ifdef TARGET_WORDS_BIGENDIAN value = bswap16(value);#endif printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);}static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value){#ifdef TARGET_WORDS_BIGENDIAN value = bswap32(value);#endif printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);}static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr){ uint32_t retval = 0; printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval); return retval;}static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr){ uint32_t retval = 0; printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);#ifdef TARGET_WORDS_BIGENDIAN retval = bswap16(retval);#endif return retval;}static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr){ uint32_t retval = 0; printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);#ifdef TARGET_WORDS_BIGENDIAN retval = bswap32(retval);#endif return retval;}static CPUWriteMemoryFunc *PPC_XCSR_write[] = { &PPC_XCSR_writeb, &PPC_XCSR_writew, &PPC_XCSR_writel,};static CPUReadMemoryFunc *PPC_XCSR_read[] = { &PPC_XCSR_readb, &PPC_XCSR_readw, &PPC_XCSR_readl,};#endif/* Fake super-io ports for PREP platform (Intel 82378ZB) */typedef struct sysctrl_t { m48t59_t *nvram; uint8_t state; uint8_t syscontrol; uint8_t fake_io[2]; int contiguous_map; int endian;} sysctrl_t;enum { STATE_HARDFILE = 0x01,};static sysctrl_t *sysctrl;static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val){ sysctrl_t *sysctrl = opaque; PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val); sysctrl->fake_io[addr - 0x0398] = val;}static uint32_t PREP_io_read (void *opaque, uint32_t addr){ sysctrl_t *sysctrl = opaque; PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, sysctrl->fake_io[addr - 0x0398]); return sysctrl->fake_io[addr - 0x0398];}static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val){ sysctrl_t *sysctrl = opaque; PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val); switch (addr) { case 0x0092: /* Special port 92 */ /* Check soft reset asked */ if (val & 0x01) { // cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET); } /* Check LE mode */ if (val & 0x02) { sysctrl->endian = 1; } else { sysctrl->endian = 0; } break; case 0x0800: /* Motorola CPU configuration register : read-only */ break; case 0x0802: /* Motorola base module feature register : read-only */ break; case 0x0803: /* Motorola base module status register : read-only */ break; case 0x0808: /* Hardfile light register */ if (val & 1) sysctrl->state |= STATE_HARDFILE; else sysctrl->state &= ~STATE_HARDFILE; break; case 0x0810: /* Password protect 1 register */ if (sysctrl->nvram != NULL) m48t59_toggle_lock(sysctrl->nvram, 1); break; case 0x0812: /* Password protect 2 register */ if (sysctrl->nvram != NULL) m48t59_toggle_lock(sysctrl->nvram, 2); break; case 0x0814: /* L2 invalidate register */ // tlb_flush(first_cpu, 1); break; case 0x081C: /* system control register */ sysctrl->syscontrol = val & 0x0F; break; case 0x0850: /* I/O map type register */ sysctrl->contiguous_map = val & 0x01; break; default: printf("ERROR: unaffected IO port write: %04lx => %02x\n", (long)addr, val); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -