diff mbox

[04/10] sm501: Add emulation of chip connected via PCI

Message ID 4bed0ec61e74992657933af970366a9e2636589a.1487522123.git.balaton@eik.bme.hu (mailing list archive)
State New, archived
Headers show

Commit Message

BALATON Zoltan Feb. 19, 2017, 4:35 p.m. UTC
Only the display controller part is created automatically on PCI

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/display/sm501.c          | 58 +++++++++++++++++++++++++++++++++++++++++----
 hw/display/sm501_template.h |  8 +++----
 2 files changed, 58 insertions(+), 8 deletions(-)

Comments

Peter Maydell Feb. 24, 2017, 2:43 p.m. UTC | #1
On 19 February 2017 at 16:35, BALATON Zoltan <balaton@eik.bme.hu> wrote:
> Only the display controller part is created automatically on PCI
>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/display/sm501.c          | 58 +++++++++++++++++++++++++++++++++++++++++----
>  hw/display/sm501_template.h |  8 +++----
>  2 files changed, 58 insertions(+), 8 deletions(-)
>
> diff --git a/hw/display/sm501.c b/hw/display/sm501.c
> index b592022..e966896 100644
> --- a/hw/display/sm501.c
> +++ b/hw/display/sm501.c
> @@ -31,6 +31,7 @@
>  #include "ui/console.h"
>  #include "hw/devices.h"
>  #include "hw/sysbus.h"
> +#include "hw/pci/pci.h"
>  #include "qemu/range.h"
>  #include "ui/pixel_ops.h"
>  #include "exec/address-spaces.h"
> @@ -460,7 +461,6 @@ typedef struct SM501State {
>      QemuConsole *con;
>
>      /* status & internal resources */
> -    hwaddr base;
>      uint32_t local_mem_size_index;
>      uint8_t *local_mem;
>      MemoryRegion local_mem_region;
> @@ -1397,12 +1397,11 @@ static const GraphicHwOps sm501_ops = {
>      .gfx_update  = sm501_update_display,
>  };
>
> -static void sm501_init(SM501State *s, DeviceState *dev, uint32_t base,
> +static void sm501_init(SM501State *s, DeviceState *dev,
>                         uint32_t local_mem_bytes)
>  {
>      MemoryRegion *mr;
>
> -    s->base = base;
>      s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
>      SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s),
>                    s->local_mem_size_index);
> @@ -1457,7 +1456,7 @@ static void sm501_realize_sysbus(DeviceState *dev, Error **errp)
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>      DeviceState *usb_dev;
>
> -    sm501_init(&s->state, dev, s->base, s->vram_size);
> +    sm501_init(&s->state, dev, s->vram_size);
>      sysbus_init_mmio(sbd, &s->state.local_mem_region);
>      sysbus_init_mmio(sbd, &s->state.mmio_region);
>
> @@ -1505,9 +1504,60 @@ static const TypeInfo sm501_sysbus_info = {
>      .class_init    = sm501_sysbus_class_init,
>  };
>
> +#define TYPE_PCI_SM501 "sm501"
> +#define PCI_SM501(obj) OBJECT_CHECK(SM501PCIState, (obj), TYPE_PCI_SM501)
> +
> +typedef struct {
> +    /*< private >*/
> +    PCIDevice parent_obj;
> +    /*< public >*/
> +    SM501State state;
> +    uint32_t vram_size;
> +} SM501PCIState;
> +
> +static void sm501_realize_pci(PCIDevice *dev, Error **errp)
> +{
> +    SM501PCIState *s = PCI_SM501(dev);
> +
> +    sm501_init(&s->state, DEVICE(dev), s->vram_size);
> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
> +                     &s->state.local_mem_region);
> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
> +                     &s->state.mmio_region);
> +}
> +
> +static Property sm501_pci_properties[] = {
> +    DEFINE_PROP_UINT32("vram-size", SM501PCIState, vram_size,
> +                       64 * 1024 * 1024),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void sm501_pci_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> +    k->realize = sm501_realize_pci;
> +    k->vendor_id = 0x126f;
> +    k->device_id = 0x0501;
> +    k->class_id = PCI_CLASS_DISPLAY_OTHER;
> +    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
> +    dc->desc = "SM501 Display Controller";
> +    dc->props = sm501_pci_properties;
> +    dc->hotpluggable = false;

This needs a reset function and a vmsd as well.

> +}
> +
> +static const TypeInfo sm501_pci_info = {
> +    .name          = TYPE_PCI_SM501,
> +    .parent        = TYPE_PCI_DEVICE,
> +    .instance_size = sizeof(SM501PCIState),
> +    .class_init    = sm501_pci_class_init,
> +};
> +
>  static void sm501_register_types(void)
>  {
>      type_register_static(&sm501_sysbus_info);
> +    type_register_static(&sm501_pci_info);
>  }
>
>  type_init(sm501_register_types)
> diff --git a/hw/display/sm501_template.h b/hw/display/sm501_template.h
> index 16e500b..832ee61 100644
> --- a/hw/display/sm501_template.h
> +++ b/hw/display/sm501_template.h
> @@ -103,13 +103,13 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
>                   uint8_t *palette, int c_y, uint8_t *d, int width)
>  {
>      int x, i;
> -    uint8_t bitset = 0;
> +    uint8_t *pixval, bitset = 0;
>
>      /* get hardware cursor pattern */
>      uint32_t cursor_addr = get_hwc_address(s, crt);
>      assert(0 <= c_y && c_y < SM501_HWC_HEIGHT);
>      cursor_addr += SM501_HWC_WIDTH * c_y / 4;  /* 4 pixels per byte */
> -    cursor_addr += s->base;
> +    pixval = s->local_mem + cursor_addr;
>
>      /* get cursor position */
>      x = get_hwc_x(s, crt);
> @@ -120,8 +120,8 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
>
>          /* get pixel value */
>          if (i % 4 == 0) {
> -            bitset = ldub_phys(&address_space_memory, cursor_addr);
> -            cursor_addr++;
> +            bitset = ldub_p(pixval);
> +            pixval++;
>          }
>          v = bitset & 3;
>          bitset >>= 2;

Dropping the requirement for a base addr is not really the same
change as adding the PCI device.

thanks
-- PMM
BALATON Zoltan Feb. 24, 2017, 8:25 p.m. UTC | #2
On Fri, 24 Feb 2017, Peter Maydell wrote:
> On 19 February 2017 at 16:35, BALATON Zoltan <balaton@eik.bme.hu> wrote:
>> Only the display controller part is created automatically on PCI
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>  hw/display/sm501.c          | 58 +++++++++++++++++++++++++++++++++++++++++----
>>  hw/display/sm501_template.h |  8 +++----
>>  2 files changed, 58 insertions(+), 8 deletions(-)
>>
>> diff --git a/hw/display/sm501.c b/hw/display/sm501.c
>> index b592022..e966896 100644
>> --- a/hw/display/sm501.c
>> +++ b/hw/display/sm501.c
>> @@ -31,6 +31,7 @@
>>  #include "ui/console.h"
>>  #include "hw/devices.h"
>>  #include "hw/sysbus.h"
>> +#include "hw/pci/pci.h"
>>  #include "qemu/range.h"
>>  #include "ui/pixel_ops.h"
>>  #include "exec/address-spaces.h"
>> @@ -460,7 +461,6 @@ typedef struct SM501State {
>>      QemuConsole *con;
>>
>>      /* status & internal resources */
>> -    hwaddr base;
>>      uint32_t local_mem_size_index;
>>      uint8_t *local_mem;
>>      MemoryRegion local_mem_region;
>> @@ -1397,12 +1397,11 @@ static const GraphicHwOps sm501_ops = {
>>      .gfx_update  = sm501_update_display,
>>  };
>>
>> -static void sm501_init(SM501State *s, DeviceState *dev, uint32_t base,
>> +static void sm501_init(SM501State *s, DeviceState *dev,
>>                         uint32_t local_mem_bytes)
>>  {
>>      MemoryRegion *mr;
>>
>> -    s->base = base;
>>      s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
>>      SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s),
>>                    s->local_mem_size_index);
>> @@ -1457,7 +1456,7 @@ static void sm501_realize_sysbus(DeviceState *dev, Error **errp)
>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>      DeviceState *usb_dev;
>>
>> -    sm501_init(&s->state, dev, s->base, s->vram_size);
>> +    sm501_init(&s->state, dev, s->vram_size);
>>      sysbus_init_mmio(sbd, &s->state.local_mem_region);
>>      sysbus_init_mmio(sbd, &s->state.mmio_region);
>>
>> @@ -1505,9 +1504,60 @@ static const TypeInfo sm501_sysbus_info = {
>>      .class_init    = sm501_sysbus_class_init,
>>  };
>>
>> +#define TYPE_PCI_SM501 "sm501"
>> +#define PCI_SM501(obj) OBJECT_CHECK(SM501PCIState, (obj), TYPE_PCI_SM501)
>> +
>> +typedef struct {
>> +    /*< private >*/
>> +    PCIDevice parent_obj;
>> +    /*< public >*/
>> +    SM501State state;
>> +    uint32_t vram_size;
>> +} SM501PCIState;
>> +
>> +static void sm501_realize_pci(PCIDevice *dev, Error **errp)
>> +{
>> +    SM501PCIState *s = PCI_SM501(dev);
>> +
>> +    sm501_init(&s->state, DEVICE(dev), s->vram_size);
>> +    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
>> +                     &s->state.local_mem_region);
>> +    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
>> +                     &s->state.mmio_region);
>> +}
>> +
>> +static Property sm501_pci_properties[] = {
>> +    DEFINE_PROP_UINT32("vram-size", SM501PCIState, vram_size,
>> +                       64 * 1024 * 1024),
>> +    DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void sm501_pci_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>> +
>> +    k->realize = sm501_realize_pci;
>> +    k->vendor_id = 0x126f;
>> +    k->device_id = 0x0501;
>> +    k->class_id = PCI_CLASS_DISPLAY_OTHER;
>> +    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>> +    dc->desc = "SM501 Display Controller";
>> +    dc->props = sm501_pci_properties;
>> +    dc->hotpluggable = false;
>
> This needs a reset function and a vmsd as well.
>
>> +}
>> +
>> +static const TypeInfo sm501_pci_info = {
>> +    .name          = TYPE_PCI_SM501,
>> +    .parent        = TYPE_PCI_DEVICE,
>> +    .instance_size = sizeof(SM501PCIState),
>> +    .class_init    = sm501_pci_class_init,
>> +};
>> +
>>  static void sm501_register_types(void)
>>  {
>>      type_register_static(&sm501_sysbus_info);
>> +    type_register_static(&sm501_pci_info);
>>  }
>>
>>  type_init(sm501_register_types)
>> diff --git a/hw/display/sm501_template.h b/hw/display/sm501_template.h
>> index 16e500b..832ee61 100644
>> --- a/hw/display/sm501_template.h
>> +++ b/hw/display/sm501_template.h
>> @@ -103,13 +103,13 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
>>                   uint8_t *palette, int c_y, uint8_t *d, int width)
>>  {
>>      int x, i;
>> -    uint8_t bitset = 0;
>> +    uint8_t *pixval, bitset = 0;
>>
>>      /* get hardware cursor pattern */
>>      uint32_t cursor_addr = get_hwc_address(s, crt);
>>      assert(0 <= c_y && c_y < SM501_HWC_HEIGHT);
>>      cursor_addr += SM501_HWC_WIDTH * c_y / 4;  /* 4 pixels per byte */
>> -    cursor_addr += s->base;
>> +    pixval = s->local_mem + cursor_addr;
>>
>>      /* get cursor position */
>>      x = get_hwc_x(s, crt);
>> @@ -120,8 +120,8 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
>>
>>          /* get pixel value */
>>          if (i % 4 == 0) {
>> -            bitset = ldub_phys(&address_space_memory, cursor_addr);
>> -            cursor_addr++;
>> +            bitset = ldub_p(pixval);
>> +            pixval++;
>>          }
>>          v = bitset & 3;
>>          bitset >>= 2;
>
> Dropping the requirement for a base addr is not really the same
> change as adding the PCI device.

This is needed for PCI device because the base is not accessible before 
something maps the BARs of the device so I had to use something else that 
is known. So this change is part of making it a PCI device but I could 
make this a separate patch if you think that's better. Should I split it 
off or can leave it here?
Peter Maydell Feb. 25, 2017, 4:14 p.m. UTC | #3
On 24 February 2017 at 20:25, BALATON Zoltan <balaton@eik.bme.hu> wrote:
> On Fri, 24 Feb 2017, Peter Maydell wrote:
>> Dropping the requirement for a base addr is not really the same
>> change as adding the PCI device.
>
>
> This is needed for PCI device because the base is not accessible before
> something maps the BARs of the device so I had to use something else that is
> known. So this change is part of making it a PCI device but I could make
> this a separate patch if you think that's better. Should I split it off or
> can leave it here?

I would split it off.

thanks
-- PMM
diff mbox

Patch

diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index b592022..e966896 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -31,6 +31,7 @@ 
 #include "ui/console.h"
 #include "hw/devices.h"
 #include "hw/sysbus.h"
+#include "hw/pci/pci.h"
 #include "qemu/range.h"
 #include "ui/pixel_ops.h"
 #include "exec/address-spaces.h"
@@ -460,7 +461,6 @@  typedef struct SM501State {
     QemuConsole *con;
 
     /* status & internal resources */
-    hwaddr base;
     uint32_t local_mem_size_index;
     uint8_t *local_mem;
     MemoryRegion local_mem_region;
@@ -1397,12 +1397,11 @@  static const GraphicHwOps sm501_ops = {
     .gfx_update  = sm501_update_display,
 };
 
-static void sm501_init(SM501State *s, DeviceState *dev, uint32_t base,
+static void sm501_init(SM501State *s, DeviceState *dev,
                        uint32_t local_mem_bytes)
 {
     MemoryRegion *mr;
 
-    s->base = base;
     s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
     SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s),
                   s->local_mem_size_index);
@@ -1457,7 +1456,7 @@  static void sm501_realize_sysbus(DeviceState *dev, Error **errp)
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     DeviceState *usb_dev;
 
-    sm501_init(&s->state, dev, s->base, s->vram_size);
+    sm501_init(&s->state, dev, s->vram_size);
     sysbus_init_mmio(sbd, &s->state.local_mem_region);
     sysbus_init_mmio(sbd, &s->state.mmio_region);
 
@@ -1505,9 +1504,60 @@  static const TypeInfo sm501_sysbus_info = {
     .class_init    = sm501_sysbus_class_init,
 };
 
+#define TYPE_PCI_SM501 "sm501"
+#define PCI_SM501(obj) OBJECT_CHECK(SM501PCIState, (obj), TYPE_PCI_SM501)
+
+typedef struct {
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+    SM501State state;
+    uint32_t vram_size;
+} SM501PCIState;
+
+static void sm501_realize_pci(PCIDevice *dev, Error **errp)
+{
+    SM501PCIState *s = PCI_SM501(dev);
+
+    sm501_init(&s->state, DEVICE(dev), s->vram_size);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &s->state.local_mem_region);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &s->state.mmio_region);
+}
+
+static Property sm501_pci_properties[] = {
+    DEFINE_PROP_UINT32("vram-size", SM501PCIState, vram_size,
+                       64 * 1024 * 1024),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sm501_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->realize = sm501_realize_pci;
+    k->vendor_id = 0x126f;
+    k->device_id = 0x0501;
+    k->class_id = PCI_CLASS_DISPLAY_OTHER;
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->desc = "SM501 Display Controller";
+    dc->props = sm501_pci_properties;
+    dc->hotpluggable = false;
+}
+
+static const TypeInfo sm501_pci_info = {
+    .name          = TYPE_PCI_SM501,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(SM501PCIState),
+    .class_init    = sm501_pci_class_init,
+};
+
 static void sm501_register_types(void)
 {
     type_register_static(&sm501_sysbus_info);
+    type_register_static(&sm501_pci_info);
 }
 
 type_init(sm501_register_types)
diff --git a/hw/display/sm501_template.h b/hw/display/sm501_template.h
index 16e500b..832ee61 100644
--- a/hw/display/sm501_template.h
+++ b/hw/display/sm501_template.h
@@ -103,13 +103,13 @@  static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
                  uint8_t *palette, int c_y, uint8_t *d, int width)
 {
     int x, i;
-    uint8_t bitset = 0;
+    uint8_t *pixval, bitset = 0;
 
     /* get hardware cursor pattern */
     uint32_t cursor_addr = get_hwc_address(s, crt);
     assert(0 <= c_y && c_y < SM501_HWC_HEIGHT);
     cursor_addr += SM501_HWC_WIDTH * c_y / 4;  /* 4 pixels per byte */
-    cursor_addr += s->base;
+    pixval = s->local_mem + cursor_addr;
 
     /* get cursor position */
     x = get_hwc_x(s, crt);
@@ -120,8 +120,8 @@  static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State *s, int crt,
 
         /* get pixel value */
         if (i % 4 == 0) {
-            bitset = ldub_phys(&address_space_memory, cursor_addr);
-            cursor_addr++;
+            bitset = ldub_p(pixval);
+            pixval++;
         }
         v = bitset & 3;
         bitset >>= 2;