qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] [RFC] sh: SM501 usb host emulation
@ 2008-12-27 15:02 Shin-ichiro KAWASAKI
  2009-01-03  5:52 ` Shin-ichiro KAWASAKI
  0 siblings, 1 reply; 4+ messages in thread
From: Shin-ichiro KAWASAKI @ 2008-12-27 15:02 UTC (permalink / raw)
  To: qemu-devel

Hi, all.

SM501 is a multi function device on sh4/r2d evaluation board.
Now, only its minimum graphics feature is implemented.
This patch adds SM501's usb host feature.

To use usb keyboard for sh4/r2d system emulation, we need to apply
another patch to add PCI usb host.  This patch avoids this work,
and provides more precise usb host emultation than PCI one.

Reviews and comments will be appreciated.
This patch modifies not only r2d/sm501 related source files but also
"hw/usb-ohci.c".  It should not have any impact on other board emulations'
usb feature.  Reviews from this point of view will be meaningful.

The changes for "hw/usb-ohci.c" are as follows.
 - 'localmem_base' is introduced as OHCIState struct menber.
   SM501 has a local memory, and it is used to pass and receive data with
   OHCI driver.  OHCI driver accesses it with SH4 physical memory address,
   and SM501 accesses it with SM501 local address.  'localmem_base' holds
   where the SM501 local memory is mapped into SH4 physical address space.
 - Memory access functions modified to adjust address with 'localmem_base'.
   The functions are, ohci_read_*(), ohci_put_*(), and ohci_copy_*().
 - ohci_read_hcca() and ohci_put_hcca() are introduced for more consistent
   implementation.

For other source files, it does,
 - introduces usb_ohci_init_sm501().
 - adds irq argument for SM501 initialization, to emulate USB interrupts.

Regards,
Shin-ichiro KAWASAKI


Signed-off-by: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp>

Index: trunk/hw/r2d.c
===================================================================
--- trunk/hw/r2d.c	(revision 6133)
+++ trunk/hw/r2d.c	(working copy)
@@ -223,7 +223,7 @@
 
     sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
     sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
-	       serial_hds[2]);
+	       irq[SM501], serial_hds[2]);
 
     /* onboard CF (True IDE mode, Master only). */
     mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
Index: trunk/hw/usb-ohci.c
===================================================================
--- trunk/hw/usb-ohci.c	(revision 6133)
+++ trunk/hw/usb-ohci.c	(working copy)
@@ -32,6 +32,7 @@
 #include "usb.h"
 #include "pci.h"
 #include "pxa.h"
+#include "devices.h"
 
 //#define DEBUG_OHCI
 /* Dump packet contents.  */
@@ -60,7 +61,8 @@
 
 enum ohci_type {
     OHCI_TYPE_PCI,
-    OHCI_TYPE_PXA
+    OHCI_TYPE_PXA,
+    OHCI_TYPE_SM501,
 };
 
 typedef struct {
@@ -108,6 +110,9 @@
     uint32_t hreset;
     uint32_t htest;
 
+    /* SM501 local memory offset */
+    target_phys_addr_t localmem_base;
+
     /* Active packets.  */
     uint32_t old_ctl;
     USBPacket usb_packet;
@@ -476,40 +481,67 @@
     return 1;
 }
 
-static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_read_ed(OHCIState *ohci,
+			       uint32_t addr, struct ohci_ed *ed)
 {
-    return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    return get_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)ed, sizeof(*ed) >> 2);
 }
 
-static inline int ohci_read_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_read_td(OHCIState *ohci,
+			       uint32_t addr, struct ohci_td *td)
 {
-    return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    return get_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)td, sizeof(*td) >> 2);
 }
 
-static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_read_iso_td(OHCIState *ohci,
+				   uint32_t addr, struct ohci_iso_td *td)
 {
-    return (get_dwords(addr, (uint32_t *)td, 4) &&
-            get_words(addr + 16, td->offset, 8));
+    return (get_dwords(addr + ohci->localmem_base, (uint32_t *)td, 4) &&
+            get_words(addr + 16 + ohci->localmem_base, td->offset, 8));
 }
 
-static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_read_hcca(OHCIState *ohci,
+				 uint32_t addr, struct ohci_hcca *hcca)
 {
-    return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+			   (uint8_t *)hcca, sizeof(*hcca), 0);
+    return 1;
 }
 
-static inline int ohci_put_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_put_ed(OHCIState *ohci,
+			      uint32_t addr, struct ohci_ed *ed)
 {
-    return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    return put_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)ed, sizeof(*ed) >> 2);
 }
 
-static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_put_td(OHCIState *ohci,
+			      uint32_t addr, struct ohci_td *td)
 {
-    return (put_dwords(addr, (uint32_t *)td, 4) &&
-            put_words(addr + 16, td->offset, 8));
+    return put_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)td, sizeof(*td) >> 2);
 }
 
+static inline int ohci_put_iso_td(OHCIState *ohci,
+				  uint32_t addr, struct ohci_iso_td *td)
+{
+    return (put_dwords(addr + ohci->localmem_base, (uint32_t *)td, 4) &&
+            put_words(addr + 16 + ohci->localmem_base, td->offset, 8));
+}
+
+static inline int ohci_put_hcca(OHCIState *ohci,
+				uint32_t addr, struct ohci_hcca *hcca)
+{
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+			   (uint8_t *)hcca, sizeof(*hcca), 1);
+    return 1;
+}
+
 /* Read/Write the contents of a TD from/to main memory.  */
-static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write)
+static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+			 uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
     uint32_t n;
@@ -518,17 +550,18 @@
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = td->be & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 /* Read/Write the contents of an ISO TD from/to main memory.  */
-static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr,
-                             uint8_t *buf, int len, int write)
+static void ohci_copy_iso_td(OHCIState *ohci,
+			     uint32_t start_addr, uint32_t end_addr,
+			     uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
     uint32_t n;
@@ -537,12 +570,12 @@
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = end_addr & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 static void ohci_process_lists(OHCIState *ohci, int completion);
@@ -579,7 +612,7 @@
 
     addr = ed->head & OHCI_DPTR_MASK;
 
-    if (!ohci_read_iso_td(addr, &iso_td)) {
+    if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
         printf("usb-ohci: ISO_TD read error at %x\n", addr);
         return 0;
     }
@@ -621,7 +654,7 @@
         i = OHCI_BM(iso_td.flags, TD_DI);
         if (i < ohci->done_count)
             ohci->done_count = i;
-        ohci_put_iso_td(addr, &iso_td);        
+        ohci_put_iso_td(ohci, addr, &iso_td);
         return 0;
     }
 
@@ -696,7 +729,7 @@
     }
 
     if (len && dir != OHCI_TD_DIR_IN) {
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
     }
 
     if (completion) {
@@ -732,7 +765,7 @@
     /* Writeback */
     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
         /* IN transfer succeeded */
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
                     OHCI_CC_NOERROR);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
@@ -788,7 +821,7 @@
         if (i < ohci->done_count)
             ohci->done_count = i;
     }
-    ohci_put_iso_td(addr, &iso_td);
+    ohci_put_iso_td(ohci, addr, &iso_td);
     return 1;
 }
 
@@ -818,7 +851,7 @@
 #endif
         return 1;
     }
-    if (!ohci_read_td(addr, &td)) {
+    if (!ohci_read_td(ohci, addr, &td)) {
         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
         return 0;
     }
@@ -859,7 +892,7 @@
         }
 
         if (len && dir != OHCI_TD_DIR_IN && !completion) {
-            ohci_copy_td(&td, ohci->usb_buf, len, 0);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0);
         }
     }
 
@@ -918,7 +951,7 @@
     }
     if (ret >= 0) {
         if (dir == OHCI_TD_DIR_IN) {
-            ohci_copy_td(&td, ohci->usb_buf, ret, 1);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
 #ifdef DEBUG_PACKET
             dprintf("  data:");
             for (i = 0; i < ret; i++)
@@ -987,7 +1020,7 @@
     i = OHCI_BM(td.flags, TD_DI);
     if (i < ohci->done_count)
         ohci->done_count = i;
-    ohci_put_td(addr, &td);
+    ohci_put_td(ohci, addr, &td);
     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
 }
 
@@ -1005,7 +1038,7 @@
         return 0;
 
     for (cur = head; cur; cur = next_ed) {
-        if (!ohci_read_ed(cur, &ed)) {
+        if (!ohci_read_ed(ohci, cur, &ed)) {
             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
             return 0;
         }
@@ -1046,7 +1079,7 @@
             }
         }
 
-        ohci_put_ed(cur, &ed);
+        ohci_put_ed(ohci, cur, &ed);
     }
 
     return active;
@@ -1087,7 +1120,7 @@
     OHCIState *ohci = opaque;
     struct ohci_hcca hcca;
 
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 0);
+    ohci_read_hcca(ohci, ohci->hcca, &hcca);
 
     /* Process all the lists at the end of the frame */
     if (ohci->ctl & OHCI_CTL_PLE) {
@@ -1131,7 +1164,7 @@
     ohci_sof(ohci);
 
     /* Writeback HCCA */
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 1);
+    ohci_put_hcca(ohci, ohci->hcca, &hcca);
 }
 
 /* Start sending SOF tokens across the USB bus, lists are processed in
@@ -1588,7 +1621,8 @@
 };
 
 static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
-            qemu_irq irq, enum ohci_type type, const char *name)
+                          qemu_irq irq, enum ohci_type type,
+			  const char *name, uint32_t localmem_base)
 {
     int i;
 
@@ -1609,6 +1643,7 @@
     }
 
     ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);
+    ohci->localmem_base = localmem_base;
     ohci->name = name;
 
     ohci->irq = irq;
@@ -1659,7 +1694,7 @@
     ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
 
     usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0],
-                  OHCI_TYPE_PCI, ohci->pci_dev.name);
+                  OHCI_TYPE_PCI, ohci->pci_dev.name, 0);
 
     pci_register_io_region((struct PCIDevice *)ohci, 0, 256,
                            PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
@@ -1671,7 +1706,19 @@
     OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
 
     usb_ohci_init(ohci, num_ports, devfn, irq,
-                  OHCI_TYPE_PXA, "OHCI USB");
+                  OHCI_TYPE_PXA, "OHCI USB", 0);
 
     cpu_register_physical_memory(base, 0x1000, ohci->mem);
 }
+
+void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
+			 int num_ports, int devfn, qemu_irq irq)
+{
+    OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
+
+    usb_ohci_init(ohci, num_ports, devfn, irq,
+                  OHCI_TYPE_SM501, "OHCI USB", localmem_base);
+
+    cpu_register_physical_memory(mmio_base, 0x1000, ohci->mem);
+}
+
Index: trunk/hw/sm501.c
===================================================================
--- trunk/hw/sm501.c	(revision 6133)
+++ trunk/hw/sm501.c	(working copy)
@@ -1061,7 +1061,7 @@
 }
 
 void sm501_init(DisplayState *ds, uint32_t base, unsigned long local_mem_base,
-		uint32_t local_mem_bytes, CharDriverState *chr)
+		uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
 {
     SM501State * s;
     int sm501_system_config_index;
@@ -1095,6 +1095,10 @@
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
                                  0x1000, sm501_disp_ctrl_index);
 
+    /* bridge to usb host emulation module */
+    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base, 
+			2, -1, irq);
+
     /* bridge to serial emulation module */
     if (chr)
 	serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
Index: trunk/hw/devices.h
===================================================================
--- trunk/hw/devices.h	(revision 6133)
+++ trunk/hw/devices.h	(working copy)
@@ -75,5 +75,8 @@
 
 /* sm501.c */
 void sm501_init(DisplayState *ds, uint32_t base, unsigned long local_mem_base,
-		uint32_t local_mem_bytes, CharDriverState *chr);
+		uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr);
+/* usb-ohci.c */
+void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
+			 int num_ports, int devfn, qemu_irq irq);
 #endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH] [RFC] sh: SM501 usb host emulation
  2008-12-27 15:02 [Qemu-devel] [PATCH] [RFC] sh: SM501 usb host emulation Shin-ichiro KAWASAKI
@ 2009-01-03  5:52 ` Shin-ichiro KAWASAKI
  2009-01-06 10:14   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 4+ messages in thread
From: Shin-ichiro KAWASAKI @ 2009-01-03  5:52 UTC (permalink / raw)
  To: qemu-devel

Shin-ichiro KAWASAKI wrote:
> Hi, all.
> 
> SM501 is a multi function device on sh4/r2d evaluation board.
> Now, only its minimum graphics feature is implemented.
> This patch adds SM501's usb host feature.
> 
> To use usb keyboard for sh4/r2d system emulation, we need to apply
> another patch to add PCI usb host.  This patch avoids this work,
> and provides more precise usb host emultation than PCI one.
> 
> Reviews and comments will be appreciated.
> This patch modifies not only r2d/sm501 related source files but also
> "hw/usb-ohci.c".  It should not have any impact on other board emulations'
> usb feature.  Reviews from this point of view will be meaningful.

I hope the patch to be applied to trunk, because now I believe it has
no impact for other board emulation, which has PCI usb host or PXA
usb host.

I've checked it with following way.
 - I built sh4/r2d system emulation environment with PCI usb host.
   Code was taken from qemu svn head and qemu-sh staging quilt repository.
   And I confirmed that USB keyboard works fine with it.
 - Applied the SM501 usb host patch to the environment.
 - Disabled SM501 usb host by killing off following lines in hw/sm501.c
    /* bridge to usb host emulation module */
    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base, 
			2, -1, irq);
 - Booted up the SH-Linux with the environment, and saw how the USB keyboard
   worked with PCI usb host.

As a result, PCI usb host works fine under the modification of SM501 usb
host patch. I didn't checked PXA usb host, but it shares whole codes with
PCI usb host emulation in "hw/usb-ohci.c".

Regards,
Shin-ichiro KAWASAKI

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH] [RFC] sh: SM501 usb host emulation
  2009-01-03  5:52 ` Shin-ichiro KAWASAKI
@ 2009-01-06 10:14   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-03-03 13:55     ` [Qemu-devel] [PATCH] [REPOST] sh: SM501 usb ohci emulation Shin-ichiro KAWASAKI
  0 siblings, 1 reply; 4+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-01-06 10:14 UTC (permalink / raw)
  To: Shin-ichiro KAWASAKI; +Cc: qemu-devel

On 14:52 Sat 03 Jan     , Shin-ichiro KAWASAKI wrote:
> Shin-ichiro KAWASAKI wrote:
> > Hi, all.
> > 
> > SM501 is a multi function device on sh4/r2d evaluation board.
> > Now, only its minimum graphics feature is implemented.
> > This patch adds SM501's usb host feature.
> > 
> > To use usb keyboard for sh4/r2d system emulation, we need to apply
> > another patch to add PCI usb host.  This patch avoids this work,
> > and provides more precise usb host emultation than PCI one.
> > 
> > Reviews and comments will be appreciated.
> > This patch modifies not only r2d/sm501 related source files but also
> > "hw/usb-ohci.c".  It should not have any impact on other board emulations'
> > usb feature.  Reviews from this point of view will be meaningful.
> 
> I hope the patch to be applied to trunk, because now I believe it has
> no impact for other board emulation, which has PCI usb host or PXA
> usb host.
> 
> I've checked it with following way.
>  - I built sh4/r2d system emulation environment with PCI usb host.
>    Code was taken from qemu svn head and qemu-sh staging quilt repository.
>    And I confirmed that USB keyboard works fine with it.
>  - Applied the SM501 usb host patch to the environment.
>  - Disabled SM501 usb host by killing off following lines in hw/sm501.c
>     /* bridge to usb host emulation module */
>     usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base, 
> 			2, -1, irq);
>  - Booted up the SH-Linux with the environment, and saw how the USB keyboard
>    worked with PCI usb host.
> 
> As a result, PCI usb host works fine under the modification of SM501 usb
> host patch. I didn't checked PXA usb host, but it shares whole codes with
> PCI usb host emulation in "hw/usb-ohci.c".
I agree too

I'll port the usb support on u-boot and test your patch

Best Regards,
J.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH] [REPOST] sh: SM501 usb ohci emulation
  2009-01-06 10:14   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-03-03 13:55     ` Shin-ichiro KAWASAKI
  0 siblings, 0 replies; 4+ messages in thread
From: Shin-ichiro KAWASAKI @ 2009-03-03 13:55 UTC (permalink / raw)
  To: qemu-devel

Shin-ichiro KAWASAKI wrote:
> Hi, all.
> 
> SM501 is a multi function device on sh4/r2d evaluation board.
> Now, only its minimum graphics feature is implemented.
> This patch adds SM501's usb host feature.

I post USB host patch for sh4/r2d, which applies to rev 6616.

This patch provide usb feature for sh4 system emulation users.
I've just confirmed that '-usb -usbdevice keyboard' works fine.

Regards,
Shin-ichiro KAWASAKI



Signed-off-by: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp>

Index: trunk/hw/r2d.c
===================================================================
--- trunk/hw/r2d.c	(revision 6676)
+++ trunk/hw/r2d.c	(working copy)
@@ -221,7 +221,7 @@
 
     sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
     sm501_init(0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
-	       serial_hds[2]);
+	       irq[SM501], serial_hds[2]);
 
     /* onboard CF (True IDE mode, Master only). */
     if ((i = drive_get_index(IF_IDE, 0, 0)) != -1)
Index: trunk/hw/usb-ohci.c
===================================================================
--- trunk/hw/usb-ohci.c	(revision 6676)
+++ trunk/hw/usb-ohci.c	(working copy)
@@ -32,6 +32,7 @@
 #include "usb.h"
 #include "pci.h"
 #include "pxa.h"
+#include "devices.h"
 
 //#define DEBUG_OHCI
 /* Dump packet contents.  */
@@ -60,7 +61,8 @@
 
 enum ohci_type {
     OHCI_TYPE_PCI,
-    OHCI_TYPE_PXA
+    OHCI_TYPE_PXA,
+    OHCI_TYPE_SM501,
 };
 
 typedef struct {
@@ -108,6 +110,9 @@
     uint32_t hreset;
     uint32_t htest;
 
+    /* SM501 local memory offset */
+    target_phys_addr_t localmem_base;
+
     /* Active packets.  */
     uint32_t old_ctl;
     USBPacket usb_packet;
@@ -476,40 +481,67 @@
     return 1;
 }
 
-static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_read_ed(OHCIState *ohci,
+			       uint32_t addr, struct ohci_ed *ed)
 {
-    return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    return get_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)ed, sizeof(*ed) >> 2);
 }
 
-static inline int ohci_read_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_read_td(OHCIState *ohci,
+			       uint32_t addr, struct ohci_td *td)
 {
-    return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    return get_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)td, sizeof(*td) >> 2);
 }
 
-static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_read_iso_td(OHCIState *ohci,
+				   uint32_t addr, struct ohci_iso_td *td)
 {
-    return (get_dwords(addr, (uint32_t *)td, 4) &&
-            get_words(addr + 16, td->offset, 8));
+    return (get_dwords(addr + ohci->localmem_base, (uint32_t *)td, 4) &&
+            get_words(addr + 16 + ohci->localmem_base, td->offset, 8));
 }
 
-static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed)
+static inline int ohci_read_hcca(OHCIState *ohci,
+				 uint32_t addr, struct ohci_hcca *hcca)
 {
-    return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+			   (uint8_t *)hcca, sizeof(*hcca), 0);
+    return 1;
 }
 
-static inline int ohci_put_td(uint32_t addr, struct ohci_td *td)
+static inline int ohci_put_ed(OHCIState *ohci,
+			      uint32_t addr, struct ohci_ed *ed)
 {
-    return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);
+    return put_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)ed, sizeof(*ed) >> 2);
 }
 
-static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td)
+static inline int ohci_put_td(OHCIState *ohci,
+			      uint32_t addr, struct ohci_td *td)
 {
-    return (put_dwords(addr, (uint32_t *)td, 4) &&
-            put_words(addr + 16, td->offset, 8));
+    return put_dwords(addr + ohci->localmem_base,
+		      (uint32_t *)td, sizeof(*td) >> 2);
 }
 
+static inline int ohci_put_iso_td(OHCIState *ohci,
+				  uint32_t addr, struct ohci_iso_td *td)
+{
+    return (put_dwords(addr + ohci->localmem_base, (uint32_t *)td, 4) &&
+            put_words(addr + 16 + ohci->localmem_base, td->offset, 8));
+}
+
+static inline int ohci_put_hcca(OHCIState *ohci,
+				uint32_t addr, struct ohci_hcca *hcca)
+{
+    cpu_physical_memory_rw(addr + ohci->localmem_base,
+			   (uint8_t *)hcca, sizeof(*hcca), 1);
+    return 1;
+}
+
 /* Read/Write the contents of a TD from/to main memory.  */
-static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write)
+static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+			 uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
     uint32_t n;
@@ -518,17 +550,18 @@
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = td->be & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 /* Read/Write the contents of an ISO TD from/to main memory.  */
-static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr,
-                             uint8_t *buf, int len, int write)
+static void ohci_copy_iso_td(OHCIState *ohci,
+			     uint32_t start_addr, uint32_t end_addr,
+			     uint8_t *buf, int len, int write)
 {
     uint32_t ptr;
     uint32_t n;
@@ -537,12 +570,12 @@
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    cpu_physical_memory_rw(ptr, buf, n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
     if (n == len)
         return;
     ptr = end_addr & ~0xfffu;
     buf += n;
-    cpu_physical_memory_rw(ptr, buf, len - n, write);
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
 }
 
 static void ohci_process_lists(OHCIState *ohci, int completion);
@@ -579,7 +612,7 @@
 
     addr = ed->head & OHCI_DPTR_MASK;
 
-    if (!ohci_read_iso_td(addr, &iso_td)) {
+    if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
         printf("usb-ohci: ISO_TD read error at %x\n", addr);
         return 0;
     }
@@ -621,7 +654,7 @@
         i = OHCI_BM(iso_td.flags, TD_DI);
         if (i < ohci->done_count)
             ohci->done_count = i;
-        ohci_put_iso_td(addr, &iso_td);        
+        ohci_put_iso_td(ohci, addr, &iso_td);
         return 0;
     }
 
@@ -696,7 +729,7 @@
     }
 
     if (len && dir != OHCI_TD_DIR_IN) {
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
     }
 
     if (completion) {
@@ -732,7 +765,7 @@
     /* Writeback */
     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
         /* IN transfer succeeded */
-        ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1);
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
                     OHCI_CC_NOERROR);
         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
@@ -788,7 +821,7 @@
         if (i < ohci->done_count)
             ohci->done_count = i;
     }
-    ohci_put_iso_td(addr, &iso_td);
+    ohci_put_iso_td(ohci, addr, &iso_td);
     return 1;
 }
 
@@ -818,7 +851,7 @@
 #endif
         return 1;
     }
-    if (!ohci_read_td(addr, &td)) {
+    if (!ohci_read_td(ohci, addr, &td)) {
         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
         return 0;
     }
@@ -859,7 +892,7 @@
         }
 
         if (len && dir != OHCI_TD_DIR_IN && !completion) {
-            ohci_copy_td(&td, ohci->usb_buf, len, 0);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0);
         }
     }
 
@@ -918,7 +951,7 @@
     }
     if (ret >= 0) {
         if (dir == OHCI_TD_DIR_IN) {
-            ohci_copy_td(&td, ohci->usb_buf, ret, 1);
+            ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
 #ifdef DEBUG_PACKET
             dprintf("  data:");
             for (i = 0; i < ret; i++)
@@ -987,7 +1020,7 @@
     i = OHCI_BM(td.flags, TD_DI);
     if (i < ohci->done_count)
         ohci->done_count = i;
-    ohci_put_td(addr, &td);
+    ohci_put_td(ohci, addr, &td);
     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
 }
 
@@ -1005,7 +1038,7 @@
         return 0;
 
     for (cur = head; cur; cur = next_ed) {
-        if (!ohci_read_ed(cur, &ed)) {
+        if (!ohci_read_ed(ohci, cur, &ed)) {
             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
             return 0;
         }
@@ -1046,7 +1079,7 @@
             }
         }
 
-        ohci_put_ed(cur, &ed);
+        ohci_put_ed(ohci, cur, &ed);
     }
 
     return active;
@@ -1087,7 +1120,7 @@
     OHCIState *ohci = opaque;
     struct ohci_hcca hcca;
 
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 0);
+    ohci_read_hcca(ohci, ohci->hcca, &hcca);
 
     /* Process all the lists at the end of the frame */
     if (ohci->ctl & OHCI_CTL_PLE) {
@@ -1131,7 +1164,7 @@
     ohci_sof(ohci);
 
     /* Writeback HCCA */
-    cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 1);
+    ohci_put_hcca(ohci, ohci->hcca, &hcca);
 }
 
 /* Start sending SOF tokens across the USB bus, lists are processed in
@@ -1620,7 +1653,8 @@
 };
 
 static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
-            qemu_irq irq, enum ohci_type type, const char *name)
+                          qemu_irq irq, enum ohci_type type,
+			  const char *name, uint32_t localmem_base)
 {
     int i;
 
@@ -1641,6 +1675,7 @@
     }
 
     ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);
+    ohci->localmem_base = localmem_base;
     ohci->name = name;
 
     ohci->irq = irq;
@@ -1686,7 +1721,7 @@
     ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
 
     usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0],
-                  OHCI_TYPE_PCI, ohci->pci_dev.name);
+                  OHCI_TYPE_PCI, ohci->pci_dev.name, 0);
 
     pci_register_io_region((struct PCIDevice *)ohci, 0, 256,
                            PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
@@ -1698,7 +1733,19 @@
     OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
 
     usb_ohci_init(ohci, num_ports, devfn, irq,
-                  OHCI_TYPE_PXA, "OHCI USB");
+                  OHCI_TYPE_PXA, "OHCI USB", 0);
 
     cpu_register_physical_memory(base, 0x1000, ohci->mem);
 }
+
+void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
+			 int num_ports, int devfn, qemu_irq irq)
+{
+    OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
+
+    usb_ohci_init(ohci, num_ports, devfn, irq,
+                  OHCI_TYPE_SM501, "OHCI USB", localmem_base);
+
+    cpu_register_physical_memory(mmio_base, 0x1000, ohci->mem);
+}
+
Index: trunk/hw/sm501.c
===================================================================
--- trunk/hw/sm501.c	(revision 6676)
+++ trunk/hw/sm501.c	(working copy)
@@ -1051,7 +1051,7 @@
 }
 
 void sm501_init(uint32_t base, unsigned long local_mem_base,
-		uint32_t local_mem_bytes, CharDriverState *chr)
+		uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
 {
     SM501State * s;
     int sm501_system_config_index;
@@ -1084,6 +1084,10 @@
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
                                  0x1000, sm501_disp_ctrl_index);
 
+    /* bridge to usb host emulation module */
+    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base, 
+			2, -1, irq);
+
     /* bridge to serial emulation module */
     if (chr)
 	serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
Index: trunk/hw/devices.h
===================================================================
--- trunk/hw/devices.h	(revision 6676)
+++ trunk/hw/devices.h	(working copy)
@@ -75,5 +75,9 @@
 
 /* sm501.c */
 void sm501_init(uint32_t base, unsigned long local_mem_base,
-		uint32_t local_mem_bytes, CharDriverState *chr);
+		uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr);
+
+/* usb-ohci.c */
+void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
+			 int num_ports, int devfn, qemu_irq irq);
 #endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-03-03 13:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-27 15:02 [Qemu-devel] [PATCH] [RFC] sh: SM501 usb host emulation Shin-ichiro KAWASAKI
2009-01-03  5:52 ` Shin-ichiro KAWASAKI
2009-01-06 10:14   ` Jean-Christophe PLAGNIOL-VILLARD
2009-03-03 13:55     ` [Qemu-devel] [PATCH] [REPOST] sh: SM501 usb ohci emulation Shin-ichiro KAWASAKI

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).