Improved handling of IO port operations
This commit is contained in:
parent
117f7820fe
commit
5fd2a1bd35
18
src/acpi.js
18
src/acpi.js
|
@ -28,45 +28,45 @@ function ACPI(cpu)
|
|||
var elcr = 0;
|
||||
|
||||
// ACPI, ELCR register
|
||||
io.register_write(0x4d0, function(data)
|
||||
io.register_write(0x4d0, this, function(data)
|
||||
{
|
||||
elcr = elcr & 0xFF00 | data;
|
||||
});
|
||||
io.register_write(0x4d1, function(data)
|
||||
io.register_write(0x4d1, this, function(data)
|
||||
{
|
||||
elcr = elcr & 0xFF | data << 8;
|
||||
});
|
||||
|
||||
io.register_read(0xb3, function()
|
||||
io.register_read(0xb3, this, function()
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
||||
// ACPI, pmtimer
|
||||
io.register_read(0xb008, function()
|
||||
io.register_read(0xb008, this, function()
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
io.register_read(0xb009, function()
|
||||
io.register_read(0xb009, this, function()
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
io.register_read(0xb00a, function()
|
||||
io.register_read(0xb00a, this, function()
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
io.register_read(0xb00b, function()
|
||||
io.register_read(0xb00b, this, function()
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
||||
// ACPI status
|
||||
io.register_read(0xb004, function(data)
|
||||
io.register_read(0xb004, this, function(data)
|
||||
{
|
||||
dbg_log("b004 read");
|
||||
return 1;
|
||||
});
|
||||
io.register_read(0xb005, function(data)
|
||||
io.register_read(0xb005, this, function(data)
|
||||
{
|
||||
dbg_log("b005 read");
|
||||
return 0;
|
||||
|
|
|
@ -662,12 +662,12 @@ v86.prototype.init = function(settings)
|
|||
|
||||
var a20_byte = 0;
|
||||
|
||||
io.register_read(0x92, function()
|
||||
io.register_read(0x92, this, function()
|
||||
{
|
||||
return a20_byte;
|
||||
});
|
||||
|
||||
io.register_write(0x92, function(out_byte)
|
||||
io.register_write(0x92, this, function(out_byte)
|
||||
{
|
||||
a20_byte = out_byte;
|
||||
});
|
||||
|
@ -676,7 +676,7 @@ v86.prototype.init = function(settings)
|
|||
{
|
||||
// Use by linux for port-IO delay
|
||||
// Avoid generating tons of debug messages
|
||||
io.register_write(0x80, function(out_byte)
|
||||
io.register_write(0x80, this, function(out_byte)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
|
12
src/dma.js
12
src/dma.js
|
@ -17,12 +17,12 @@ function DMA(dev)
|
|||
|
||||
this.lsb_msb_flipflop = 0;
|
||||
|
||||
this.io.register_write(0x04, this.port_write.bind(this, 0x04));
|
||||
this.io.register_write(0x05, this.port_write.bind(this, 0x05));
|
||||
this.io.register_write(0x0A, this.portA_write.bind(this));
|
||||
this.io.register_write(0x0B, this.portB_write.bind(this));
|
||||
this.io.register_write(0x0C, this.portC_write.bind(this));
|
||||
this.io.register_write(0x81, this.port81_write.bind(this));
|
||||
this.io.register_write(0x04, this, this.port_write.bind(this, 0x04));
|
||||
this.io.register_write(0x05, this, this.port_write.bind(this, 0x05));
|
||||
this.io.register_write(0x0A, this, this.portA_write);
|
||||
this.io.register_write(0x0B, this, this.portB_write);
|
||||
this.io.register_write(0x0C, this, this.portC_write);
|
||||
this.io.register_write(0x81, this, this.port81_write);
|
||||
|
||||
/** @const */
|
||||
this._state_skip = ["io", "memory"];
|
||||
|
|
|
@ -77,14 +77,14 @@ function FloppyController(cpu, fda_image, fdb_image)
|
|||
this.number_of_heads = number_of_heads;
|
||||
this.number_of_cylinders = number_of_cylinders;
|
||||
|
||||
this.io.register_read(0x3F0, this.port3F0_read, this);
|
||||
this.io.register_read(0x3F2, this.port3F2_read, this);
|
||||
this.io.register_read(0x3F4, this.port3F4_read, this);
|
||||
this.io.register_read(0x3F5, this.port3F5_read, this);
|
||||
this.io.register_read(0x3F7, this.port3F7_read, this);
|
||||
this.io.register_read(0x3F0, this, this.port3F0_read);
|
||||
this.io.register_read(0x3F2, this, this.port3F2_read);
|
||||
this.io.register_read(0x3F4, this, this.port3F4_read);
|
||||
this.io.register_read(0x3F5, this, this.port3F5_read);
|
||||
this.io.register_read(0x3F7, this, this.port3F7_read);
|
||||
|
||||
this.io.register_write(0x3F2, this.port3F2_write, this);
|
||||
this.io.register_write(0x3F5, this.port3F5_write, this);
|
||||
this.io.register_write(0x3F2, this, this.port3F2_write);
|
||||
this.io.register_write(0x3F5, this, this.port3F5_write);
|
||||
}
|
||||
|
||||
FloppyController.prototype.port3F0_read = function()
|
||||
|
|
248
src/ide.js
248
src/ide.js
|
@ -137,11 +137,11 @@ function IDEDevice(cpu, buffer, is_cd, nr)
|
|||
cpu.devices.pci.register_device(this);
|
||||
|
||||
// status
|
||||
cpu.io.register_read(this.ata_port | 7, this.read_status, this);
|
||||
cpu.io.register_read(this.ata_port_high | 2, this.read_status, this);
|
||||
cpu.io.register_read(this.ata_port | 7, this, this.read_status);
|
||||
cpu.io.register_read(this.ata_port_high | 2, this, this.read_status);
|
||||
|
||||
cpu.io.register_write(this.ata_port | 7, this.write_control, this);
|
||||
cpu.io.register_write(this.ata_port_high | 2, this.write_control, this);
|
||||
cpu.io.register_write(this.ata_port | 7, this, this.write_control);
|
||||
cpu.io.register_write(this.ata_port_high | 2, this, this.write_control);
|
||||
|
||||
/** @type {number} */
|
||||
this.device_control = 2;
|
||||
|
@ -191,44 +191,44 @@ function IDEDevice(cpu, buffer, is_cd, nr)
|
|||
/** @type {number} */
|
||||
this.dma_status = 0;
|
||||
|
||||
cpu.io.register_read(this.ata_port | 0, this.read_data_port, this);
|
||||
cpu.io.register_read(this.ata_port | 1, this.read_data_port, this);
|
||||
cpu.io.register_read(this.ata_port | 2, this.read_data_port, this);
|
||||
cpu.io.register_read(this.ata_port | 3, this.read_data_port, this);
|
||||
cpu.io.register_read(this.ata_port | 0, this, this.read_data_port8, this.read_data_port16, this.read_data_port32);
|
||||
cpu.io.register_read(this.ata_port | 1, this, this.read_lba_port);
|
||||
cpu.io.register_read(this.ata_port | 2, this, this.read_bytecount_port);
|
||||
cpu.io.register_read(this.ata_port | 3, this, this.read_sector_port);
|
||||
|
||||
cpu.io.register_read(this.ata_port | 4, function()
|
||||
cpu.io.register_read(this.ata_port | 4, this, function()
|
||||
{
|
||||
dbg_log("Read 1F4: " + h(this.cylinder_low & 0xFF), LOG_DISK);
|
||||
return this.cylinder_low & 0xFF;
|
||||
}, this);
|
||||
cpu.io.register_read(this.ata_port | 5, function(port)
|
||||
});
|
||||
cpu.io.register_read(this.ata_port | 5, this, function(port)
|
||||
{
|
||||
dbg_log("Read 1F5: " + h(this.cylinder_high & 0xFF), LOG_DISK);
|
||||
return this.cylinder_high & 0xFF;
|
||||
}, this);
|
||||
cpu.io.register_read(this.ata_port | 6, function()
|
||||
});
|
||||
cpu.io.register_read(this.ata_port | 6, this, function()
|
||||
{
|
||||
dbg_log("Read 1F6", LOG_DISK);
|
||||
return this.drive_head;
|
||||
}, this);
|
||||
});
|
||||
|
||||
|
||||
cpu.io.register_write(this.ata_port | 0, this.write_data_port, this);
|
||||
cpu.io.register_write(this.ata_port | 1, this.write_data_port, this);
|
||||
cpu.io.register_write(this.ata_port | 2, this.write_data_port, this);
|
||||
cpu.io.register_write(this.ata_port | 3, this.write_data_port, this);
|
||||
cpu.io.register_write(this.ata_port | 0, this, this.write_data_port8, this.write_data_port16, this.write_data_port32);
|
||||
cpu.io.register_write(this.ata_port | 1, this, this.write_lba_port);
|
||||
cpu.io.register_write(this.ata_port | 2, this, this.write_bytecount_port);
|
||||
cpu.io.register_write(this.ata_port | 3, this, this.write_sector_port);
|
||||
|
||||
cpu.io.register_write(this.ata_port | 4, function(data)
|
||||
cpu.io.register_write(this.ata_port | 4, this, function(data)
|
||||
{
|
||||
dbg_log("1F4/sector low: " + h(data), LOG_DISK);
|
||||
this.cylinder_low = (this.cylinder_low << 8 | data) & 0xFFFF;
|
||||
}, this);
|
||||
cpu.io.register_write(this.ata_port | 5, function(data)
|
||||
});
|
||||
cpu.io.register_write(this.ata_port | 5, this, function(data)
|
||||
{
|
||||
dbg_log("1F5/sector high: " + h(data), LOG_DISK);
|
||||
this.cylinder_high = (this.cylinder_high << 8 | data) & 0xFFFF;
|
||||
}, this);
|
||||
cpu.io.register_write(this.ata_port | 6, function(data)
|
||||
});
|
||||
cpu.io.register_write(this.ata_port | 6, this, function(data)
|
||||
{
|
||||
var slave = data & 0x10,
|
||||
mode = data & 0xE0,
|
||||
|
@ -253,24 +253,18 @@ function IDEDevice(cpu, buffer, is_cd, nr)
|
|||
this.is_lba = data >> 6 & 1;
|
||||
this.head = data & 0xF;
|
||||
this.last_drive = data;
|
||||
}, this);
|
||||
});
|
||||
|
||||
cpu.io.register_write(this.ata_port | 7, this.ata_command, this);
|
||||
cpu.io.register_write(this.ata_port | 7, this, this.ata_command);
|
||||
|
||||
cpu.io.register_read(this.master_port | 4, this.dma_read_addr0, this);
|
||||
cpu.io.register_read(this.master_port | 5, this.dma_read_addr1, this);
|
||||
cpu.io.register_read(this.master_port | 6, this.dma_read_addr2, this);
|
||||
cpu.io.register_read(this.master_port | 7, this.dma_read_addr3, this);
|
||||
cpu.io.register_read(this.master_port | 4, this, undefined, undefined, this.dma_read_addr);
|
||||
cpu.io.register_write(this.master_port | 4, this, undefined, undefined, this.dma_set_addr);
|
||||
|
||||
cpu.io.register_write(this.master_port | 4, this.dma_set_addr0, this);
|
||||
cpu.io.register_write(this.master_port | 5, this.dma_set_addr1, this);
|
||||
cpu.io.register_write(this.master_port | 6, this.dma_set_addr2, this);
|
||||
cpu.io.register_write(this.master_port | 7, this.dma_set_addr3, this);
|
||||
cpu.io.register_read(this.master_port, this, this.dma_read_command8, undefined, this.dma_read_command);
|
||||
cpu.io.register_write(this.master_port, this, undefined, undefined, this.dma_write_command);
|
||||
|
||||
cpu.io.register_read(this.master_port | 2, this.dma_read_status, this);
|
||||
cpu.io.register_write(this.master_port | 2, this.dma_write_status, this);
|
||||
cpu.io.register_read(this.master_port, this.dma_read_command, this);
|
||||
cpu.io.register_write(this.master_port, this.dma_write_command, this);
|
||||
cpu.io.register_read(this.master_port | 2, this, this.dma_read_status, undefined, undefined);
|
||||
cpu.io.register_write(this.master_port | 2, this, this.dma_write_status, undefined);
|
||||
|
||||
/** @const */
|
||||
this._state_skip = [
|
||||
|
@ -821,27 +815,38 @@ IDEDevice.prototype.atapi_read_dma = function(cmd)
|
|||
}
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_data_port = function(port_addr)
|
||||
IDEDevice.prototype.read_data_port8 = function()
|
||||
{
|
||||
if(port_addr === this.ata_port)
|
||||
{
|
||||
return this.read_data();
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 1))
|
||||
{
|
||||
dbg_log("Read lba_count: " + h(this.lba_count & 0xFF), LOG_DISK);
|
||||
return this.lba_count & 0xFF;
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 2))
|
||||
{
|
||||
dbg_log("Read bytecount: " + h(this.bytecount & 0xFF), LOG_DISK);
|
||||
return this.bytecount & 0xFF;
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 3))
|
||||
{
|
||||
dbg_log("Read sector: " + h(this.sector & 0xFF), LOG_DISK);
|
||||
return this.sector & 0xFF;
|
||||
}
|
||||
return this.read_data();
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_data_port16 = function()
|
||||
{
|
||||
return this.read_data() | this.read_data() << 8;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_data_port32 = function()
|
||||
{
|
||||
return this.read_data() | this.read_data() << 8 |
|
||||
this.read_data() << 16 | this.read_data() << 24;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_lba_port = function()
|
||||
{
|
||||
dbg_log("Read lba_count: " + h(this.lba_count & 0xFF), LOG_DISK);
|
||||
return this.lba_count & 0xFF;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_bytecount_port = function()
|
||||
{
|
||||
dbg_log("Read bytecount: " + h(this.bytecount & 0xFF), LOG_DISK);
|
||||
return this.bytecount & 0xFF;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_sector_port = function()
|
||||
{
|
||||
dbg_log("Read sector: " + h(this.sector & 0xFF), LOG_DISK);
|
||||
return this.sector & 0xFF;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.read_data = function()
|
||||
|
@ -910,54 +915,67 @@ IDEDevice.prototype.read_data = function()
|
|||
}
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_data_port = function(data, port_addr)
|
||||
IDEDevice.prototype.write_data_port8 = function(data)
|
||||
{
|
||||
if(port_addr === this.ata_port)
|
||||
if(this.data_port_current >= this.data_port_count)
|
||||
{
|
||||
if(this.data_port_current >= this.data_port_count)
|
||||
dbg_log("Redundant write to data port: " + h(data) + " count=" + h(this.data_port_count) +
|
||||
" cur=" + h(this.data_port_current), LOG_DISK);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((this.data_port_current + 1 & 255) === 0 || this.data_port_count < 20)
|
||||
{
|
||||
dbg_log("Redundant write to data port: " + h(data) + " count=" + h(this.data_port_count) +
|
||||
dbg_log("Data port: " + h(data) + " count=" + h(this.data_port_count) +
|
||||
" cur=" + h(this.data_port_current), LOG_DISK);
|
||||
}
|
||||
else
|
||||
|
||||
this.data_port_buffer[this.data_port_current++] = data;
|
||||
|
||||
if((this.data_port_current % (this.sectors_per_drq * 512)) === 0)
|
||||
{
|
||||
if((this.data_port_current + 1 & 255) === 0 || this.data_port_count < 20)
|
||||
{
|
||||
dbg_log("Data port: " + h(data) + " count=" + h(this.data_port_count) +
|
||||
" cur=" + h(this.data_port_current), LOG_DISK);
|
||||
}
|
||||
|
||||
this.data_port_buffer[this.data_port_current++] = data;
|
||||
|
||||
if((this.data_port_current % (this.sectors_per_drq * 512)) === 0)
|
||||
{
|
||||
dbg_log("ATA IRQ", LOG_DISK);
|
||||
this.push_irq();
|
||||
}
|
||||
|
||||
if(this.data_port_current === this.data_port_count)
|
||||
{
|
||||
dbg_assert(typeof this[this.data_port_callback] === "function");
|
||||
this[this.data_port_callback]();
|
||||
}
|
||||
dbg_log("ATA IRQ", LOG_DISK);
|
||||
this.push_irq();
|
||||
}
|
||||
|
||||
if(this.data_port_current === this.data_port_count)
|
||||
{
|
||||
dbg_assert(typeof this[this.data_port_callback] === "function");
|
||||
this[this.data_port_callback]();
|
||||
}
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 1))
|
||||
{
|
||||
dbg_log("1F1/lba_count: " + h(data), LOG_DISK);
|
||||
this.lba_count = (this.lba_count << 8 | data) & 0xFFFF;
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 2))
|
||||
{
|
||||
dbg_log("1F2/bytecount: " + h(data), LOG_DISK);
|
||||
this.bytecount = (this.bytecount << 8 | data) & 0xFFFF;
|
||||
}
|
||||
else if(port_addr === (this.ata_port | 3))
|
||||
{
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_data_port16 = function(data)
|
||||
{
|
||||
this.write_data_port8(data & 0xFF);
|
||||
this.write_data_port8(data >> 8 & 0xFF);
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_data_port32 = function(data)
|
||||
{
|
||||
this.write_data_port8(data & 0xFF);
|
||||
this.write_data_port8(data >> 8 & 0xFF);
|
||||
this.write_data_port8(data >> 16 & 0xFF);
|
||||
this.write_data_port8(data >> 24 & 0xFF);
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_lba_port = function(data)
|
||||
{
|
||||
dbg_log("1F1/lba_count: " + h(data), LOG_DISK);
|
||||
this.lba_count = (this.lba_count << 8 | data) & 0xFFFF;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_bytecount_port = function(data)
|
||||
{
|
||||
dbg_log("1F2/bytecount: " + h(data), LOG_DISK);
|
||||
this.bytecount = (this.bytecount << 8 | data) & 0xFFFF;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.write_sector_port = function(data)
|
||||
{
|
||||
dbg_log("1F3/sector: " + h(data), LOG_DISK);
|
||||
this.sector = (this.sector << 8 | data) & 0xFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
IDEDevice.prototype.ata_read_sectors = function(cmd)
|
||||
|
@ -1343,39 +1361,14 @@ IDEDevice.prototype.create_identify_packet = function()
|
|||
}
|
||||
};
|
||||
|
||||
IDEDevice.prototype.dma_read_addr0 = function()
|
||||
IDEDevice.prototype.dma_read_addr = function()
|
||||
{
|
||||
return this.prdt_addr & 0xFF;
|
||||
};
|
||||
IDEDevice.prototype.dma_read_addr1 = function()
|
||||
{
|
||||
return this.prdt_addr >> 8 & 0xFF;
|
||||
};
|
||||
IDEDevice.prototype.dma_read_addr2 = function()
|
||||
{
|
||||
return this.prdt_addr >> 16 & 0xFF;
|
||||
};
|
||||
IDEDevice.prototype.dma_read_addr3 = function()
|
||||
{
|
||||
return this.prdt_addr >> 24 & 0xFF;
|
||||
return this.prdt_addr;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.dma_set_addr0 = function(data)
|
||||
IDEDevice.prototype.dma_set_addr = function(data)
|
||||
{
|
||||
this.prdt_addr = this.prdt_addr & ~0xFF | data;
|
||||
};
|
||||
IDEDevice.prototype.dma_set_addr1 = function(data)
|
||||
{
|
||||
this.prdt_addr = this.prdt_addr & ~0xFF00 | data << 8;
|
||||
};
|
||||
IDEDevice.prototype.dma_set_addr2 = function(data)
|
||||
{
|
||||
this.prdt_addr = this.prdt_addr & ~0xFF0000 | data << 16;
|
||||
};
|
||||
IDEDevice.prototype.dma_set_addr3 = function(data)
|
||||
{
|
||||
this.prdt_addr = this.prdt_addr & 0xFFFFFF | data << 24;
|
||||
dbg_log("Set PRDT addr: " + h(this.prdt_addr), LOG_DISK);
|
||||
this.prdt_addr = data;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.dma_read_status = function()
|
||||
|
@ -1394,9 +1387,16 @@ IDEDevice.prototype.dma_write_status = function(value)
|
|||
IDEDevice.prototype.dma_read_command = function()
|
||||
{
|
||||
dbg_log("DMA read command", LOG_DISK);
|
||||
return 1 | this.dma_read_status() << 16;
|
||||
};
|
||||
|
||||
IDEDevice.prototype.dma_read_command8 = function()
|
||||
{
|
||||
dbg_log("DMA read command8", LOG_DISK);
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
IDEDevice.prototype.dma_write_command = function(value)
|
||||
{
|
||||
dbg_log("DMA write command: " + h(value), LOG_DISK);
|
||||
|
@ -1405,5 +1405,7 @@ IDEDevice.prototype.dma_write_command = function(value)
|
|||
{
|
||||
this.push_irq();
|
||||
}
|
||||
|
||||
this.dma_write_status(value >> 16 & 0xFF);
|
||||
};
|
||||
|
||||
|
|
301
src/io.js
301
src/io.js
|
@ -10,6 +10,8 @@ function IO(memory)
|
|||
{
|
||||
var memory_size = memory.size;
|
||||
|
||||
this._state_skip = ["devices", "ports",];
|
||||
|
||||
function get_port_description(addr)
|
||||
{
|
||||
// via seabios ioport.h
|
||||
|
@ -79,90 +81,188 @@ function IO(memory)
|
|||
}
|
||||
}
|
||||
|
||||
function empty_port_read_debug(port_addr)
|
||||
function empty_port_read8()
|
||||
{
|
||||
dbg_log(
|
||||
"read port #" + h(port_addr, 3) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
function empty_port_write_debug(out_byte, port_addr)
|
||||
function empty_port_read16()
|
||||
{
|
||||
dbg_log(
|
||||
"write port #" + h(port_addr, 3) + " <- " + h(out_byte, 2) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
function empty_port_read()
|
||||
function empty_port_read32()
|
||||
{
|
||||
return 0xFF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
function empty_port_write(x)
|
||||
{
|
||||
}
|
||||
|
||||
// Why 0x10003 if there are only 0x10000 ports:
|
||||
// Reading/Writing from port 0xFFFF could make the number
|
||||
// go outside of the valid range and cause an exception otherwise
|
||||
/** @const */
|
||||
var NUM_PORTS = 0x10003;
|
||||
this.ports = [];
|
||||
this.devices = Array(0x10000);
|
||||
|
||||
var read_callbacks = Array(NUM_PORTS),
|
||||
write_callbacks = Array(NUM_PORTS);
|
||||
|
||||
for(var i = 0; i < NUM_PORTS; i++)
|
||||
for(var i = 0; i < 0x10000; i++)
|
||||
{
|
||||
// avoid sparse arrays
|
||||
this.ports[i] = {
|
||||
read8: empty_port_read8,
|
||||
read16: empty_port_read16,
|
||||
read32: empty_port_read32,
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
read_callbacks[i] = empty_port_read_debug;
|
||||
write_callbacks[i] = empty_port_write_debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
read_callbacks[i] = empty_port_read;
|
||||
write_callbacks[i] = empty_port_write;
|
||||
}
|
||||
write8: empty_port_write,
|
||||
write16: empty_port_write,
|
||||
write32: empty_port_write,
|
||||
|
||||
device: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} port_addr
|
||||
* @param {function():number} callback
|
||||
* @param {Object=} device
|
||||
* @param {Object} device
|
||||
* @param {function():number} r8
|
||||
* @param {function():number=} r16
|
||||
* @param {function():number=} r32
|
||||
*/
|
||||
this.register_read = function(port_addr, callback, device)
|
||||
this.register_read = function(port_addr, device, r8, r16, r32)
|
||||
{
|
||||
dbg_assert(typeof port_addr === "number");
|
||||
dbg_assert(typeof device === "object");
|
||||
dbg_assert(!r8 || typeof r8 === "function");
|
||||
dbg_assert(!r16 || typeof r16 === "function");
|
||||
dbg_assert(!r32 || typeof r32 === "function");
|
||||
dbg_assert(r8 || r16 || r32);
|
||||
|
||||
if(device !== undefined)
|
||||
if(DEBUG)
|
||||
{
|
||||
callback = callback.bind(device);
|
||||
var fail = function(n) {
|
||||
dbg_assert(false, "Overlapped read" + n + " " + h(port_addr, 4));
|
||||
return -1;
|
||||
};
|
||||
if(!r8) r8 = fail.bind(this, 8);
|
||||
if(!r16) r16 = fail.bind(this, 16);
|
||||
if(!r32) r32 = fail.bind(this, 32);
|
||||
}
|
||||
|
||||
read_callbacks[port_addr] = callback;
|
||||
this.ports[port_addr].read8 = r8;
|
||||
this.ports[port_addr].read16 = r16;
|
||||
this.ports[port_addr].read32 = r32;
|
||||
this.ports[port_addr].device = device;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} port_addr
|
||||
* @param {function(number)} callback
|
||||
* @param {Object=} device
|
||||
* @param {Object} device
|
||||
* @param {function(number)} w8
|
||||
* @param {function(number)=} w16
|
||||
* @param {function(number)=} w32
|
||||
*/
|
||||
this.register_write = function(port_addr, callback, device)
|
||||
this.register_write = function(port_addr, device, w8, w16, w32)
|
||||
{
|
||||
dbg_assert(typeof port_addr === "number");
|
||||
dbg_assert(typeof device === "object");
|
||||
dbg_assert(!w8 || typeof w8 === "function");
|
||||
dbg_assert(!w16 || typeof w16 === "function");
|
||||
dbg_assert(!w32 || typeof w32 === "function");
|
||||
dbg_assert(w8 || w16 || w32);
|
||||
|
||||
if(device !== undefined)
|
||||
if(DEBUG)
|
||||
{
|
||||
callback = callback.bind(device);
|
||||
var fail = function(n) {
|
||||
dbg_assert(false, "Overlapped write" + n + " " + h(port_addr));
|
||||
};
|
||||
if(!w8) w8 = fail.bind(this, 8);
|
||||
if(!w16) w16 = fail.bind(this, 16);
|
||||
if(!w32) w32 = fail.bind(this, 32);
|
||||
}
|
||||
|
||||
write_callbacks[port_addr] = callback;
|
||||
this.ports[port_addr].write8 = w8;
|
||||
this.ports[port_addr].write16 = w16;
|
||||
this.ports[port_addr].write32 = w32;
|
||||
this.ports[port_addr].device = device;
|
||||
};
|
||||
|
||||
/*
|
||||
* > Any two consecutive 8-bit ports can be treated as a 16-bit port;
|
||||
* > and four consecutive 8-bit ports can be treated as a 32-bit port
|
||||
* > http://css.csail.mit.edu/6.858/2012/readings/i386/s08_01.htm
|
||||
*
|
||||
* This info is not correct for all ports, but handled by the following functions
|
||||
*
|
||||
* Register the write of 2 or 4 consecutive 8-bit ports, 1 or 2 16-bit
|
||||
* ports and 0 or 1 32-bit ports
|
||||
*/
|
||||
this.register_read_consecutive = function(port_addr, device, r8_1, r8_2, r8_3, r8_4)
|
||||
{
|
||||
dbg_assert(arguments.length === 4 || arguments.length === 6);
|
||||
|
||||
function r16_1()
|
||||
{
|
||||
return r8_1.call(this) |
|
||||
r8_2.call(this) << 8;
|
||||
}
|
||||
function r16_2()
|
||||
{
|
||||
return r8_3.call(this) |
|
||||
r8_4.call(this) << 8;
|
||||
}
|
||||
function r32()
|
||||
{
|
||||
return r8_1.call(this) |
|
||||
r8_2.call(this) << 8 |
|
||||
r8_3.call(this) << 16 |
|
||||
r8_4.call(this) << 24;
|
||||
}
|
||||
|
||||
if(r8_3 && r8_4)
|
||||
{
|
||||
this.register_read(port_addr, device, r8_1, r16_1, r32);
|
||||
this.register_read(port_addr + 1, device, r8_2);
|
||||
this.register_read(port_addr + 2, device, r8_3, r16_2);
|
||||
this.register_read(port_addr + 3, device, r8_4);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.register_read(port_addr, device, r8_1, r16_1);
|
||||
this.register_read(port_addr + 1, device, r8_2);
|
||||
}
|
||||
};
|
||||
|
||||
this.register_write_consecutive = function(port_addr, device, w8_1, w8_2, w8_3, w8_4)
|
||||
{
|
||||
dbg_assert(arguments.length === 4 || arguments.length === 6);
|
||||
|
||||
function w16_1(data)
|
||||
{
|
||||
w8_1.call(this, data & 0xFF);
|
||||
w8_2.call(this, data >> 8 & 0xFF);
|
||||
}
|
||||
function w16_2(data)
|
||||
{
|
||||
w8_3.call(this, data & 0xFF);
|
||||
w8_4.call(this, data >> 8 & 0xFF);
|
||||
}
|
||||
function w32(data)
|
||||
{
|
||||
w8_1.call(this, data & 0xFF);
|
||||
w8_2.call(this, data >> 8 & 0xFF);
|
||||
w8_3.call(this, data >> 16 & 0xFF);
|
||||
w8_4.call(this, data >>> 24);
|
||||
}
|
||||
|
||||
if(w8_3 && w8_4)
|
||||
{
|
||||
this.register_write(port_addr, device, w8_1, w16_1, w32);
|
||||
this.register_write(port_addr + 1, device, w8_2);
|
||||
this.register_write(port_addr + 2, device, w8_3, w16_2);
|
||||
this.register_write(port_addr + 3, device, w8_4);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.register_write(port_addr, device, w8_1, w16_1);
|
||||
this.register_write(port_addr + 1, device, w8_2);
|
||||
}
|
||||
};
|
||||
|
||||
this.mmap_read32_shim = function(addr)
|
||||
|
@ -201,10 +301,10 @@ function IO(memory)
|
|||
dbg_assert(size && (size & MMAP_BLOCK_SIZE - 1) === 0);
|
||||
|
||||
if(!read_func32)
|
||||
read_func32 = this.mmap_read32_shim.bind(this);
|
||||
read_func32 = this.mmap_read32_shim;
|
||||
|
||||
if(!write_func32)
|
||||
write_func32 = this.mmap_write32_shim.bind(this);
|
||||
write_func32 = this.mmap_write32_shim;
|
||||
|
||||
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
|
||||
|
||||
|
@ -237,8 +337,15 @@ function IO(memory)
|
|||
function(addr, value) {
|
||||
// write outside of the memory size
|
||||
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value, 2), LOG_IO);
|
||||
});
|
||||
|
||||
},
|
||||
function(addr) {
|
||||
dbg_log("Read from unmapped memory space, addr=" + h(addr >>> 0, 8), LOG_IO);
|
||||
return -1;
|
||||
},
|
||||
function(addr, value) {
|
||||
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value >>> 0, 8), LOG_IO);
|
||||
}
|
||||
);
|
||||
|
||||
this.in_mmap_range = function(start, count)
|
||||
{
|
||||
|
@ -268,58 +375,88 @@ function IO(memory)
|
|||
return false;
|
||||
};
|
||||
|
||||
// any two consecutive 8-bit ports can be treated as a 16-bit port;
|
||||
// and four consecutive 8-bit ports can be treated as a 32-bit port
|
||||
//
|
||||
// http://css.csail.mit.edu/6.858/2012/readings/i386/s08_01.htm
|
||||
//
|
||||
// This info seems to be incorrect, at least some multibyte ports are next
|
||||
// to each other, such as 1CE and 1CF (VBE dispi) or the 170 (ATA data port).
|
||||
//
|
||||
// As a workaround, we pass the original port to the callback as the last argument.
|
||||
|
||||
|
||||
this.port_write8 = function(port_addr, out_byte)
|
||||
this.port_write8 = function(port_addr, data)
|
||||
{
|
||||
write_callbacks[port_addr](out_byte, port_addr);
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.write8 === empty_port_write)
|
||||
{
|
||||
dbg_log(
|
||||
"write8 port #" + h(port_addr, 4) + " <- " + h(data, 2) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.write8.call(entry.device, data);
|
||||
};
|
||||
|
||||
this.port_write16 = function(port_addr, out_byte)
|
||||
this.port_write16 = function(port_addr, data)
|
||||
{
|
||||
//dbg_log("16 bit write port=" + h(port_addr) + " " + get_port_description(port_addr));
|
||||
write_callbacks[port_addr](out_byte & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 1](out_byte >> 8, port_addr);
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.write16 === empty_port_write)
|
||||
{
|
||||
dbg_log(
|
||||
"write16 port #" + h(port_addr, 4) + " <- " + h(data, 4) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.write16.call(entry.device, data);
|
||||
};
|
||||
|
||||
this.port_write32 = function(port_addr, out_byte)
|
||||
this.port_write32 = function(port_addr, data)
|
||||
{
|
||||
//dbg_log("32 bit write port=" + h(port_addr) + " " + get_port_description(port_addr));
|
||||
write_callbacks[port_addr](out_byte & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 1](out_byte >> 8 & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 2](out_byte >> 16 & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 3](out_byte >>> 24, port_addr);
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.write32 === empty_port_write)
|
||||
{
|
||||
dbg_log(
|
||||
"write32 port #" + h(port_addr, 4) + " <- " + h(data, 8) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.write32.call(entry.device, data);
|
||||
};
|
||||
|
||||
// read byte from port
|
||||
this.port_read8 = function(port_addr)
|
||||
{
|
||||
return read_callbacks[port_addr](port_addr);
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.read8 === empty_port_read8)
|
||||
{
|
||||
dbg_log(
|
||||
"read8 port #" + h(port_addr, 4) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.read8.call(entry.device);
|
||||
};
|
||||
|
||||
this.port_read16 = function(port_addr)
|
||||
{
|
||||
//dbg_log("16 bit read port=" + h(port_addr) + " " + get_port_description(port_addr));
|
||||
return read_callbacks[port_addr](port_addr) |
|
||||
read_callbacks[port_addr + 1](port_addr) << 8;
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.read16 === empty_port_read16)
|
||||
{
|
||||
dbg_log(
|
||||
"read16 port #" + h(port_addr, 4) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.read16.call(entry.device);
|
||||
};
|
||||
|
||||
this.port_read32 = function(port_addr)
|
||||
{
|
||||
//dbg_log("32 bit read port=" + h(port_addr) + " " + get_port_description(port_addr));
|
||||
return read_callbacks[port_addr](port_addr) |
|
||||
read_callbacks[port_addr + 1](port_addr) << 8 |
|
||||
read_callbacks[port_addr + 2](port_addr) << 16 |
|
||||
read_callbacks[port_addr + 3](port_addr) << 24;
|
||||
var entry = this.ports[port_addr];
|
||||
|
||||
if(entry.read32 === empty_port_read32)
|
||||
{
|
||||
dbg_log(
|
||||
"read32 port #" + h(port_addr, 4) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
return entry.read32.call(entry.device);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
116
src/ne2k.js
116
src/ne2k.js
|
@ -106,13 +106,13 @@ function Ne2k(cpu, adapter)
|
|||
|
||||
var io = cpu.io;
|
||||
|
||||
io.register_read(this.port | E8390_CMD, function()
|
||||
io.register_read(this.port | E8390_CMD, this, function()
|
||||
{
|
||||
dbg_log("Read cmd", LOG_NET);
|
||||
return this.cr;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | E8390_CMD, function(data_byte)
|
||||
io.register_write(this.port | E8390_CMD, this, function(data_byte)
|
||||
{
|
||||
this.cr = data_byte | (this.cr & 4);
|
||||
dbg_log("Write command: " + h(data_byte, 2), LOG_NET);
|
||||
|
@ -123,27 +123,27 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
this.remote_buffer = new Uint8Array(this.rcnt);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_COUNTER0, function()
|
||||
io.register_read(this.port | EN0_COUNTER0, this, function()
|
||||
{
|
||||
dbg_log("Read counter0", LOG_NET);
|
||||
return 0;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_COUNTER1, function()
|
||||
io.register_read(this.port | EN0_COUNTER1, this, function()
|
||||
{
|
||||
dbg_log("Read counter1", LOG_NET);
|
||||
return 0;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_COUNTER2, function()
|
||||
io.register_read(this.port | EN0_COUNTER2, this, function()
|
||||
{
|
||||
dbg_log("Read counter2", LOG_NET);
|
||||
return 0;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | NE_RESET, function()
|
||||
io.register_read(this.port | NE_RESET, this, function()
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -156,9 +156,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Read pg1/1f", LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | NE_RESET, function(data_byte)
|
||||
io.register_write(this.port | NE_RESET, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -170,9 +170,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/1f: " + h(data_byte), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_ISR, function()
|
||||
io.register_read(this.port | EN0_ISR, this, function()
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -185,9 +185,9 @@ function Ne2k(cpu, adapter)
|
|||
dbg_log("Read curpg: " + h(this.curpg, 2), LOG_NET);
|
||||
return this.curpg;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_ISR, function(data_byte)
|
||||
io.register_write(this.port | EN0_ISR, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -201,9 +201,9 @@ function Ne2k(cpu, adapter)
|
|||
dbg_log("Write curpg: " + h(data_byte, 2), LOG_NET);
|
||||
this.curpg = data_byte
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_TXCR, function(data_byte)
|
||||
io.register_write(this.port | EN0_TXCR, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -214,9 +214,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x0d " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_DCFG, function(data_byte)
|
||||
io.register_write(this.port | EN0_DCFG, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -227,9 +227,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x0e " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_RCNTLO, function(data_byte)
|
||||
io.register_write(this.port | EN0_RCNTLO, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -241,9 +241,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x0a " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_RCNTHI, function(data_byte)
|
||||
io.register_write(this.port | EN0_RCNTHI, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -255,9 +255,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x0b " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_RSARLO, function(data_byte)
|
||||
io.register_write(this.port | EN0_RSARLO, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -269,9 +269,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x08 " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_RSARHI, function(data_byte)
|
||||
io.register_write(this.port | EN0_RSARHI, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -283,9 +283,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x09 " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_IMR, function(data_byte)
|
||||
io.register_write(this.port | EN0_IMR, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -297,9 +297,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x0f " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_BOUNDARY, function()
|
||||
io.register_read(this.port | EN0_BOUNDARY, this, function()
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -312,9 +312,9 @@ function Ne2k(cpu, adapter)
|
|||
dbg_log("Read pg1/0x03", LOG_NET);
|
||||
return 0;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(this.port | EN0_BOUNDARY, function(data_byte)
|
||||
io.register_write(this.port | EN0_BOUNDARY, this, function(data_byte)
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -326,9 +326,9 @@ function Ne2k(cpu, adapter)
|
|||
{
|
||||
dbg_log("Write pg1/0x03 " + h(data_byte, 2), LOG_NET);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_TSR, function()
|
||||
io.register_read(this.port | EN0_TSR, this, function()
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -340,9 +340,9 @@ function Ne2k(cpu, adapter)
|
|||
dbg_log("Read pg1/0x04", LOG_NET);
|
||||
return 0;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | EN0_RSR, function()
|
||||
io.register_read(this.port | EN0_RSR, this, function()
|
||||
{
|
||||
var pg = this.cr & 0xC0;
|
||||
if(pg === 0)
|
||||
|
@ -354,17 +354,10 @@ function Ne2k(cpu, adapter)
|
|||
dbg_log("Read pg1/0x0c", LOG_NET);
|
||||
return 0;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(this.port | NE_DATAPORT | 0, this.data_port_read, this);
|
||||
io.register_read(this.port | NE_DATAPORT | 1, this.data_port_read, this);
|
||||
io.register_read(this.port | NE_DATAPORT | 2, this.data_port_read, this);
|
||||
io.register_read(this.port | NE_DATAPORT | 3, this.data_port_read, this);
|
||||
|
||||
io.register_write(this.port | NE_DATAPORT | 0, this.data_port_write, this);
|
||||
io.register_write(this.port | NE_DATAPORT | 1, this.data_port_write, this);
|
||||
io.register_write(this.port | NE_DATAPORT | 2, this.data_port_write, this);
|
||||
io.register_write(this.port | NE_DATAPORT | 3, this.data_port_write, this);
|
||||
io.register_read(this.port | NE_DATAPORT | 0, this, this.data_port_read, this.data_port_read16, this.data_port_read32);
|
||||
io.register_write(this.port | NE_DATAPORT | 0, this, this.data_port_write, this.data_port_write16, this.data_port_write32);
|
||||
|
||||
this._state_skip = [
|
||||
"adapter",
|
||||
|
@ -403,6 +396,20 @@ Ne2k.prototype.data_port_write = function(data_byte)
|
|||
}
|
||||
};
|
||||
|
||||
Ne2k.prototype.data_port_write16 = function(data)
|
||||
{
|
||||
this.data_port_write(data);
|
||||
this.data_port_write(data >> 8);
|
||||
};
|
||||
|
||||
Ne2k.prototype.data_port_write32 = function(data)
|
||||
{
|
||||
this.data_port_write(data);
|
||||
this.data_port_write(data >> 8);
|
||||
this.data_port_write(data >> 16);
|
||||
this.data_port_write(data >> 24);
|
||||
};
|
||||
|
||||
Ne2k.prototype.data_port_read = function()
|
||||
{
|
||||
var data = this.receive_buffer[this.rsar++];
|
||||
|
@ -412,6 +419,17 @@ Ne2k.prototype.data_port_read = function()
|
|||
return data;
|
||||
};
|
||||
|
||||
Ne2k.prototype.data_port_read16 = function()
|
||||
{
|
||||
return this.data_port_read() | this.data_port_read() << 8;
|
||||
};
|
||||
|
||||
Ne2k.prototype.data_port_read32 = function()
|
||||
{
|
||||
return this.data_port_read() | this.data_port_read() << 8 |
|
||||
this.data_port_read() << 16 | this.data_port_read() << 24;
|
||||
};
|
||||
|
||||
Ne2k.prototype.receive = function(data)
|
||||
{
|
||||
// called from the adapter when data is received over the network
|
||||
|
|
148
src/pci.js
148
src/pci.js
|
@ -46,80 +46,86 @@ function PCI(cpu)
|
|||
}
|
||||
});*/
|
||||
|
||||
io.register_write(PCI_CONFIG_DATA, function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data0: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(0, out_byte);
|
||||
});
|
||||
io.register_write(PCI_CONFIG_DATA | 1, function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data1: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(1, out_byte);
|
||||
});
|
||||
io.register_write(PCI_CONFIG_DATA | 2, function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data2: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(2, out_byte);
|
||||
});
|
||||
io.register_write(PCI_CONFIG_DATA | 3, function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data3: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
io.register_write_consecutive(PCI_CONFIG_DATA, this,
|
||||
function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data0: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(0, out_byte);
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data1: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(1, out_byte);
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data2: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(2, out_byte);
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
dbg_log("PCI data3: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
|
||||
pci_write_byte(3, out_byte);
|
||||
}
|
||||
);
|
||||
|
||||
pci_write_byte(3, out_byte);
|
||||
});
|
||||
io.register_read_consecutive(PCI_CONFIG_DATA, this,
|
||||
function()
|
||||
{
|
||||
return pci_response[0];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_response[1];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_response[2];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_response[3];
|
||||
}
|
||||
);
|
||||
|
||||
io.register_read(PCI_CONFIG_DATA, function()
|
||||
{
|
||||
return pci_response[0];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_DATA | 1, function()
|
||||
{
|
||||
return pci_response[1];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_DATA | 2, function()
|
||||
{
|
||||
return pci_response[2];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_DATA | 3, function()
|
||||
{
|
||||
return pci_response[3];
|
||||
});
|
||||
io.register_read_consecutive(PCI_CONFIG_ADDRESS, this,
|
||||
function()
|
||||
{
|
||||
return pci_status[0];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_status[1];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_status[2];
|
||||
},
|
||||
function()
|
||||
{
|
||||
return pci_status[3];
|
||||
}
|
||||
);
|
||||
|
||||
io.register_read(PCI_CONFIG_ADDRESS, function()
|
||||
{
|
||||
return pci_status[0];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_ADDRESS | 1, function()
|
||||
{
|
||||
return pci_status[1];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_ADDRESS | 2, function()
|
||||
{
|
||||
return pci_status[2];
|
||||
});
|
||||
io.register_read(PCI_CONFIG_ADDRESS | 3, function()
|
||||
{
|
||||
return pci_status[3];
|
||||
});
|
||||
|
||||
io.register_write(PCI_CONFIG_ADDRESS, function(out_byte)
|
||||
{
|
||||
pci_addr[0] = out_byte;
|
||||
});
|
||||
io.register_write(PCI_CONFIG_ADDRESS | 1, function(out_byte)
|
||||
{
|
||||
pci_addr[1] = out_byte;
|
||||
});
|
||||
io.register_write(PCI_CONFIG_ADDRESS | 2, function(out_byte)
|
||||
{
|
||||
pci_addr[2] = out_byte;
|
||||
});
|
||||
io.register_write(PCI_CONFIG_ADDRESS | 3, function(out_byte)
|
||||
{
|
||||
pci_addr[3] = out_byte;
|
||||
|
||||
pci_query();
|
||||
});
|
||||
io.register_write_consecutive(PCI_CONFIG_ADDRESS, this,
|
||||
function(out_byte)
|
||||
{
|
||||
pci_addr[0] = out_byte;
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
pci_addr[1] = out_byte;
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
pci_addr[2] = out_byte;
|
||||
},
|
||||
function(out_byte)
|
||||
{
|
||||
pci_addr[3] = out_byte;
|
||||
pci_query();
|
||||
}
|
||||
);
|
||||
|
||||
function pci_query()
|
||||
{
|
||||
|
|
12
src/pic.js
12
src/pic.js
|
@ -91,7 +91,7 @@ function PIC(cpu, master)
|
|||
cpu.call_interrupt_vector(this.irq_map | irq_number, false, false);
|
||||
|
||||
return true;
|
||||
}.bind(this);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -135,7 +135,7 @@ function PIC(cpu, master)
|
|||
}
|
||||
|
||||
return true;
|
||||
}.bind(this);
|
||||
};
|
||||
}
|
||||
|
||||
this.dump = function()
|
||||
|
@ -161,11 +161,11 @@ function PIC(cpu, master)
|
|||
io_base = 0xA0;
|
||||
}
|
||||
|
||||
cpu.io.register_write(io_base, port20_write, this);
|
||||
cpu.io.register_read(io_base, port20_read, this);
|
||||
cpu.io.register_write(io_base, this, port20_write);
|
||||
cpu.io.register_read(io_base, this, port20_read);
|
||||
|
||||
cpu.io.register_write(io_base | 1, port21_write, this);
|
||||
cpu.io.register_read(io_base | 1, port21_read, this);
|
||||
cpu.io.register_write(io_base | 1, this, port21_write);
|
||||
cpu.io.register_read(io_base | 1, this, port21_read);
|
||||
|
||||
function port20_write(data_byte)
|
||||
{
|
||||
|
|
18
src/pit.js
18
src/pit.js
|
@ -39,7 +39,7 @@ function PIT(cpu)
|
|||
|
||||
var parity = 0;
|
||||
|
||||
cpu.io.register_read(0x61, function()
|
||||
cpu.io.register_read(0x61, this, function()
|
||||
{
|
||||
// > xxx1 xxxx 0=RAM parity error enable
|
||||
// > PS/2: Read: This bit tiggles for each refresh request.
|
||||
|
@ -48,17 +48,17 @@ function PIT(cpu)
|
|||
|
||||
parity ^= 0x10;
|
||||
return parity | this.counter2_out << 5;
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
cpu.io.register_read(0x40, this.counter_read.bind(this, 0));
|
||||
cpu.io.register_read(0x41, this.counter_read.bind(this, 1));
|
||||
cpu.io.register_read(0x42, this.counter_read.bind(this, 2));
|
||||
cpu.io.register_read(0x40, this, function() { return this.counter_read(0); });
|
||||
cpu.io.register_read(0x41, this, function() { return this.counter_read(1); });
|
||||
cpu.io.register_read(0x42, this, function() { return this.counter_read(2); });
|
||||
|
||||
cpu.io.register_write(0x40, this.counter_write.bind(this, 0));
|
||||
cpu.io.register_write(0x41, this.counter_write.bind(this, 1));
|
||||
cpu.io.register_write(0x42, this.counter_write.bind(this, 2));
|
||||
cpu.io.register_write(0x40, this, function(data) { this.counter_write(0, data); });
|
||||
cpu.io.register_write(0x41, this, function(data) { this.counter_write(1, data); });
|
||||
cpu.io.register_write(0x42, this, function(data) { this.counter_write(2, data); });
|
||||
|
||||
cpu.io.register_write(0x43, this.port43_write.bind(this));
|
||||
cpu.io.register_write(0x43, this, this.port43_write);
|
||||
|
||||
/** @const */
|
||||
this._state_skip = ["pic"];
|
||||
|
|
|
@ -93,11 +93,11 @@ function PS2(cpu, keyboard, mouse)
|
|||
this.read_output_register = false;
|
||||
this.read_command_register = false;
|
||||
|
||||
cpu.io.register_read(0x60, this.port60_read, this);
|
||||
cpu.io.register_read(0x64, this.port64_read, this);
|
||||
cpu.io.register_read(0x60, this, this.port60_read);
|
||||
cpu.io.register_read(0x64, this, this.port64_read);
|
||||
|
||||
cpu.io.register_write(0x60, this.port60_write, this);
|
||||
cpu.io.register_write(0x64, this.port64_write, this);
|
||||
cpu.io.register_write(0x60, this, this.port60_write);
|
||||
cpu.io.register_write(0x64, this, this.port64_write);
|
||||
|
||||
/** @const */
|
||||
this._state_skip = ["pic", "cpu"];
|
||||
|
|
|
@ -31,14 +31,14 @@ function RTC(cpu, diskette_type, boot_order)
|
|||
|
||||
this.nmi_disabled = 0;
|
||||
|
||||
cpu.io.register_write(0x70, function(out_byte)
|
||||
cpu.io.register_write(0x70, this, function(out_byte)
|
||||
{
|
||||
this.cmos_index = out_byte & 0x7F;
|
||||
this.nmi_disabled = out_byte >> 7;
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
cpu.io.register_write(0x71, this.cmos_write.bind(this));
|
||||
cpu.io.register_read(0x71, this.cmos_read.bind(this));
|
||||
cpu.io.register_write(0x71, this, this.cmos_write);
|
||||
cpu.io.register_read(0x71, this, this.cmos_read);
|
||||
|
||||
this._state_skip = ["cpu", "pic"];
|
||||
}
|
||||
|
|
64
src/uart.js
64
src/uart.js
|
@ -62,7 +62,7 @@ function UART(cpu, port, adapter)
|
|||
|
||||
var io = cpu.io;
|
||||
|
||||
io.register_write(port, function(out_byte)
|
||||
io.register_write(port, this, function(out_byte)
|
||||
{
|
||||
if(this.line_control & DLAB)
|
||||
{
|
||||
|
@ -98,9 +98,9 @@ function UART(cpu, port, adapter)
|
|||
{
|
||||
adapter.put_str(String.fromCharCode(out_byte));
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_write(port | 1, function(out_byte)
|
||||
io.register_write(port | 1, this, function(out_byte)
|
||||
{
|
||||
if(this.line_control & DLAB)
|
||||
{
|
||||
|
@ -112,9 +112,9 @@ function UART(cpu, port, adapter)
|
|||
this.interrupt_enable = out_byte;
|
||||
dbg_log("interrupt enable: " + h(out_byte), LOG_SERIAL);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port, function()
|
||||
io.register_read(port, this, function()
|
||||
{
|
||||
if(this.line_control & DLAB)
|
||||
{
|
||||
|
@ -135,9 +135,9 @@ function UART(cpu, port, adapter)
|
|||
|
||||
return data;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 1, function()
|
||||
io.register_read(port | 1, this, function()
|
||||
{
|
||||
if(this.line_control & DLAB)
|
||||
{
|
||||
|
@ -147,45 +147,45 @@ function UART(cpu, port, adapter)
|
|||
{
|
||||
return this.interrupt_enable;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 2, function()
|
||||
io.register_read(port | 2, this, function()
|
||||
{
|
||||
var ret = this.iir;
|
||||
dbg_log("read interrupt identification: " + h(this.iir), LOG_SERIAL);
|
||||
this.iir ^= 1;
|
||||
|
||||
return ret;
|
||||
}, this);
|
||||
io.register_write(port | 2, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 2, this, function(out_byte)
|
||||
{
|
||||
dbg_log("fifo control: " + h(out_byte), LOG_SERIAL);
|
||||
this.fifo_control = out_byte;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 3, function()
|
||||
io.register_read(port | 3, this, function()
|
||||
{
|
||||
dbg_log("read line control: " + h(this.line_control), LOG_SERIAL);
|
||||
return this.line_control;
|
||||
}, this);
|
||||
io.register_write(port | 3, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 3, this, function(out_byte)
|
||||
{
|
||||
dbg_log("line control: " + h(out_byte), LOG_SERIAL);
|
||||
this.line_control = out_byte;
|
||||
}, this);
|
||||
});
|
||||
|
||||
|
||||
io.register_read(port | 4, function()
|
||||
io.register_read(port | 4, this, function()
|
||||
{
|
||||
return this.modem_control;
|
||||
}, this);
|
||||
io.register_write(port | 4, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 4, this, function(out_byte)
|
||||
{
|
||||
dbg_log("modem control: " + h(out_byte), LOG_SERIAL);
|
||||
this.modem_control = out_byte;
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 5, function()
|
||||
io.register_read(port | 5, this, function()
|
||||
{
|
||||
var line_status = 0;
|
||||
|
||||
|
@ -198,30 +198,30 @@ function UART(cpu, port, adapter)
|
|||
|
||||
dbg_log("read line status: " + h(line_status), LOG_SERIAL);
|
||||
return line_status;
|
||||
}, this);
|
||||
io.register_write(port | 5, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 5, this, function(out_byte)
|
||||
{
|
||||
dbg_log("Factory test write", LOG_SERIAL);
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 6, function()
|
||||
io.register_read(port | 6, this, function()
|
||||
{
|
||||
dbg_log("read modem status: " + h(this.modem_status), LOG_SERIAL);
|
||||
return this.modem_status;
|
||||
}, this);
|
||||
io.register_write(port | 6, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 6, this, function(out_byte)
|
||||
{
|
||||
dbg_log("Unkown register write (base+6)", LOG_SERIAL);
|
||||
}, this);
|
||||
});
|
||||
|
||||
io.register_read(port | 7, function()
|
||||
io.register_read(port | 7, this, function()
|
||||
{
|
||||
return this.scratch_register;
|
||||
}, this);
|
||||
io.register_write(port | 7, function(out_byte)
|
||||
});
|
||||
io.register_write(port | 7, this, function(out_byte)
|
||||
{
|
||||
this.scratch_register = out_byte;
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
|
||||
UART.prototype.push_irq = function()
|
||||
|
|
103
src/vga.js
103
src/vga.js
|
@ -182,49 +182,43 @@ function VGAScreen(cpu, adapter, vga_memory_size)
|
|||
|
||||
var io = cpu.io;
|
||||
|
||||
io.register_write(0x3C0, this.port3C0_write, this);
|
||||
io.register_read(0x3C0, this.port3C0_read, this);
|
||||
io.register_write(0x3C0, this, this.port3C0_write);
|
||||
io.register_read(0x3C0, this, this.port3C0_read);
|
||||
|
||||
io.register_read(0x3C1, this.port3C1_read, this);
|
||||
io.register_write(0x3C2, this.port3C2_write, this);
|
||||
io.register_read(0x3C1, this, this.port3C1_read);
|
||||
io.register_write(0x3C2, this, this.port3C2_write);
|
||||
|
||||
io.register_write(0x3C4, this.port3C4_write, this);
|
||||
io.register_read(0x3C4, this.port3C4_read, this);
|
||||
io.register_write_consecutive(0x3C4, this, this.port3C4_write, this.port3C5_write);
|
||||
|
||||
io.register_write(0x3C5, this.port3C5_write, this);
|
||||
io.register_read(0x3C5, this.port3C5_read, this);
|
||||
io.register_read(0x3C4, this, this.port3C4_read);
|
||||
io.register_read(0x3C5, this, this.port3C5_read);
|
||||
|
||||
io.register_write(0x3CE, this.port3CE_write, this);
|
||||
io.register_read(0x3CE, this.port3CE_read, this);
|
||||
io.register_write_consecutive(0x3CE, this, this.port3CE_write, this.port3CF_write);
|
||||
|
||||
io.register_write(0x3CF, this.port3CF_write, this);
|
||||
io.register_read(0x3CF, this.port3CF_read, this);
|
||||
io.register_read(0x3CE, this, this.port3CE_read);
|
||||
io.register_read(0x3CF, this, this.port3CF_read);
|
||||
|
||||
io.register_write(0x3C7, this.port3C7_write, this);
|
||||
io.register_write(0x3C8, this.port3C8_write, this);
|
||||
io.register_write(0x3C9, this.port3C9_write, this);
|
||||
io.register_write(0x3C7, this, this.port3C7_write);
|
||||
io.register_write(0x3C8, this, this.port3C8_write);
|
||||
io.register_write(0x3C9, this, this.port3C9_write);
|
||||
|
||||
io.register_read(0x3CC, this.port3CC_read, this);
|
||||
io.register_read(0x3CC, this, this.port3CC_read);
|
||||
|
||||
io.register_write(0x3D4, this.port3D4_write, this);
|
||||
io.register_write(0x3D5, this.port3D5_write, this);
|
||||
io.register_read(0x3D5, this.port3D5_read, this);
|
||||
io.register_write_consecutive(0x3D4, this, this.port3D4_write, this.port3D5_write);
|
||||
io.register_read(0x3D5, this, this.port3D5_read);
|
||||
|
||||
io.register_read(0x3DA, this.port3DA_read, this);
|
||||
io.register_read(0x3DA, this, this.port3DA_read);
|
||||
|
||||
|
||||
// Bochs VBE Extensions
|
||||
// http://wiki.osdev.org/Bochs_VBE_Extensions
|
||||
this.dispi_index = -1;
|
||||
this.dispi_value = -1;
|
||||
this.dispi_enable_value = 0;
|
||||
|
||||
io.register_write(0x1CE, this.port1CE_write, this);
|
||||
io.register_write(0x1CF, this.port1CF_write, this);
|
||||
io.register_write(0x1D0, this.port1D0_write, this);
|
||||
io.register_write(0x1CE, this, undefined, this.port1CE_write);
|
||||
|
||||
io.register_read(0x1CF, this.port1CF_read, this);
|
||||
io.register_read(0x1D0, this.port1D0_read, this);
|
||||
io.register_write(0x1CF, this, undefined, this.port1CF_write);
|
||||
io.register_read(0x1CF, this, undefined, this.port1CF_read);
|
||||
|
||||
if(this.vga_memory_size === undefined || this.vga_memory_size < 4 * VGA_BANK_SIZE)
|
||||
{
|
||||
|
@ -252,13 +246,16 @@ function VGAScreen(cpu, adapter, vga_memory_size)
|
|||
this.set_size_text(80, 25);
|
||||
this.update_cursor_scanline();
|
||||
|
||||
var me = this;
|
||||
io.mmap_register(0xA0000, 0x20000,
|
||||
this.vga_memory_read.bind(this),
|
||||
this.vga_memory_write.bind(this)
|
||||
function(addr) { return me.vga_memory_read(addr); },
|
||||
function(addr, value) { me.vga_memory_write(addr, value); }
|
||||
);
|
||||
io.mmap_register(0xE0000000, this.vga_memory_size,
|
||||
this.svga_memory_read8.bind(this), this.svga_memory_write8.bind(this),
|
||||
this.svga_memory_read32.bind(this), this.svga_memory_write32.bind(this)
|
||||
function(addr) { return me.svga_memory_read8(addr); },
|
||||
function(addr, value) { me.svga_memory_write8(addr, value); },
|
||||
function(addr) { return me.svga_memory_read32(addr); },
|
||||
function(addr, value) { me.svga_memory_write32(addr, value); }
|
||||
);
|
||||
|
||||
/** @const */
|
||||
|
@ -1211,29 +1208,14 @@ VGAScreen.prototype.port1CE_write = function(value)
|
|||
this.dispi_index = value;
|
||||
};
|
||||
|
||||
VGAScreen.prototype.port1CF_write = function(value, low_port)
|
||||
VGAScreen.prototype.port1CF_write = function(value)
|
||||
{
|
||||
if(low_port === 0x1CE)
|
||||
{
|
||||
this.dispi_index = this.dispi_index & 0xFF | value << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dispi_value = value;
|
||||
|
||||
dbg_log("1CF / dispi write low " + h(this.dispi_index) + ": " + h(value), LOG_VGA);
|
||||
}
|
||||
};
|
||||
|
||||
VGAScreen.prototype.port1D0_write = function(value)
|
||||
{
|
||||
dbg_log("1D0 / dispi write high " + h(this.dispi_index) + ": " + h(value), LOG_VGA);
|
||||
this.dispi_value = this.dispi_value & 0xFF | value << 8;
|
||||
dbg_log("1CF / dispi write " + h(this.dispi_index) + ": " + h(value), LOG_VGA);
|
||||
|
||||
switch(this.dispi_index)
|
||||
{
|
||||
case 1:
|
||||
this.svga_width = this.dispi_value;
|
||||
this.svga_width = value;
|
||||
if(this.svga_width > MAX_XRES)
|
||||
{
|
||||
dbg_log("svga_width reduced from " + this.svga_width + " to " + MAX_XRES, LOG_VGA);
|
||||
|
@ -1241,7 +1223,7 @@ VGAScreen.prototype.port1D0_write = function(value)
|
|||
}
|
||||
break;
|
||||
case 2:
|
||||
this.svga_height = this.dispi_value;
|
||||
this.svga_height = value;
|
||||
if(this.svga_height > MAX_YRES)
|
||||
{
|
||||
dbg_log("svga_height reduced from " + this.svga_height + " to " + MAX_YRES, LOG_VGA);
|
||||
|
@ -1249,17 +1231,17 @@ VGAScreen.prototype.port1D0_write = function(value)
|
|||
}
|
||||
break;
|
||||
case 3:
|
||||
this.svga_bpp = this.dispi_value;
|
||||
this.svga_bpp = value;
|
||||
break;
|
||||
case 4:
|
||||
// enable, options
|
||||
this.svga_enabled = (this.dispi_value & 1) === 1;
|
||||
this.dispi_enable_value = this.dispi_value;
|
||||
this.svga_enabled = (value & 1) === 1;
|
||||
this.dispi_enable_value = value;
|
||||
break;
|
||||
case 9:
|
||||
// y offset
|
||||
this.svga_offset = this.dispi_value * this.svga_bytes_per_line();
|
||||
dbg_log("SVGA offset: " + h(this.svga_offset) + " y=" + h(this.dispi_value), LOG_VGA);
|
||||
this.svga_offset = value * this.svga_bytes_per_line();
|
||||
dbg_log("SVGA offset: " + h(this.svga_offset) + " y=" + h(value), LOG_VGA);
|
||||
this.do_complete_redraw = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -1287,14 +1269,9 @@ VGAScreen.prototype.port1D0_write = function(value)
|
|||
|
||||
VGAScreen.prototype.port1CF_read = function()
|
||||
{
|
||||
dbg_log("1CF / dispi read low " + h(this.dispi_index), LOG_VGA);
|
||||
dbg_log("1CF / dispi read " + h(this.dispi_index), LOG_VGA);
|
||||
return this.svga_register_read(this.dispi_index);
|
||||
};
|
||||
VGAScreen.prototype.port1D0_read = function()
|
||||
{
|
||||
dbg_log("1D0 / dispi read high " + h(this.dispi_index), LOG_VGA);
|
||||
return this.svga_register_read(this.dispi_index) >> 8;
|
||||
};
|
||||
|
||||
VGAScreen.prototype.svga_register_read = function(n)
|
||||
{
|
||||
|
@ -1304,11 +1281,11 @@ VGAScreen.prototype.svga_register_read = function(n)
|
|||
// id
|
||||
return 0xB0C0;
|
||||
case 1:
|
||||
return this.dispi_value & 2 ? MAX_XRES : this.svga_width;
|
||||
return this.dispi_enable_value & 2 ? MAX_XRES : this.svga_width;
|
||||
case 2:
|
||||
return this.dispi_value & 2 ? MAX_YRES : this.svga_height;
|
||||
return this.dispi_enable_value & 2 ? MAX_YRES : this.svga_height;
|
||||
case 3:
|
||||
return this.dispi_value & 2 ? MAX_BPP : this.svga_bpp;
|
||||
return this.dispi_enable_value & 2 ? MAX_BPP : this.svga_bpp;
|
||||
case 4:
|
||||
return this.dispi_enable_value;
|
||||
case 6:
|
||||
|
|
Loading…
Reference in a new issue