From patchwork Wed Aug 17 22:09:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryce Lanham X-Patchwork-Id: 110451 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4987CB6FA1 for ; Thu, 18 Aug 2011 09:24:16 +1000 (EST) Received: from localhost ([::1]:35122 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QtoJK-0007cQ-7n for incoming@patchwork.ozlabs.org; Wed, 17 Aug 2011 18:10:06 -0400 Received: from eggs.gnu.org ([140.186.70.92]:57844) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QtoIx-0006j4-GV for qemu-devel@nongnu.org; Wed, 17 Aug 2011 18:09:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QtoIs-0008N4-R6 for qemu-devel@nongnu.org; Wed, 17 Aug 2011 18:09:43 -0400 Received: from mail-gy0-f173.google.com ([209.85.160.173]:33574) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QtoIs-0008LM-Kj for qemu-devel@nongnu.org; Wed, 17 Aug 2011 18:09:38 -0400 Received: by mail-gy0-f173.google.com with SMTP id 12so1281803gyd.4 for ; Wed, 17 Aug 2011 15:09:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=wpxnCweACC8TGcfQHUy+QUIg2F5xmvCOtwri1wfRaeM=; b=x4rEQoGNvbf9ysjlTcjEKz1LwEPlvdTq1RrazrQBuA/f9dbXvODkDkiOpmjpfVmeWg lYJHK3e/ljN5mpMn6Jckev62WIFKev3vVZtOhDuGFXNUIOSAFw5dt2xl3H661q5zUix3 xfpX3ItKWiYR/ccxIl9jo4Pa8XTecOf7m+wn8= Received: by 10.150.54.7 with SMTP id c7mr1715080yba.250.1313618978390; Wed, 17 Aug 2011 15:09:38 -0700 (PDT) Received: from localhost.localdomain (betelgeuse.cs.uchicago.edu [128.135.24.226]) by mx.google.com with ESMTPS id c63sm445841yhe.46.2011.08.17.15.09.36 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 17 Aug 2011 15:09:37 -0700 (PDT) From: Bryce Lanham To: qemu-devel@nongnu.org Date: Wed, 17 Aug 2011 17:09:06 -0500 Message-Id: <1313618952-14774-4-git-send-email-blanham@gmail.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1313618952-14774-1-git-send-email-blanham@gmail.com> References: <1313618952-14774-1-git-send-email-blanham@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.160.173 Cc: Bryce Lanham Subject: [Qemu-devel] [PATCH 2/8] main next driver, needs a bit of cleanup X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Bryce Lanham --- hw/next-cube.c | 471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 471 insertions(+), 0 deletions(-) create mode 100644 hw/next-cube.c diff --git a/hw/next-cube.c b/hw/next-cube.c new file mode 100644 index 0000000..37e3c17 --- /dev/null +++ b/hw/next-cube.c @@ -0,0 +1,471 @@ +/* + * Next Cube System Driver + * Copyright (c) 2011 Bryce Lanham + * + * Based on dummy_m68k.c Copyright (c) 2007 CodeSourcery. + * + * Scr2 code from Previous, used under the GPL + * + * This code is licensed under the GPL + */ + + +#include "hw.h" +#include "next-fb.h" +#include "next-kbd.h" +#include "next-net.h" + +#include "monitor.h" +#include "sysemu.h" +#include "boards.h" +#include "console.h" +#include "loader.h"//probably not needed +#include "elf.h" +#include "esp.h" //SCSI ESP should work out of the box +#include "escc.h" //ZILOG 8530 Serial Emulation +#define ENTRY 0x0100001e + +/* Board init. */ +#define ROM_FILE "rom66.bin" +/* these need to be in machine state */ +uint32_t scr1 = 0; +uint32_t scr2 = 0; +uint32_t int_status = 4;//from previous +uint32_t int_mask = 0; +uint32_t event_test = 0; +/* Thanks to NeXT forums for this */ +uint8_t rtc_ram3[32]={ +0x94,0x0f,0x40,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xfb,0x6d,0x00,0x00,0x7B,0x00, +0x00,0x00,0x65,0x6e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x13 +}; +uint8_t *rtc_ram; +uint8_t rtc_ram2[32]={ +0x94,0x0f,0x40,0x03,0x00,0x00,0x00,0x00, +0x00,0x00,0xfb,0x6d,0x00,0x00,0x4b,0x00, +0x41,0x00,0x20,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x7e, +}; + +next_state_t next_state; + +static uint32_t mmio_readb(void*opaque, target_phys_addr_t addr); +static uint32_t mmio_readw(void*opaque, target_phys_addr_t addr); +static uint32_t mmio_readl(void*opaque, target_phys_addr_t addr); + +static void mmio_writeb(void*opaque, target_phys_addr_t addr, uint32_t val); +static void mmio_writew(void*opaque, target_phys_addr_t addr, uint32_t val); +static void mmio_writel(void*opaque, target_phys_addr_t addr, uint32_t val); +static CPUReadMemoryFunc *mmio_read[3] = { + mmio_readb, + mmio_readw, + mmio_readl +}; + +static CPUWriteMemoryFunc *mmio_write[3] = { + mmio_writeb, + mmio_writew, + mmio_writel +}; +static uint32_t mmio_readb(void*opaque, target_phys_addr_t addr) +{ + switch(addr) + { + case 0xc002: + return (scr1 >> 8) & 0xFF; + case 0xc0008: + return 0xff;//hack to hide memory error + default: + fprintf(stderr,"MMIO Read B @ %x\n",addr); + return 0x0; + } +} +static uint32_t mmio_readw(void*opaque, target_phys_addr_t addr) +{ + switch(addr) + { + default: + fprintf(stderr,"MMIO Read W @ %x\n",addr); + return 0x0; + } +} + +static uint32_t mmio_readl(void*opaque, target_phys_addr_t addr) +{ + + switch(addr) + { + case 0x7000: + // fprintf(stderr,"INTSTAT\n"); + return int_status; + + case 0x7800: + //fprintf(stderr,"INTMASK\n"); + return int_mask; + + case 0xc000: + // fprintf(stderr, "SCR1 Read: @ %X\n",((CPUM68KState *)opaque)->pc); + return scr1; + + case 0xd000: + // fprintf(stderr, "SCR2 Read: @ %X %X\n",((CPUM68KState *)opaque)->pc,scr2); + return scr2; + + case 0xc0000: + return 0x01; + + case 0xc0034: + return 0x560; + + default: + fprintf(stderr,"MMIO Read L @ %x\n",addr); + return 0x0; + } +} +static void mmio_writeb(void*opaque, target_phys_addr_t addr, uint32_t val) +{ + + switch(addr) + { + default: + fprintf(stderr,"MMIO Write B @ %x with %x\n",addr,val); + } + +} +static void mmio_writew(void*opaque, target_phys_addr_t addr, uint32_t val) +{ + fprintf(stderr,"MMIO Write W\n" ); +} +int led = 0; + +static void mmio_writel(void*opaque, target_phys_addr_t addr, uint32_t val) +{ + static int phase = 0; + static uint8_t old_scr2; + static uint8_t rtc_command = 0; + static uint8_t rtc_value = 0; + static uint8_t rtc_status = 0x90; + static uint8_t rtc_return = 0; + uint8_t scr2_2; + switch(addr) + { + case 0x10: + break; + case 0x7000: + fprintf(stderr,"INT Status old: %x new: %x\n",int_status,val); + int_status = val; + break; + case 0x7800: + fprintf(stderr,"INT Status old: %x new: %x\n",int_mask,val); + int_mask = val; + break; + case 0xc000: + fprintf(stderr, "SCR1 Write: %x @ %X\n",val,((CPUM68KState *)opaque)->pc); + break; + case 0xd000: + //old_scr2 = val; + scr2_2 = (val >> 8) & 0xFF; + if(val &0x1) + { + printf("fault!\n"); + led++; + if(led == 10) + { + fprintf(stderr,"LED flashing, possible fault, pausing emulation\n"); + led = 0; + vm_stop(VMSTOP_DEBUG); + } + + } + + if (scr2_2& 0x1) { + // fprintf(stderr,"RTC %x phase %i\n",scr2_2,phase); + if (phase==-1) phase=0; + // if we are in going down clock... do something + #define SCR2_RTCLK 0x2 + #define SCR2_RTDATA 0x4 + if (((old_scr2&SCR2_RTCLK)!=(scr2_2&SCR2_RTCLK)) && ((scr2_2&SCR2_RTCLK)==0) ) { + if (phase<8) + rtc_command=(rtc_command<<1)|((scr2_2&SCR2_RTDATA)?1:0); + if ((phase>=8) && (phase<16)) { + rtc_value=(rtc_value<<1)|((scr2_2&SCR2_RTDATA)?1:0); + + // if we read RAM register, output RT_DATA bit + if (rtc_command<=0x1F) { + scr2_2=scr2_2&(~SCR2_RTDATA); + if (rtc_ram[rtc_command]&(0x80>>(phase-8))) + scr2_2 |=SCR2_RTDATA; + + rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0); + } + // read the status 0x30 + if (rtc_command==0x30) { + scr2_2=scr2_2&(~SCR2_RTDATA); + // for now status = 0x98 (new rtc + FTU) + if (rtc_status&(0x80>>(phase-8))) + scr2_2|=SCR2_RTDATA; + + rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0); + } + // read the status 0x31 + if (rtc_command==0x31) { + scr2_2=scr2_2&(~SCR2_RTDATA); + // for now 0x00 + if (0x00&(0x80>>(phase-8))) + scr2_2|=SCR2_RTDATA; + rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0); + } + + if ((rtc_command>=0x20) && (rtc_command<=0x2F)) { + scr2_2=scr2_2&(~SCR2_RTDATA); + // for now 0x00 + if (0x00&(0x80>>(phase-8))) + scr2_2|=SCR2_RTDATA; + rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0); + } + + } + + phase++; + if (phase==16) { + // fprintf(stderr,"SCR2 RTC command complete %x %x %x at PC=$%08x\n", + // rtc_command,rtc_value,rtc_return,0); + if ((rtc_command>=0x80) && (rtc_command<=0x9F)) + { + rtc_ram[rtc_command-0x80]=rtc_value; + #ifdef READ_RTC + FILE *fp = fopen("rtc.ram","wb+"); + int ret = fwrite(rtc_ram,1,32,fp); + if(ret != 32) + abort(); + fclose(fp); + #endif + } + // write to x30 register + if (rtc_command==0xB1) { + // clear FTU + if (rtc_value & 0x04) { + rtc_status=rtc_status&(~0x18); + int_status=int_status&(~0x04); + } + } + } + } + } else { + // else end or abort + phase=-1; + rtc_command=0; + rtc_value=0; + } + scr2 = val & 0xFFFF00FF; + scr2 |= scr2_2<< 8; + old_scr2 = scr2_2; + + break; + case 0xc0034: + // if(val == 0x90000560) + // vm_stop(VMSTOP_DEBUG); + default: + fprintf(stderr,"MMIO Write l @ %x with %x\n",addr,val); + + } +} + + +static uint32_t scr_readb(void*opaque, target_phys_addr_t addr); +static uint32_t scr_readw(void*opaque, target_phys_addr_t addr); +static uint32_t scr_readl(void*opaque, target_phys_addr_t addr); +static CPUReadMemoryFunc *scr_read[3] = { + scr_readb, + scr_readw, + scr_readl + +}; + +static void scr_writeb(void*opaque, target_phys_addr_t addr, uint32_t value); +static void scr_writew(void*opaque, target_phys_addr_t addr, uint32_t value); +static void scr_writel(void*opaque, target_phys_addr_t addr, uint32_t value); +static CPUWriteMemoryFunc * const scr_write[3] = { + scr_writeb, + scr_writew, + scr_writel +}; + +static uint32_t scr_readb(void*opaque, target_phys_addr_t addr) +{ + // CPUState *s = (CPUState *)opaque; + switch(addr) + { + + case 0x14000: case 0x14005: + fprintf(stderr,"SCSI read b\n"); + return 0x0; + + case 0x14104://FDD + // return 0x0; + + case 0x14108: + return 0x0; + + case 0x18001: + // fprintf(stderr, "SCC @ %X\n",((CPUM68KState *)opaque)->pc); + return 0; + case 0x1a000: + // return 0; + case 0x1a001: + // return 0; + case 0x1a002: + // return 0; + case 0x1a003: + // fprintf(stderr,"event #%x @ %x\n",addr &0x3,s->pc); + // event_test++; + // if(event_test == 200) event_test = 0; + return event_test; + default: + fprintf(stderr,"BMAP Read B @ %x\n",addr); + return 0; + } + return 0; +} +static uint32_t scr_readw(void*opaque, target_phys_addr_t addr) +{ + fprintf(stderr,"S Read W @ %x\n",addr); + return 0; +} +static uint32_t scr_readl(void*opaque, target_phys_addr_t addr) +{ + fprintf(stderr,"SRead L @ %x\n",addr); + return 0; +} +static void scr_writeb(void*opaque, target_phys_addr_t addr, uint32_t value) +{ + switch(addr) + { + case 0x10000: break;//Screen brightness + case 0x18000: + case 0x18001: + case 0x18004: + break; + default: + fprintf(stderr,"BMAP Write B @ %x with %x\n",addr,value); + } +} +static void scr_writew(void*opaque, target_phys_addr_t addr, uint32_t value) +{ + fprintf(stderr,"SWrite w @ %x with %x\n",addr,value); +} +static void scr_writel(void*opaque, target_phys_addr_t addr, uint32_t value) +{ + + fprintf(stderr,"SWrite l @ %x with %x\n",addr,value); +} + +/* need to make more defines, put them into a header */ +#define RAM_SIZE 0x4000000 + +void serial_irq(void *opaque, int n, int level); +static void next_cube_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + /* Initialize the cpu core */ + CPUState *env = cpu_init("m68040"); + if (env == NULL) { + fprintf(stderr, "Unable to find m68k CPU definition\n"); + exit(1); + } + + /* Initialize CPU registers. */ + env->vbr = 0; + env->pc = 0x100001e; //technically should read vector + env->sr = 0x2700; + + /* Set internal registers to initial values */ + scr1 = 0x01000220; + scr2 = 0x00ff8880; + + int_mask = 0x88027640; + int_status= 0x200; + + /* Load RTC ram, needs to be in a function probably */ + { + rtc_ram = malloc(32); + #ifdef LOAD_RTC + FILE *fp = fopen("rtc.ram","rb"); + if(fread(rtc_ram,1,32,fp) != 32) + abort(); + fclose(fp); + #endif + memcpy(rtc_ram,rtc_ram2,32); + } + + + /* 64MB RAM starting at 0x4000000 */ + cpu_register_physical_memory(0x4000000, RAM_SIZE, + qemu_ram_alloc(NULL, "next-cube.ram", RAM_SIZE) | IO_MEM_RAM); + + /* Framebuffer */ + nextfb_init(&next_state); + + /* MMIO */ + cpu_register_physical_memory((uint32_t)0x2000000,0xD0000, + cpu_register_io_memory(mmio_read,mmio_write, (void *)env,DEVICE_NATIVE_ENDIAN)); + + /* BMAP */ //acts as a catch-all for now + cpu_register_physical_memory((uint32_t)0x2100000,0x3A7FF, + cpu_register_io_memory(scr_read,scr_write, (void *)env,DEVICE_NATIVE_ENDIAN)); + + /* KBD */ + nextkbd_init((void *)env); + + /* Serial */ + //CharDriverState *console = text_console_init(NULL); + //qemu_irq *serial = qemu_allocate_irqs(serial_irq, env, 2); + //escc_init(0x2118000, serial[0], serial[1], + // console, NULL, (9600*384),0); + + + /* Load ROM here */ + if(get_image_size(ROM_FILE) != 0x20000) + { + fprintf(stderr,"Failed to load rom file!\n"); + exit(1); + } + + rom_add_file_fixed(ROM_FILE,0x1000000,0); + rom_add_file_fixed(ROM_FILE,0x000000,1); + cpu_register_physical_memory((uint32_t)0x1000000, 0x20000, + qemu_ram_alloc(NULL, "next.rom", 0x20000) | IO_MEM_ROM); + cpu_register_physical_memory((uint32_t)0x000000, 0x20000, + qemu_ram_alloc(NULL, "nex.rom", 0x20000) | IO_MEM_ROM); + + /* Ethernet */ + nextnet_init((void *)env); + + +} + +void serial_irq(void *opaque, int n, int level) +{ + // fprintf(stderr,"IRQQQQQ\n"); + // int_status |= 0xFFFFFF00; +// int_status |= 1<<17; +//CPUM68KState *env = (CPUM68KState *)opaque; +//env->exception_index = 10; +//m68k_set_irq_level((CPUM68KState *)opaque, 5,29);//25); + +} +static QEMUMachine next_machine = { + .name = "next-cube", + .desc = "NeXT Cube", + .init = next_cube_init, +}; + +static void next_machine_init(void) +{ + qemu_register_machine(&next_machine); +} + +machine_init(next_machine_init);