struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
- PrintDebug(core->vm_info, core, "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);
+ PrintDebug(core->vm_info, core, "vga: memory write: guest_addr=0x%p len=%u write_mode=%d first_byte=0x%x\n",
+ (void*)guest_addr, length, vga->vga_graphics_controller.vga_graphics_mode.write_mode, *(uint8_t*)src);
if (vga->passthrough) {
PrintDebug(core->vm_info, core, "vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
/* Write mode determine by Graphics Mode Register (Index 05h).writemode */
+ // probably could just reduce this to the datapath itself instead
+ // of following the programmer's perspective...
+
switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
case 0: {
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
uint8_t mm = find_map_write(vga,guest_addr+i);
- for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
+ for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
vga_map map = vga->map[mapnum];
uint8_t data = ((uint8_t *)src)[i];
uint8_t latchval = vga->latch[mapnum];
data = (data>>ror) | (data<<(8-ror));
}
+ // Note here that the bitmask is the register AND the data
+ // the data written by the system is used for no other purpose
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
+
uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
+
uint8_t mm = find_map_write(vga,guest_addr+i);
- for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
+ for (mapnum=0;mapnum<4;mapnum++, sr>>=1, mm>>=1) {
vga_map map = vga->map[mapnum];
uint8_t latchval = vga->latch[mapnum];
- // expand SR bit
+ // expand SR bit - that's the data we're going to use
data = (sr&0x1) * -1;
// mux between latch and alu output
mapnum = find_map_read(vga,guest_addr+i);
+ // the data returned
((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
- vga->latch[mapnum] = *(vga->map[mapnum]+offset);
-
+ // need to load all latches even though we are
+ // returning data from only the selected map
+ for (mapnum=0;mapnum<4;mapnum++) {
+ vga->latch[mapnum] = *(vga->map[mapnum]+offset);
+ }
}
-
}
break;
*/
int i;
-
- uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
- uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
-
- uint8_t mapnum;
uint64_t offset;
- uint8_t byte;
- uint8_t bits;
-
+
offset = find_offset_read(vga,guest_addr);
#if DEBUG_DEEP_MEM
- PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
+ PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx\n",offset);
#endif
-
- for (i=0;i<length;i++,offset++) {
- vga_map map;
- byte=0;
- for (mapnum=0;mapnum<4;mapnum++) {
- map = vga->map[mapnum];
- if ( (dc>>mapnum)&0x1 ) { // don't care
- bits=0;
- } else {
- // lower 4 bits
- bits = (map[offset]&0xf) == cc;
- bits <<= 1;
- // upper 4 bits
- bits |= (((map[offset]>>4))&0xf) == cc;
- }
- // not clear whether it is 0..k or k..0
- byte<<=2;
- byte|=bits;
+ for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
+ uint8_t mapnum;
+ uint8_t mapcalc=0xff;
+
+ uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
+ uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
+
+ for (mapnum=0;mapnum<4;mapnum++, cc>>=1, dc>>=1) {
+ if (dc&0x1) { // dc is active low; 1=we do care
+ mapcalc &= (cc * -1) & *(vga->map[mapnum]+offset);
}
- }
-
- // load the latches with the last item read
- for (mapnum=0;mapnum<4;mapnum++) {
- vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
+ // do latch load
+ vga->latch[mapnum] = *(vga->map[mapnum]+offset);
+ }
+ // write back the comparison result (for 8 pixels)
+ ((uint8_t *)dst)[i]=mapcalc;
}
}
+
break;
// there is no default
}
*((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
+ // Pretend that horizontal and vertical blanking
+ // is occurring
+ if (!vga->vga_misc.vga_input_stat1.disp_en) {
+
+ // if not blanking, start horizontal blanking
+ vga->vga_misc.vga_input_stat1.disp_en = 1;
+ vga->vga_misc.vga_input_stat1.vert_retrace = 0;
+
+ } else {
+
+ if (!vga->vga_misc.vga_input_stat1.vert_retrace) {
+ // if not vertical blanking, then now vertical blanking
+ vga->vga_misc.vga_input_stat1.disp_en = 1;
+ vga->vga_misc.vga_input_stat1.vert_retrace = 1;
+ } else {
+ // if vertical blanking, now not blanking
+ vga->vga_misc.vga_input_stat1.disp_en = 0;
+ vga->vga_misc.vga_input_stat1.vert_retrace = 0;
+ }
+
+ }
+
// Stunningly, reading stat1 is also a way to reset
// the state of attribute controller address/data flipflop
// That is some mighty fine crack the designers were smoking.
PASSTHROUGH_IO_OUT(vga,port,src,len);
if (index>=VGA_CRT_CONTROLLER_NUM) {
- PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
+ PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
} else {
- vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
+ vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
+ if (index == 17) {
+ if (vga->vga_crt_controller.vga_vertical_retrace_end.enable_vertical_interrupt) {
+ PrintError(core->vm_info, core, "vga: vertical_retrace_interrupt_enabled is unsupported -- no interrupts will occur!\n");
+ }
+ }
}
render(vga);
for (i=0;i<MAP_NUM;i++) {
void *temp;
- temp = (void*)V3_AllocShadowSafePages(vm,MAP_SIZE/4096);
+ temp = (void*)V3_AllocPages(MAP_SIZE/4096);
if (!temp) {
PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
free_vga(vga);