Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Correct VGA text functionality without passthrough
Peter Dinda [Sat, 28 Apr 2012 00:43:29 +0000 (19:43 -0500)]
Corrected operation of odd/even chaining and chain4 chaining and other cleanup

palacios/src/devices/vga.c
palacios/src/devices/vga_regs.h

index a99faae..a507f48 100644 (file)
@@ -831,7 +831,7 @@ static void render_text(struct vga_internal *vga, void *fb)
     rtw = tw < fw/cw ? tw : fw/cw;
     rth = th < fh/ch ? th : fh/ch;
 
-    
+    PrintDebug("\n");
 
     // Now let's scan by char across the whole thing
     for (y=0;y<th;y++) { 
@@ -842,6 +842,8 @@ static void render_text(struct vga_internal *vga, void *fb)
                ca = *attr;  
                a.val = ca;
 
+               PrintDebug("%c",ct);
+
                // find the character's font bitmap (one byte per row)
                find_text_font_start(vga,(void**)&font,
                                     extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 ); 
@@ -1134,10 +1136,11 @@ static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
 
     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
-       return (guest_addr-mem_start) % size;
+      // NOT odd/even mode
+      return (guest_addr-mem_start) % size;
     } else {
        // odd/even mode
-       return ((guest_addr-mem_start) >> 1 ) % size;
+      return ((guest_addr-mem_start) >> 1 ) % size;
     }
 }
 
@@ -1154,23 +1157,26 @@ static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
     uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
 
     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
-       return mm;
+      // NOT odd/even mode
+      return mm;
     } else {
-       if (guest_addr & 0x1) { 
-           return mm & 0xa;  // 0x1010
-       } else {
-           return mm & 0x5;  // 0x0101
-       }
+      // odd/even mode
+      if (guest_addr & 0x1) { 
+       return mm & 0xa;  // 0x1010
+      } else {
+       return mm & 0x5;  // 0x0101
+      }
     }
 }
 
 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
 {
-    if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
-       return 1;
-    } else {
-       return !(new_guest_addr & 0x1);
-    }
+  if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
+    // NOT odd/even mode
+    return 1;
+  } else {
+    return !(new_guest_addr & 0x1);
+  }
 }
 
 
@@ -1184,7 +1190,8 @@ static int vga_write(struct guest_info * core,
     struct vm_device *dev = (struct vm_device *)priv_data;
     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
 
-    PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
+    PrintDebug("vga: memory write: guest_addr=0x%p len=%u write_mode=%d\n",(void*)guest_addr, length,
+              vga->vga_graphics_controller.vga_graphics_mode.write_mode);
 
     if (vga->passthrough) { 
        PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
@@ -1499,22 +1506,61 @@ static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
     
     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
 
-    if (!vga->vga_sequencer.vga_mem_mode.chain4) { 
-       return (guest_addr-mem_start) % size;
-    } else {
-       // chain4 mode
-       return ((guest_addr - mem_start) >> 2) % size;
+    if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
+      // odd/even mode takes priority
+      return ((guest_addr-mem_start) >> 1 ) % size;
+    } 
+
+    if (vga->vga_sequencer.vga_mem_mode.chain4) {
+      // otherwise chain4 if it's on
+      return ((guest_addr - mem_start) >> 2) % size;
     }
+
+    // and what you would expect if neither are on
+    return (guest_addr-mem_start) % size;
 }
 
-static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
+// Given this address
+// which specific map should we write into?
+// Note that unlike with find_map_write, here we are looking
+// for a single map number, not a bit vector of maps to be selected
+static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
 {
+    uint64_t mem_start, mem_end;
+    
+    mem_start=mem_end=0;
+    
+    get_mem_region(vga, &mem_start, &mem_end);
+    
+    if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
+      // odd-even mode
+      // last bit tells us map 0 or 1
+      return (guest_addr-mem_start) & 0x1; 
+    } 
 
-    if (vga->vga_sequencer.vga_mem_mode.chain4) { 
-       return !(new_guest_addr & 0x3);
-    } else {
-       return 1;
+    if (vga->vga_sequencer.vga_mem_mode.chain4) {
+      // otherwise chain4 if it's on
+      // last two bits
+      return (guest_addr - mem_start) & 0x3;
     }
+
+    // and what you would expect if neither are on
+    // note that it's not the same as a write!
+    return vga->vga_graphics_controller.vga_read_map_select.map_select;
+}
+
+static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
+{
+
+  if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
+    // odd-even mode
+    return !(new_guest_addr & 0x1); 
+  } 
+
+  if (vga->vga_sequencer.vga_mem_mode.chain4) { 
+    return !(new_guest_addr & 0x3);
+  } 
+  return 1;
 }
 
 
@@ -1528,7 +1574,8 @@ static int vga_read(struct guest_info * core,
     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
     
 
-    PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
+    PrintDebug("vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
+              vga->vga_graphics_controller.vga_graphics_mode.read_mode);
 
         
    
@@ -1538,46 +1585,29 @@ static int vga_read(struct guest_info * core,
     switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) { 
        case 0: {
            /*      0 - a byte from ONE of the 4 planes is returned; 
-                   which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
+                   which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
+                   OR by odd/even chaining OR by chain4 chaining
+           */
            uint8_t  mapnum;
            uint64_t offset;
+           uint32_t i;
 
-
-           if (vga->vga_sequencer.vga_mem_mode.chain4) { 
-               uint32_t i;
-               offset = find_offset_read(vga,guest_addr);
-               // address bytes select the map
-               for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) { 
-                   mapnum = (guest_addr+i) % 4;
+           offset = find_offset_read(vga,guest_addr);
+           
 #if DEBUG_DEEP_MEM
-                   PrintDebug("vga: mode 0 read, chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
+           PrintDebug("vga: mode 0 read, offset=0x%llx\n",offset);
 #endif
-                   ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
+           for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) { 
+
+             mapnum = find_map_read(vga,guest_addr+i);
+
+             ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
+             
+             vga->latch[mapnum] = *(vga->map[mapnum]+offset);
 
-                   // presumably all the latches are to be reloaded, not just the selected one?
-                   for (mapnum=0;mapnum<4;mapnum++) { 
-                       vga->latch[mapnum] = *(vga->map[mapnum]+offset);
-                   }
-               }
-           } else {
-               mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
-               offset = find_offset_read(vga,guest_addr);
-               
-               if (offset>=65536) { 
-                   PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
-               }
-               
-#if DEBUG_DEEP_MEM
-               PrintDebug("vga: mode 0 read, not-chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
-#endif
 
-               memcpy(dst,(vga->map[mapnum])+offset,length);
-               
-               // load the latches with the last item read
-               for (mapnum=0;mapnum<4;mapnum++) { 
-                   vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
-               }
            }
+
        
        }
            break;
@@ -2645,9 +2675,10 @@ static int dac_pixel_mask_write(struct guest_info *core,
 
 static int init_vga(struct vga_internal *vga)
 {
-    // TODO: startup spec of register contents, if any
-    PrintError("vga: init_vga is UNIMPLEMTED\n");
-    return 0;
+  // TODO: startup spec of register contents, if any
+  vga->vga_misc.vga_input_stat1.val = 0x1;  // display enable, not in retrace
+
+  return 0;
 }
 
 static int free_vga(struct vga_internal *vga) 
index 08b65f2..fd4a068 100644 (file)
@@ -199,6 +199,7 @@ struct vga_mem_mode_reg {
            uint8_t extended_memory:1; // 1=>256K RAM, 0=>64K
            uint8_t odd_even:1;
                 // 0 => even addresses go to BOTH banks 0 and 2, odd 1 and 3
+               //      or flip between 0/1 for CGA compat
                 // 1 => address bank sequentially, map mask selects bank
            uint8_t chain4:1;  
                 // 0 => map mask register used to select bank
@@ -630,6 +631,8 @@ page 2-88).
            // 0 = read gets bits from selected map
            uint8_t odd_even:1;
            // 1 = odd/even addressing as in CGMA
+           // 0 = NOT odd/even
+           // notice that this is the OPPOSITE of the bit in the sequencer!
            uint8_t shift_reg_mode:1;
            // 1 = shift regs get odd bits from odd maps and even/even
            uint8_t c256:1;                 // 1 = 256 color mode