]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/pl110.c
find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[mirror_qemu.git] / hw / pl110.c
index 8a4d5807af0568fa29ce7b6ee471757947d46b4f..3494264563d867fe883fc61f4bd93ba22148503a 100644 (file)
@@ -1,7 +1,7 @@
-/* 
+/*
  * Arm PrimeCell PL110 Color LCD Controller
  *
- * Copyright (c) 2005 CodeSourcery, LLC.
+ * Copyright (c) 2005-2006 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GNU LGPL
@@ -27,7 +27,8 @@ enum pl110_bppmode
 typedef struct {
     uint32_t base;
     DisplayState *ds;
-    void *pic;
+    /* The Versatile/PB uses a slightly modified PL110 controller.  */
+    int versatile;
     uint32_t timing[4];
     uint32_t cr;
     uint32_t upbase;
@@ -40,12 +41,21 @@ typedef struct {
     int invalidate;
     uint32_t pallette[256];
     uint32_t raw_pallette[128];
-    int irq;
+    qemu_irq irq;
 } pl110_state;
 
 static const unsigned char pl110_id[] =
 { 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
 
+/* The Arm documentation (DDI0224C) says the CLDC on the Versatile board
+   has a different ID.  However Linux only looks for the normal ID.  */
+#if 0
+static const unsigned char pl110_versatile_id[] =
+{ 0x93, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+#else
+#define pl110_versatile_id pl110_id
+#endif
+
 static inline uint32_t rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
 {
     return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
@@ -89,7 +99,7 @@ static int pl110_enabled(pl110_state *s)
   return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
 }
 
-void pl110_update_display(void *opaque)
+static void pl110_update_display(void *opaque)
 {
     pl110_state *s = (pl110_state *)opaque;
     drawfn* fntable;
@@ -101,14 +111,16 @@ void pl110_update_display(void *opaque)
     int src_width;
     uint8_t *dest;
     uint8_t *src;
-    int first, last;
+    int first, last = 0;
     int dirty, new_dirty;
     int i;
 
     if (!pl110_enabled(s))
         return;
-    
+   
     switch (s->ds->depth) {
+    case 0:
+        return;
     case 8:
         fntable = pl110_draw_fn_8;
         dest_width = 1;
@@ -130,7 +142,7 @@ void pl110_update_display(void *opaque)
         dest_width = 4;
         break;
     default:
-        fprintf(stderr, "qemu: Bad color depth\n");
+        fprintf(stderr, "pl110: Bad color depth\n");
         exit(1);
     }
     if (s->cr & PL110_CR_BEBO)
@@ -139,7 +151,7 @@ void pl110_update_display(void *opaque)
       fn = fntable[s->bpp + 12];
     else
       fn = fntable[s->bpp];
-    
+   
     src_width = s->cols;
     switch (s->bpp) {
     case BPP_1:
@@ -172,10 +184,11 @@ void pl110_update_display(void *opaque)
     addr = base;
 
     dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
+    new_dirty = dirty;
     for (i = 0; i < s->rows; i++) {
-        new_dirty = 0;
-        if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
+        if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
             uint32_t tmp;
+            new_dirty = 0;
             for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
                 new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
                                                            VGA_DIRTY_FLAG);
@@ -203,7 +216,7 @@ void pl110_update_display(void *opaque)
     dpy_update(s->ds, 0, first, s->cols, last - first + 1);
 }
 
-void pl110_invalidate_display(void * opaque)
+static void pl110_invalidate_display(void * opaque)
 {
     pl110_state *s = (pl110_state *)opaque;
     s->invalidate = 1;
@@ -248,7 +261,7 @@ static void pl110_resize(pl110_state *s, int width, int height)
 {
     if (width != s->cols || height != s->rows) {
         if (pl110_enabled(s)) {
-            dpy_resize(s->ds, s->cols, s->rows);
+            dpy_resize(s->ds, width, height);
         }
     }
     s->cols = width;
@@ -267,7 +280,10 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
 
     offset -= s->base;
     if (offset >= 0xfe0 && offset < 0x1000) {
-        return pl110_id[(offset - 0xfe0) >> 2];
+        if (s->versatile)
+            return pl110_versatile_id[(offset - 0xfe0) >> 2];
+        else
+            return pl110_id[(offset - 0xfe0) >> 2];
     }
     if (offset >= 0x200 && offset < 0x400) {
         return s->raw_pallette[(offset - 0x200) >> 2];
@@ -286,8 +302,12 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
     case 5: /* LCDLPBASE */
         return s->lpbase;
     case 6: /* LCDIMSC */
+       if (s->versatile)
+         return s->cr;
         return s->int_mask;
     case 7: /* LCDControl */
+       if (s->versatile)
+         return s->int_mask;
         return s->cr;
     case 8: /* LCDRIS */
         return s->int_status;
@@ -319,6 +339,7 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
         n = (offset - 0x200) >> 2;
         s->raw_pallette[(offset - 0x200) >> 2] = val;
         pl110_update_pallette(s, n);
+        return;
     }
     switch (offset >> 2) {
     case 0: /* LCDTiming0 */
@@ -344,10 +365,16 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
         s->lpbase = val;
         break;
     case 6: /* LCDIMSC */
+        if (s->versatile)
+            goto control;
+    imsc:
         s->int_mask = val;
         pl110_update(s);
         break;
     case 7: /* LCDControl */
+        if (s->versatile)
+            goto imsc;
+    control:
         s->cr = val;
         s->bpp = (val >> 1) & 7;
         if (pl110_enabled(s)) {
@@ -375,7 +402,8 @@ static CPUWriteMemoryFunc *pl110_writefn[] = {
    pl110_write
 };
 
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq)
+void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq,
+                 int versatile)
 {
     pl110_state *s;
     int iomemtype;
@@ -383,11 +411,13 @@ void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq)
     s = (pl110_state *)qemu_mallocz(sizeof(pl110_state));
     iomemtype = cpu_register_io_memory(0, pl110_readfn,
                                        pl110_writefn, s);
-    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
+    cpu_register_physical_memory(base, 0x00001000, iomemtype);
     s->base = base;
     s->ds = ds;
-    s->pic = pic;
+    s->versatile = versatile;
     s->irq = irq;
+    graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
+                         NULL, s);
     /* ??? Save/restore.  */
     return s;
 }