public inbox for linux-sh@vger.kernel.org
 help / color / mirror / Atom feed
From: Kristoffer Ericson <kristoffer.ericson@gmail.com>
To: linux-sh@vger.kernel.org
Subject: Re: Concerning Qemu SH4
Date: Sat, 08 Nov 2008 19:37:14 +0000	[thread overview]
Message-ID: <20081108213718.8d2f41c4.kristoffer.ericson@gmail.com> (raw)
In-Reply-To: <20081108020202.0c9a4b59.kristoffer.ericson@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 23823 bytes --]

On Sun, 9 Nov 2008 00:28:35 +0900 (JST)
takasi-y@ops.dti.ne.jp wrote:

> Hi,
> 
> > Oki, gotten it to work now. Whats left is putting some sort 
> > of harddrive file there. I've created an loop file but
> > can't seem to get it going.
> Have you applied all patches on ML?
> Otherwise it doesn't support hard disk.
> QEMU repository is being maintained very slowly.
> There always many patches left on ML waiting for being merged.
> 
> Now, following patches are pending.
> http://lists.gnu.org/archive/html/qemu-devel/2008-10/msg00970.html
>  This must be applied. Otherwise it will be crashed frequently.
> http://lists.gnu.org/archive/html/qemu-devel/2008-10/msg01246.html
> http://lists.gnu.org/archive/html/qemu-devel/2008-10/msg01247.html
> http://lists.gnu.org/archive/html/qemu-devel/2008-10/msg01248.html
>  These three are needed use to use HDD.
> http://lists.gnu.org/archive/html/qemu-devel/2008-11/msg00118.html
> http://lists.gnu.org/archive/html/qemu-devel/2008-11/msg00119.html
>  These two are needed to use network.

Great!

> 
> Some of them can't be applied cleanly, because other patch has been
>  applied after I posted them. Please edit them manually.
> 

I've edited them and finally gotten everything to compile (without errors/warnings).
BUT I get segmentation fault at startup, I'm thinking it could be related
to me compiling with 4.1.x, so I'm going to give it a try with 3.4.x.

I've attached the up-to-date diff (and also below for everyone else).
Note that the sh_pci.c is just a regular file so it's not an patch.

> > I'm also missing something with the initrd as it
> > constantly claims that the initrd expands beyond
> > the memory boundry.
> Current code doesn't support --initrd nor --append.
> Only --kernel works. Use initramfs and initial command line.
> 
> /yoshii

/*
 * SuperH on-chip PCIC emulation.      
 *
 * Copyright (c) 2008 Takashi YOSHII
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to 
eal
 * 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 "sh.h"
#include "pci.h"

typedef struct {
    PCIBus *bus;
    PCIDevice *dev;
    uint32_t regbase;
    uint32_t iopbase;
    uint32_t membase;
    uint32_t par;
    uint32_t mbr;
    uint32_t iobr;
} SHPCIC;

static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
{
    SHPCIC *pcic = p;
    addr -= pcic->regbase;
    switch(addr) {
      case 0 ... 0xff: *(uint32_t*)(pcic->dev->config + addr) = val;
      case 0x1c0: pcic->par = val; break;
      case 0x1c4: pcic->mbr = val; break;
      case 0x1c8: pcic->iobr = val; break;
      case 0x220: pci_data_write(pcic->bus, pcic->par, val, 4);
    }
}

static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
{
    SHPCIC *pcic = p;
    addr -= pcic->regbase;
    switch(addr) {
      case 0 ... 0xff: return *(uint32_t*)(pcic->dev->config + addr);
      case 0x1c0: return pcic->par;
      case 0x220: return pci_data_read(pcic->bus, pcic->par, 4);
    }
    return 0;
}

static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr,
                               uint32_t val, int size)
{
    pci_data_write(pcic->bus, addr - pcic->membase + pcic->mbr, val, size);
}

static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr,
                                 int size)
{
    return pci_data_read(pcic->bus, addr - pcic->membase + pcic->mbr, size);
}

static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 1);
}

static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 2);
}

static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 4);
}

static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 1);
}

static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 2);
}

static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 4);
}

static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr)
{
    return addr - pcic->iopbase + pcic->iobr;
}

static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outb(NULL, sh_pci_addr2port(p, addr), val);
}

static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outw(NULL, sh_pci_addr2port(p, addr), val);
}

static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outl(NULL, sh_pci_addr2port(p, addr), val);
}

static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr)
{
    return cpu_inb(NULL, sh_pci_addr2port(p, addr));
}

static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr)
{
    return cpu_inw(NULL, sh_pci_addr2port(p, addr));
}

static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr)
{
    return cpu_inl(NULL, sh_pci_addr2port(p, addr));
}

typedef struct {
    CPUReadMemoryFunc *r[3];
    CPUWriteMemoryFunc *w[3];
} MemOp;

static MemOp sh_pci_reg = {
    { NULL, NULL, sh_pci_reg_read },
    { NULL, NULL, sh_pci_reg_write },
};

static MemOp sh_pci_mem = {
    { sh_pci_readb, sh_pci_readw, sh_pci_readl },
    { sh_pci_writeb, sh_pci_writew, sh_pci_writel },
};

static MemOp sh_pci_iop = {
    { sh_pci_inb, sh_pci_inw, sh_pci_inl },
    { sh_pci_outb, sh_pci_outw, sh_pci_outl },
};

PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                            qemu_irq *pic, int devfn_min, int nirq)
{
    SHPCIC *p;
    int mem, reg, iop;

    p = qemu_mallocz(sizeof(SHPCIC));
    p->bus = pci_register_bus(set_irq, map_irq, pic, devfn_min, nirq);

    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
                                 -1, NULL, NULL);
    p->regbase = 0x1e200000;
    p->iopbase = 0x1e240000;
    p->membase = 0xfd000000;
    reg = cpu_register_io_memory(0, sh_pci_reg.r, sh_pci_reg.w, p);
    mem = cpu_register_io_memory(0, sh_pci_mem.r, sh_pci_mem.w, p);
    iop = cpu_register_io_memory(0, sh_pci_iop.r, sh_pci_iop.w, p);
    cpu_register_physical_memory(p->regbase, 0x224, reg);
    cpu_register_physical_memory(p->iopbase, 0x40000, iop);
    cpu_register_physical_memory(p->membase, 0x1000000, mem);

    p->dev->config[0x00] = 0x54; // HITACHI
    p->dev->config[0x01] = 0x10; //
    p->dev->config[0x02] = 0x0e; // SH7751R
    p->dev->config[0x03] = 0x35; //
    p->dev->config[0x04] = 0x80;
    p->dev->config[0x05] = 0x00;
    p->dev->config[0x06] = 0x90;
    p->dev->config[0x07] = 0x02;

    return p->bus;
}



Index: target-sh4/helper.c
===================================================================
--- target-sh4/helper.c	(revision 5646)
+++ target-sh4/helper.c	(working copy)
@@ -359,14 +359,13 @@
 			   int *prot, target_ulong address,
 			   int rw, int access_type)
 {
-    int use_asid, is_code, n;
+    int use_asid, n;
     tlb_t *matching = NULL;
 
     use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
-    is_code = env->pc == address;	/* Hack */
 
     /* Use a hack to find if this is an instruction or data access */
-    if (env->pc == address && !(rw & PAGE_WRITE)) {
+    if (rw == 2) {
 	n = find_itlb_entry(env, address, use_asid, 1);
 	if (n >= 0) {
 	    matching = &env->itlb[n];
@@ -382,13 +381,13 @@
 	    switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) {
 	    case 0:		/* 000 */
 	    case 2:		/* 010 */
-		n = (rw & PAGE_WRITE) ? MMU_DTLB_VIOLATION_WRITE :
+		n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
 		    MMU_DTLB_VIOLATION_READ;
 		break;
 	    case 1:		/* 001 */
 	    case 4:		/* 100 */
 	    case 5:		/* 101 */
-		if (rw & PAGE_WRITE)
+		if (rw == 1)
 		    n = MMU_DTLB_VIOLATION_WRITE;
 		else
 		    *prot = PAGE_READ;
@@ -396,11 +395,11 @@
 	    case 3:		/* 011 */
 	    case 6:		/* 110 */
 	    case 7:		/* 111 */
-		*prot = rw & (PAGE_READ | PAGE_WRITE);
+		*prot = (rw == 1) ? PAGE_WRITE : PAGE_READ;
 		break;
 	    }
 	} else if (n == MMU_DTLB_MISS) {
-	    n = (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :
+	    n = (rw == 1) ? MMU_DTLB_MISS_WRITE :
 		MMU_DTLB_MISS_READ;
 	}
     }
@@ -426,8 +425,12 @@
 	    && (address < 0xe0000000 || address > 0xe4000000)) {
 	    /* Unauthorized access in user mode (only store queues are available) */
 	    fprintf(stderr, "Unauthorized access\n");
-	    return (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :
-		MMU_DTLB_MISS_READ;
+	    if (rw == 0)
+		return MMU_DTLB_MISS_READ;
+	    else if (rw == 1)
+		return MMU_DTLB_MISS_WRITE;
+	    else
+		return MMU_ITLB_MISS;
 	}
 	if (address >= 0x80000000 && address < 0xc0000000) {
 	    /* Mask upper 3 bits for P1 and P2 areas */
@@ -465,27 +468,6 @@
     target_ulong physical, page_offset, page_size;
     int prot, ret, access_type;
 
-    switch (rw) {
-    case 0:
-        rw = PAGE_READ;
-        break;
-    case 1:
-        rw = PAGE_WRITE;
-        break;
-    case 2: /* READ_ACCESS_TYPE == 2 defined in softmmu_template.h */
-        rw = PAGE_READ;
-        break;
-    default:
-        /* fatal error */
-        assert(0);
-    }
-
-    /* XXXXX */
-#if 0
-    fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n",
-	    __func__, env->pc, address, rw, mmu_idx, is_softmmu);
-#endif
-
     access_type = ACCESS_INT;
     ret =
 	get_physical_address(env, &physical, &prot, address, rw,
@@ -537,7 +519,7 @@
     target_ulong physical;
     int prot;
 
-    get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0);
+    get_physical_address(env, &physical, &prot, addr, 0, 0);
     return physical;
 }
 
Index: Makefile.target
===================================================================
--- Makefile.target	(revision 5646)
+++ Makefile.target	(working copy)
@@ -738,6 +738,7 @@
 ifeq ($(TARGET_BASE_ARCH), sh4)
 OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o sm501.o serial.o
+OBJS+= ide.o sh_pci.o
 endif
 ifeq ($(TARGET_BASE_ARCH), m68k)
 OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
Index: hw/r2d.c
===================================================================
--- hw/r2d.c	(revision 5646)
+++ hw/r2d.c	(working copy)
@@ -28,19 +28,24 @@
 #include "devices.h"
 #include "sysemu.h"
 #include "boards.h"
+#include "pci.h"
+#include "net.h"
+#include "sh7750_regs.h"
 
 #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
 #define SDRAM_SIZE 0x04000000
 
 #define SM501_VRAM_SIZE 0x800000
 
+#define PA_IRLMSK	0x00
 #define PA_POWOFF	0x30
 #define PA_VERREG	0x32
 #define PA_OUTPORT	0x36
 
 typedef struct {
     target_phys_addr_t base;
-
+    /*register */
+    uint16_t irlmsk;
     uint16_t bcr;
     uint16_t irlmon;
     uint16_t cfctl;
@@ -62,8 +67,54 @@
     uint16_t inport;
     uint16_t outport;
     uint16_t bverreg;
+
+    /* output_pin */
+    qemu_irq irl;
+
 } r2d_fpga_t;
 
+enum r2d_fgpa_irq {
+    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
+    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
+    NR_IRQS
+};
+
+static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
+    [CF_IDE]	=	{ 1, 1<<9  },
+    [CF_CD]	=	{ 2, 1<<8  },
+    [PCI_INTA]	=	{ 9, 1<<14 },
+    [PCI_INTB]	=	{10, 1<<13 },
+    [PCI_INTC]	=	{ 3, 1<<12 },
+    [PCI_INTD]	=	{ 0, 1<<11 },
+    [SM501]	=	{ 4, 1<<10 },
+    [KEY]	=	{ 5, 1<<6  },
+    [RTC_A]	=	{ 6, 1<<5  },
+    [RTC_T]	=	{ 7, 1<<4  },
+    [SDCARD]	=	{ 8, 1<<7  },
+    [EXT]	=	{11, 1<<0  },
+    [TP]	=	{12, 1<<15 },
+};
+
+static void update_irl(r2d_fpga_t *fpga)
+{
+    int i, irl = 15;
+    for (i = 0; i < NR_IRQS; i++)
+	if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
+	    if (irqtab[i].irl < irl)
+		irl = irqtab[i].irl;
+    qemu_set_irq(fpga->irl, irl ^ 15);
+}
+
+static void r2d_fpga_irq_set(void *opaque, int n, int level)
+{
+    r2d_fpga_t	*fpga = opaque;
+    if (level)
+	fpga->irlmon |= irqtab[n].msk;
+    else
+	fpga->irlmon &= ~irqtab[n].msk;
+    update_irl(fpga);
+}
+
 static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr)
 {
     r2d_fpga_t *s = opaque;
@@ -71,6 +122,8 @@
     addr -= s->base;
 
     switch (addr) {
+    case PA_IRLMSK:
+	return s->irlmsk;
     case PA_OUTPORT:
 	return s->outport;
     case PA_POWOFF:
@@ -90,6 +143,10 @@
     addr -= s->base;
 
     switch (addr) {
+    case PA_IRLMSK:
+	s->irlmsk = value;
+	update_irl(s);
+	break;
     case PA_OUTPORT:
 	s->outport = value;
 	break;
@@ -114,21 +171,35 @@
     NULL,
 };
 
-static void r2d_fpga_init(target_phys_addr_t base)
+static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
 {
     int iomemtype;
     r2d_fpga_t *s;
 
     s = qemu_mallocz(sizeof(r2d_fpga_t));
     if (!s)
-	return;
+	return NULL;
 
+    s->irl = irl;
+
     s->base = base;
     iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn,
 				       r2d_fpga_writefn, s);
     cpu_register_physical_memory(base, 0x40, iomemtype);
+    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
 }
 
+static void r2d_pci_set_irq(qemu_irq *p, int n, int l)
+{
+    qemu_set_irq(p[n], l);
+}
+
+static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
+    return intx[d->devfn>>3];
+}
+
 static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
               const char *boot_device, DisplayState * ds,
 	      const char *kernel_filename, const char *kernel_cmdline,
@@ -136,6 +207,10 @@
 {
     CPUState *env;
     struct SH7750State *s;
+    qemu_irq *irq;
+    PCIBus *pci;
+    int i;
+
     ram_addr_t sdram_addr, sm501_vga_ram_addr;
 
     if (!cpu_model)
@@ -151,14 +226,24 @@
     sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
     cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
     /* Register peripherals */
-    r2d_fpga_init(0x04000000);
+    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
+    pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
     s = sh7750_init(env);
     sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
     sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
 	       serial_hds[2]);
+
+    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
+	    drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL);
+
     /* Todo: register on board registers */
     {
       int kernel_size;
+      /* initialization which should be done by firmware */
+      uint32_t bcr1 = 1<<3; // cs3 SDRAM
+      uint16_t bcr2 = 3<<(3*2); // cs3 32bit
+      cpu_physical_memory_write(SH7750_BCR1_A7, &bcr1, 4);
+      cpu_physical_memory_write(SH7750_BCR2_A7, &bcr2, 2);
 
       kernel_size = load_image(kernel_filename, phys_ram_base);
 
Index: hw/sh.h
===================================================================
--- hw/sh.h	(revision 5646)
+++ hw/sh.h	(working copy)
@@ -42,7 +42,14 @@
 		     struct intc_source *tei_source,
 		     struct intc_source *bri_source);
 
+/* sh7750.c */
+qemu_irq sh7750_irl(struct SH7750State *s);
+
 /* tc58128.c */
 int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2);
 
+/* ide.c */
+void mmio_ide_init(target_phys_addr_t membase, target_phys_addr_t membase2,
+		    qemu_irq irq, int shift,
+		    BlockDriverState *hd0, BlockDriverState *hd1);
 #endif
Index: hw/sh7750.c
===================================================================
--- hw/sh7750.c	(revision 5646)
+++ hw/sh7750.c	(working copy)
@@ -41,6 +41,8 @@
     /* Peripheral frequency in Hz */
     uint32_t periph_freq;
     /* SDRAM controller */
+    uint32_t bcr1;
+    uint32_t bcr2;
     uint16_t rfcr;
     /* IO ports */
     uint16_t gpioic;
@@ -208,6 +210,8 @@
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR2_A7:
+	return s->bcr2;
     case SH7750_FRQCR_A7:
 	return 0;
     case SH7750_RFCR_A7:
@@ -231,6 +235,15 @@
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR1_A7:
+	return s->bcr1;
+    case SH7750_BCR4_A7:
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+	ignore_access("long read", addr);
+	return 0;
     case SH7750_MMUCR_A7:
 	return s->cpu->mmucr;
     case SH7750_PTEH_A7:
@@ -285,6 +298,8 @@
     switch (addr) {
 	/* SDRAM controller */
     case SH7750_BCR2_A7:
+	s->bcr2 = mem_value;
+	return;
     case SH7750_BCR3_A7:
     case SH7750_RTCOR_A7:
     case SH7750_RTCNT_A7:
@@ -331,6 +346,8 @@
     switch (addr) {
 	/* SDRAM controller */
     case SH7750_BCR1_A7:
+	s->bcr1 = mem_value;
+	return;
     case SH7750_BCR4_A7:
     case SH7750_WCR1_A7:
     case SH7750_WCR2_A7:
@@ -412,6 +429,8 @@
 	UNUSED = 0,
 
 	/* interrupt sources */
+	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
 	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
 	HUDI, GPIOI,
 	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
@@ -428,10 +447,34 @@
 
 	/* interrupt groups */
 	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
-
+	IRL,
 	NR_SOURCES,
 };
 
+static struct intc_vect vectors_irl[] = {
+	INTC_VECT(IRL_0, 0x200),
+	INTC_VECT(IRL_1, 0x220),
+	INTC_VECT(IRL_2, 0x240),
+	INTC_VECT(IRL_3, 0x260),
+	INTC_VECT(IRL_4, 0x280),
+	INTC_VECT(IRL_5, 0x2a0),
+	INTC_VECT(IRL_6, 0x2c0),
+	INTC_VECT(IRL_7, 0x2e0),
+	INTC_VECT(IRL_8, 0x300),
+	INTC_VECT(IRL_9, 0x320),
+	INTC_VECT(IRL_A, 0x340),
+	INTC_VECT(IRL_B, 0x360),
+	INTC_VECT(IRL_C, 0x380),
+	INTC_VECT(IRL_D, 0x3a0),
+	INTC_VECT(IRL_E, 0x3c0),
+};
+
+static struct intc_group groups_irl[] = {
+    INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+    IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E)
+};
+
+
 static struct intc_vect vectors[] = {
 	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -717,5 +760,15 @@
 				 NULL, 0);
     }
 
+    sh_intc_register_sources(&s->intc,
+				_INTC_ARRAY(vectors_irl),
+				_INTC_ARRAY(groups_irl));
     return s;
 }
+
+qemu_irq sh7750_irl(SH7750State *s)
+{
+    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
+    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
+				1)[0];
+}
Index: hw/ide.c
===================================================================
--- hw/ide.c	(revision 5646)
+++ hw/ide.c	(working copy)
@@ -3486,6 +3486,104 @@
 }
 
 /***********************************************************/
+/* MMIO based ide port
+ * This emulates IDE device connected directly to the CPU bus
+ * without dedicated ide controller, which is often seen on
+ * embedded boards.
+ */
+
+typedef struct {
+    void *dev;
+    int shift;
+} MMIOState;
+
+static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
+{
+    MMIOState *s = (MMIOState*)opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    addr >>= s->shift;
+    if (addr & 7)
+	return ide_ioport_read(ide, addr);
+    else
+	return ide_data_readw(ide, 0);
+}
+
+static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
+		uint32_t val)
+{
+    MMIOState *s = (MMIOState*) opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    addr >>= s->shift;
+    if (addr & 7)
+	ide_ioport_write(ide, addr, val);
+    else
+	ide_data_writew(ide, 0, val);
+}
+
+static CPUReadMemoryFunc *mmio_ide_reads[] = {
+    mmio_ide_read,
+    mmio_ide_read,
+    mmio_ide_read,
+};
+
+static CPUWriteMemoryFunc *mmio_ide_writes[] = {
+    mmio_ide_write,
+    mmio_ide_write,
+    mmio_ide_write,
+};
+
+static uint32_t mmio_ide_status_read (void *opaque, target_phys_addr_t addr)
+{
+    MMIOState *s = (MMIOState*) opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    return ide_status_read(ide, 0);
+}
+
+static void mmio_ide_cmd_write (void *opaque, target_phys_addr_t addr,
+	uint32_t val)
+{
+    MMIOState *s = (MMIOState*)opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    ide_cmd_write(ide, 0, val);
+}
+
+static CPUReadMemoryFunc *mmio_ide_status[] = {
+    mmio_ide_status_read,
+    mmio_ide_status_read,
+    mmio_ide_status_read,
+};
+
+static CPUWriteMemoryFunc *mmio_ide_cmd[] = {
+    mmio_ide_cmd_write,
+    mmio_ide_cmd_write,
+    mmio_ide_cmd_write,
+};
+
+void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+		qemu_irq irq, int shift, 
+		BlockDriverState *hd0, BlockDriverState *hd1)
+{
+    MMIOState *s = qemu_mallocz(sizeof(MMIOState));
+    IDEState *ide = qemu_mallocz(sizeof(IDEState) * 2);
+    int mem1, mem2;
+    
+    ide_init2(ide, hd0, hd1, irq);
+    
+    s->dev = ide;
+    s->shift = shift;
+    
+    mem1 = cpu_register_io_memory(0, mmio_ide_reads, mmio_ide_writes, s);
+    mem2 = cpu_register_io_memory(0, mmio_ide_status, mmio_ide_cmd, s);
+    cpu_register_physical_memory(membase, 16<<shift, mem1);
+    cpu_register_physical_memory(membase2, 2<<shift, mem2);
+}
+/***************************************************************************/
+    
+
+
+
+
+/***********************************************************/
 /* CF-ATA Microdrive */
 
 #define METADATA_SIZE	0x20
Index: hw/sh_intc.c
===================================================================
--- hw/sh_intc.c	(revision 5646)
+++ hw/sh_intc.c	(working copy)
@@ -451,3 +451,21 @@
 
     return 0;
 }
+
+/* Assert level <n> IRL interrupt 
+    0:deassert, 1:lowest priority... 15:highest priority */
+void sh_intc_set_irl(void *opaque, int n, int level)
+{
+    struct intc_source *s = opaque;
+    int i, irl = level ^ 15;
+    for (i = 0; (s = sh_intc_source(s->parent, s->next_enum_id)); i++) {
+	if (i == irl)
+	    sh_intc_toggle_source(s, s->enable_count?0:1, s->asserted?0:1);
+	else
+	    if (s->asserted)
+		sh_intc_toggle_source(s, 0, -1);
+	}
+}
+
+
+
Index: hw/sh_intc.h
===================================================================
--- hw/sh_intc.h	(revision 5646)
+++ hw/sh_intc.h	(working copy)
@@ -72,4 +72,6 @@
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs);
 
+void sh_intc_set_irl(void *opaque, int n, int level);
+
 #endif /* __SH_INTC_H__ */




-- 
Kristoffer Ericson <kristoffer.ericson@gmail.com>

[-- Attachment #1.2: big-sh4-svn-patch --]
[-- Type: application/octet-stream, Size: 15368 bytes --]

Index: target-sh4/helper.c
===================================================================
--- target-sh4/helper.c	(revision 5646)
+++ target-sh4/helper.c	(working copy)
@@ -359,14 +359,13 @@
 			   int *prot, target_ulong address,
 			   int rw, int access_type)
 {
-    int use_asid, is_code, n;
+    int use_asid, n;
     tlb_t *matching = NULL;
 
     use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
-    is_code = env->pc == address;	/* Hack */
 
     /* Use a hack to find if this is an instruction or data access */
-    if (env->pc == address && !(rw & PAGE_WRITE)) {
+    if (rw == 2) {
 	n = find_itlb_entry(env, address, use_asid, 1);
 	if (n >= 0) {
 	    matching = &env->itlb[n];
@@ -382,13 +381,13 @@
 	    switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) {
 	    case 0:		/* 000 */
 	    case 2:		/* 010 */
-		n = (rw & PAGE_WRITE) ? MMU_DTLB_VIOLATION_WRITE :
+		n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
 		    MMU_DTLB_VIOLATION_READ;
 		break;
 	    case 1:		/* 001 */
 	    case 4:		/* 100 */
 	    case 5:		/* 101 */
-		if (rw & PAGE_WRITE)
+		if (rw == 1)
 		    n = MMU_DTLB_VIOLATION_WRITE;
 		else
 		    *prot = PAGE_READ;
@@ -396,11 +395,11 @@
 	    case 3:		/* 011 */
 	    case 6:		/* 110 */
 	    case 7:		/* 111 */
-		*prot = rw & (PAGE_READ | PAGE_WRITE);
+		*prot = (rw == 1) ? PAGE_WRITE : PAGE_READ;
 		break;
 	    }
 	} else if (n == MMU_DTLB_MISS) {
-	    n = (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :
+	    n = (rw == 1) ? MMU_DTLB_MISS_WRITE :
 		MMU_DTLB_MISS_READ;
 	}
     }
@@ -426,8 +425,12 @@
 	    && (address < 0xe0000000 || address > 0xe4000000)) {
 	    /* Unauthorized access in user mode (only store queues are available) */
 	    fprintf(stderr, "Unauthorized access\n");
-	    return (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :
-		MMU_DTLB_MISS_READ;
+	    if (rw == 0)
+		return MMU_DTLB_MISS_READ;
+	    else if (rw == 1)
+		return MMU_DTLB_MISS_WRITE;
+	    else
+		return MMU_ITLB_MISS;
 	}
 	if (address >= 0x80000000 && address < 0xc0000000) {
 	    /* Mask upper 3 bits for P1 and P2 areas */
@@ -465,27 +468,6 @@
     target_ulong physical, page_offset, page_size;
     int prot, ret, access_type;
 
-    switch (rw) {
-    case 0:
-        rw = PAGE_READ;
-        break;
-    case 1:
-        rw = PAGE_WRITE;
-        break;
-    case 2: /* READ_ACCESS_TYPE == 2 defined in softmmu_template.h */
-        rw = PAGE_READ;
-        break;
-    default:
-        /* fatal error */
-        assert(0);
-    }
-
-    /* XXXXX */
-#if 0
-    fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n",
-	    __func__, env->pc, address, rw, mmu_idx, is_softmmu);
-#endif
-
     access_type = ACCESS_INT;
     ret =
 	get_physical_address(env, &physical, &prot, address, rw,
@@ -537,7 +519,7 @@
     target_ulong physical;
     int prot;
 
-    get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0);
+    get_physical_address(env, &physical, &prot, addr, 0, 0);
     return physical;
 }
 
Index: Makefile.target
===================================================================
--- Makefile.target	(revision 5646)
+++ Makefile.target	(working copy)
@@ -738,6 +738,7 @@
 ifeq ($(TARGET_BASE_ARCH), sh4)
 OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o sm501.o serial.o
+OBJS+= ide.o sh_pci.o
 endif
 ifeq ($(TARGET_BASE_ARCH), m68k)
 OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
Index: hw/r2d.c
===================================================================
--- hw/r2d.c	(revision 5646)
+++ hw/r2d.c	(working copy)
@@ -28,19 +28,24 @@
 #include "devices.h"
 #include "sysemu.h"
 #include "boards.h"
+#include "pci.h"
+#include "net.h"
+#include "sh7750_regs.h"
 
 #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
 #define SDRAM_SIZE 0x04000000
 
 #define SM501_VRAM_SIZE 0x800000
 
+#define PA_IRLMSK	0x00
 #define PA_POWOFF	0x30
 #define PA_VERREG	0x32
 #define PA_OUTPORT	0x36
 
 typedef struct {
     target_phys_addr_t base;
-
+    /*register */
+    uint16_t irlmsk;
     uint16_t bcr;
     uint16_t irlmon;
     uint16_t cfctl;
@@ -62,8 +67,54 @@
     uint16_t inport;
     uint16_t outport;
     uint16_t bverreg;
+
+    /* output_pin */
+    qemu_irq irl;
+
 } r2d_fpga_t;
 
+enum r2d_fgpa_irq {
+    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
+    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
+    NR_IRQS
+};
+
+static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
+    [CF_IDE]	=	{ 1, 1<<9  },
+    [CF_CD]	=	{ 2, 1<<8  },
+    [PCI_INTA]	=	{ 9, 1<<14 },
+    [PCI_INTB]	=	{10, 1<<13 },
+    [PCI_INTC]	=	{ 3, 1<<12 },
+    [PCI_INTD]	=	{ 0, 1<<11 },
+    [SM501]	=	{ 4, 1<<10 },
+    [KEY]	=	{ 5, 1<<6  },
+    [RTC_A]	=	{ 6, 1<<5  },
+    [RTC_T]	=	{ 7, 1<<4  },
+    [SDCARD]	=	{ 8, 1<<7  },
+    [EXT]	=	{11, 1<<0  },
+    [TP]	=	{12, 1<<15 },
+};
+
+static void update_irl(r2d_fpga_t *fpga)
+{
+    int i, irl = 15;
+    for (i = 0; i < NR_IRQS; i++)
+	if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
+	    if (irqtab[i].irl < irl)
+		irl = irqtab[i].irl;
+    qemu_set_irq(fpga->irl, irl ^ 15);
+}
+
+static void r2d_fpga_irq_set(void *opaque, int n, int level)
+{
+    r2d_fpga_t	*fpga = opaque;
+    if (level)
+	fpga->irlmon |= irqtab[n].msk;
+    else
+	fpga->irlmon &= ~irqtab[n].msk;
+    update_irl(fpga);
+}
+
 static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr)
 {
     r2d_fpga_t *s = opaque;
@@ -71,6 +122,8 @@
     addr -= s->base;
 
     switch (addr) {
+    case PA_IRLMSK:
+	return s->irlmsk;
     case PA_OUTPORT:
 	return s->outport;
     case PA_POWOFF:
@@ -90,6 +143,10 @@
     addr -= s->base;
 
     switch (addr) {
+    case PA_IRLMSK:
+	s->irlmsk = value;
+	update_irl(s);
+	break;
     case PA_OUTPORT:
 	s->outport = value;
 	break;
@@ -114,21 +171,35 @@
     NULL,
 };
 
-static void r2d_fpga_init(target_phys_addr_t base)
+static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
 {
     int iomemtype;
     r2d_fpga_t *s;
 
     s = qemu_mallocz(sizeof(r2d_fpga_t));
     if (!s)
-	return;
+	return NULL;
 
+    s->irl = irl;
+
     s->base = base;
     iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn,
 				       r2d_fpga_writefn, s);
     cpu_register_physical_memory(base, 0x40, iomemtype);
+    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
 }
 
+static void r2d_pci_set_irq(qemu_irq *p, int n, int l)
+{
+    qemu_set_irq(p[n], l);
+}
+
+static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
+    return intx[d->devfn>>3];
+}
+
 static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
               const char *boot_device, DisplayState * ds,
 	      const char *kernel_filename, const char *kernel_cmdline,
@@ -136,6 +207,10 @@
 {
     CPUState *env;
     struct SH7750State *s;
+    qemu_irq *irq;
+    PCIBus *pci;
+    int i;
+
     ram_addr_t sdram_addr, sm501_vga_ram_addr;
 
     if (!cpu_model)
@@ -151,14 +226,24 @@
     sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
     cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
     /* Register peripherals */
-    r2d_fpga_init(0x04000000);
+    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
+    pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
     s = sh7750_init(env);
     sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
     sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
 	       serial_hds[2]);
+
+    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
+	    drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL);
+
     /* Todo: register on board registers */
     {
       int kernel_size;
+      /* initialization which should be done by firmware */
+      uint32_t bcr1 = 1<<3; // cs3 SDRAM
+      uint16_t bcr2 = 3<<(3*2); // cs3 32bit
+      cpu_physical_memory_write(SH7750_BCR1_A7, &bcr1, 4);
+      cpu_physical_memory_write(SH7750_BCR2_A7, &bcr2, 2);
 
       kernel_size = load_image(kernel_filename, phys_ram_base);
 
Index: hw/sh.h
===================================================================
--- hw/sh.h	(revision 5646)
+++ hw/sh.h	(working copy)
@@ -42,7 +42,14 @@
 		     struct intc_source *tei_source,
 		     struct intc_source *bri_source);
 
+/* sh7750.c */
+qemu_irq sh7750_irl(struct SH7750State *s);
+
 /* tc58128.c */
 int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2);
 
+/* ide.c */
+void mmio_ide_init(target_phys_addr_t membase, target_phys_addr_t membase2,
+		    qemu_irq irq, int shift,
+		    BlockDriverState *hd0, BlockDriverState *hd1);
 #endif
Index: hw/sh7750.c
===================================================================
--- hw/sh7750.c	(revision 5646)
+++ hw/sh7750.c	(working copy)
@@ -41,6 +41,8 @@
     /* Peripheral frequency in Hz */
     uint32_t periph_freq;
     /* SDRAM controller */
+    uint32_t bcr1;
+    uint32_t bcr2;
     uint16_t rfcr;
     /* IO ports */
     uint16_t gpioic;
@@ -208,6 +210,8 @@
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR2_A7:
+	return s->bcr2;
     case SH7750_FRQCR_A7:
 	return 0;
     case SH7750_RFCR_A7:
@@ -231,6 +235,15 @@
     SH7750State *s = opaque;
 
     switch (addr) {
+    case SH7750_BCR1_A7:
+	return s->bcr1;
+    case SH7750_BCR4_A7:
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+	ignore_access("long read", addr);
+	return 0;
     case SH7750_MMUCR_A7:
 	return s->cpu->mmucr;
     case SH7750_PTEH_A7:
@@ -285,6 +298,8 @@
     switch (addr) {
 	/* SDRAM controller */
     case SH7750_BCR2_A7:
+	s->bcr2 = mem_value;
+	return;
     case SH7750_BCR3_A7:
     case SH7750_RTCOR_A7:
     case SH7750_RTCNT_A7:
@@ -331,6 +346,8 @@
     switch (addr) {
 	/* SDRAM controller */
     case SH7750_BCR1_A7:
+	s->bcr1 = mem_value;
+	return;
     case SH7750_BCR4_A7:
     case SH7750_WCR1_A7:
     case SH7750_WCR2_A7:
@@ -412,6 +429,8 @@
 	UNUSED = 0,
 
 	/* interrupt sources */
+	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
 	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
 	HUDI, GPIOI,
 	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
@@ -428,10 +447,34 @@
 
 	/* interrupt groups */
 	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
-
+	IRL,
 	NR_SOURCES,
 };
 
+static struct intc_vect vectors_irl[] = {
+	INTC_VECT(IRL_0, 0x200),
+	INTC_VECT(IRL_1, 0x220),
+	INTC_VECT(IRL_2, 0x240),
+	INTC_VECT(IRL_3, 0x260),
+	INTC_VECT(IRL_4, 0x280),
+	INTC_VECT(IRL_5, 0x2a0),
+	INTC_VECT(IRL_6, 0x2c0),
+	INTC_VECT(IRL_7, 0x2e0),
+	INTC_VECT(IRL_8, 0x300),
+	INTC_VECT(IRL_9, 0x320),
+	INTC_VECT(IRL_A, 0x340),
+	INTC_VECT(IRL_B, 0x360),
+	INTC_VECT(IRL_C, 0x380),
+	INTC_VECT(IRL_D, 0x3a0),
+	INTC_VECT(IRL_E, 0x3c0),
+};
+
+static struct intc_group groups_irl[] = {
+    INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+    IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E)
+};
+
+
 static struct intc_vect vectors[] = {
 	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -717,5 +760,15 @@
 				 NULL, 0);
     }
 
+    sh_intc_register_sources(&s->intc,
+				_INTC_ARRAY(vectors_irl),
+				_INTC_ARRAY(groups_irl));
     return s;
 }
+
+qemu_irq sh7750_irl(SH7750State *s)
+{
+    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
+    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
+				1)[0];
+}
Index: hw/ide.c
===================================================================
--- hw/ide.c	(revision 5646)
+++ hw/ide.c	(working copy)
@@ -3486,6 +3486,104 @@
 }
 
 /***********************************************************/
+/* MMIO based ide port
+ * This emulates IDE device connected directly to the CPU bus
+ * without dedicated ide controller, which is often seen on
+ * embedded boards.
+ */
+
+typedef struct {
+    void *dev;
+    int shift;
+} MMIOState;
+
+static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr)
+{
+    MMIOState *s = (MMIOState*)opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    addr >>= s->shift;
+    if (addr & 7)
+	return ide_ioport_read(ide, addr);
+    else
+	return ide_data_readw(ide, 0);
+}
+
+static void mmio_ide_write (void *opaque, target_phys_addr_t addr,
+		uint32_t val)
+{
+    MMIOState *s = (MMIOState*) opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    addr >>= s->shift;
+    if (addr & 7)
+	ide_ioport_write(ide, addr, val);
+    else
+	ide_data_writew(ide, 0, val);
+}
+
+static CPUReadMemoryFunc *mmio_ide_reads[] = {
+    mmio_ide_read,
+    mmio_ide_read,
+    mmio_ide_read,
+};
+
+static CPUWriteMemoryFunc *mmio_ide_writes[] = {
+    mmio_ide_write,
+    mmio_ide_write,
+    mmio_ide_write,
+};
+
+static uint32_t mmio_ide_status_read (void *opaque, target_phys_addr_t addr)
+{
+    MMIOState *s = (MMIOState*) opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    return ide_status_read(ide, 0);
+}
+
+static void mmio_ide_cmd_write (void *opaque, target_phys_addr_t addr,
+	uint32_t val)
+{
+    MMIOState *s = (MMIOState*)opaque;
+    IDEState *ide = (IDEState*)s->dev;
+    ide_cmd_write(ide, 0, val);
+}
+
+static CPUReadMemoryFunc *mmio_ide_status[] = {
+    mmio_ide_status_read,
+    mmio_ide_status_read,
+    mmio_ide_status_read,
+};
+
+static CPUWriteMemoryFunc *mmio_ide_cmd[] = {
+    mmio_ide_cmd_write,
+    mmio_ide_cmd_write,
+    mmio_ide_cmd_write,
+};
+
+void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+		qemu_irq irq, int shift, 
+		BlockDriverState *hd0, BlockDriverState *hd1)
+{
+    MMIOState *s = qemu_mallocz(sizeof(MMIOState));
+    IDEState *ide = qemu_mallocz(sizeof(IDEState) * 2);
+    int mem1, mem2;
+    
+    ide_init2(ide, hd0, hd1, irq);
+    
+    s->dev = ide;
+    s->shift = shift;
+    
+    mem1 = cpu_register_io_memory(0, mmio_ide_reads, mmio_ide_writes, s);
+    mem2 = cpu_register_io_memory(0, mmio_ide_status, mmio_ide_cmd, s);
+    cpu_register_physical_memory(membase, 16<<shift, mem1);
+    cpu_register_physical_memory(membase2, 2<<shift, mem2);
+}
+/***************************************************************************/
+    
+
+
+
+
+/***********************************************************/
 /* CF-ATA Microdrive */
 
 #define METADATA_SIZE	0x20
Index: hw/sh_intc.c
===================================================================
--- hw/sh_intc.c	(revision 5646)
+++ hw/sh_intc.c	(working copy)
@@ -451,3 +451,21 @@
 
     return 0;
 }
+
+/* Assert level <n> IRL interrupt 
+    0:deassert, 1:lowest priority... 15:highest priority */
+void sh_intc_set_irl(void *opaque, int n, int level)
+{
+    struct intc_source *s = opaque;
+    int i, irl = level ^ 15;
+    for (i = 0; (s = sh_intc_source(s->parent, s->next_enum_id)); i++) {
+	if (i == irl)
+	    sh_intc_toggle_source(s, s->enable_count?0:1, s->asserted?0:1);
+	else
+	    if (s->asserted)
+		sh_intc_toggle_source(s, 0, -1);
+	}
+}
+
+
+
Index: hw/sh_intc.h
===================================================================
--- hw/sh_intc.h	(revision 5646)
+++ hw/sh_intc.h	(working copy)
@@ -72,4 +72,6 @@
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs);
 
+void sh_intc_set_irl(void *opaque, int n, int level);
+
 #endif /* __SH_INTC_H__ */

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: plain-file-sh_pci.c --]
[-- Type: text/x-csrc; name="plain-file-sh_pci.c", Size: 5952 bytes --]

/*
 * SuperH on-chip PCIC emulation.      
 *
 * Copyright (c) 2008 Takashi YOSHII
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to 
eal
 * 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 "sh.h"
#include "pci.h"

typedef struct {
    PCIBus *bus;
    PCIDevice *dev;
    uint32_t regbase;
    uint32_t iopbase;
    uint32_t membase;
    uint32_t par;
    uint32_t mbr;
    uint32_t iobr;
} SHPCIC;

static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
{
    SHPCIC *pcic = p;
    addr -= pcic->regbase;
    switch(addr) {
      case 0 ... 0xff: *(uint32_t*)(pcic->dev->config + addr) = val;
      case 0x1c0: pcic->par = val; break;
      case 0x1c4: pcic->mbr = val; break;
      case 0x1c8: pcic->iobr = val; break;
      case 0x220: pci_data_write(pcic->bus, pcic->par, val, 4);
    }
}

static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
{
    SHPCIC *pcic = p;
    addr -= pcic->regbase;
    switch(addr) {
      case 0 ... 0xff: return *(uint32_t*)(pcic->dev->config + addr);
      case 0x1c0: return pcic->par;
      case 0x220: return pci_data_read(pcic->bus, pcic->par, 4);
    }
    return 0;
}

static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr,
                               uint32_t val, int size)
{
    pci_data_write(pcic->bus, addr - pcic->membase + pcic->mbr, val, size);
}

static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr,
                                 int size)
{
    return pci_data_read(pcic->bus, addr - pcic->membase + pcic->mbr, size);
}

static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 1);
}

static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 2);
}

static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val)
{
    sh_pci_data_write(p, addr, val, 4);
}

static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 1);
}

static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 2);
}

static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr)
{
    return sh_pci_mem_read(p, addr, 4);
}

static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr)
{
    return addr - pcic->iopbase + pcic->iobr;
}

static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outb(NULL, sh_pci_addr2port(p, addr), val);
}

static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outw(NULL, sh_pci_addr2port(p, addr), val);
}

static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val)
{
    cpu_outl(NULL, sh_pci_addr2port(p, addr), val);
}

static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr)
{
    return cpu_inb(NULL, sh_pci_addr2port(p, addr));
}

static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr)
{
    return cpu_inw(NULL, sh_pci_addr2port(p, addr));
}

static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr)
{
    return cpu_inl(NULL, sh_pci_addr2port(p, addr));
}

typedef struct {
    CPUReadMemoryFunc *r[3];
    CPUWriteMemoryFunc *w[3];
} MemOp;

static MemOp sh_pci_reg = {
    { NULL, NULL, sh_pci_reg_read },
    { NULL, NULL, sh_pci_reg_write },
};

static MemOp sh_pci_mem = {
    { sh_pci_readb, sh_pci_readw, sh_pci_readl },
    { sh_pci_writeb, sh_pci_writew, sh_pci_writel },
};

static MemOp sh_pci_iop = {
    { sh_pci_inb, sh_pci_inw, sh_pci_inl },
    { sh_pci_outb, sh_pci_outw, sh_pci_outl },
};

PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                            qemu_irq *pic, int devfn_min, int nirq)
{
    SHPCIC *p;
    int mem, reg, iop;

    p = qemu_mallocz(sizeof(SHPCIC));
    p->bus = pci_register_bus(set_irq, map_irq, pic, devfn_min, nirq);

    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
                                 -1, NULL, NULL);
    p->regbase = 0x1e200000;
    p->iopbase = 0x1e240000;
    p->membase = 0xfd000000;
    reg = cpu_register_io_memory(0, sh_pci_reg.r, sh_pci_reg.w, p);
    mem = cpu_register_io_memory(0, sh_pci_mem.r, sh_pci_mem.w, p);
    iop = cpu_register_io_memory(0, sh_pci_iop.r, sh_pci_iop.w, p);
    cpu_register_physical_memory(p->regbase, 0x224, reg);
    cpu_register_physical_memory(p->iopbase, 0x40000, iop);
    cpu_register_physical_memory(p->membase, 0x1000000, mem);

    p->dev->config[0x00] = 0x54; // HITACHI
    p->dev->config[0x01] = 0x10; //
    p->dev->config[0x02] = 0x0e; // SH7751R
    p->dev->config[0x03] = 0x35; //
    p->dev->config[0x04] = 0x80;
    p->dev->config[0x05] = 0x00;
    p->dev->config[0x06] = 0x90;
    p->dev->config[0x07] = 0x02;

    return p->bus;
}

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

  parent reply	other threads:[~2008-11-08 19:37 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-08  0:01 Concerning Qemu SH4 Kristoffer Ericson
2008-11-08 15:28 ` takasi-y
2008-11-08 19:37 ` Kristoffer Ericson [this message]
2008-11-08 19:42 ` Kristoffer Ericson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081108213718.8d2f41c4.kristoffer.ericson@gmail.com \
    --to=kristoffer.ericson@gmail.com \
    --cc=linux-sh@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox