| "use strict"; |
| |
| // http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf |
| |
| /** @const */ |
| var PMTIMER_FREQ = 3579545; |
| |
| /** |
| * @constructor |
| * @param {CPU} cpu |
| */ |
| function ACPI(cpu) |
| { |
| /** @type {CPU} */ |
| this.cpu = cpu; |
| |
| var io = cpu.io; |
| |
| var acpi = { |
| pci_id: 0x07 << 3, |
| pci_space: [ |
| 0x86, 0x80, 0x13, 0x71, 0x07, 0x00, 0x80, 0x02, 0x08, 0x00, 0x80, 0x06, 0x00, 0x00, 0x80, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, |
| ], |
| pci_bars: [], |
| name: "acpi", |
| }; |
| |
| // 00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08) |
| cpu.devices.pci.register_device(acpi); |
| |
| this.status = 1; |
| this.pm1_status = 0; |
| this.pm1_enable = 0; |
| this.last_timer = this.get_timer(v86.microtick()); |
| |
| io.register_read(0xB000, this, undefined, function() |
| { |
| dbg_log("ACPI pm1_status read", LOG_ACPI); |
| return this.pm1_status; |
| }); |
| io.register_write(0xB000, this, undefined, function(value) |
| { |
| dbg_log("ACPI pm1_status write: " + h(value, 4), LOG_ACPI); |
| this.pm1_status &= ~value; |
| }); |
| |
| io.register_read(0xB002, this, undefined, function() |
| { |
| dbg_log("ACPI pm1_enable read", LOG_ACPI); |
| return this.pm1_enable; |
| }); |
| io.register_write(0xB002, this, undefined, function(value) |
| { |
| dbg_log("ACPI pm1_enable write: " + h(value), LOG_ACPI); |
| this.pm1_enable = value; |
| }); |
| |
| // ACPI status |
| io.register_read(0xB004, this, undefined, function() |
| { |
| dbg_log("ACPI status read", LOG_ACPI); |
| return this.status; |
| }); |
| io.register_write(0xB004, this, undefined, function(value) |
| { |
| dbg_log("ACPI status write: " + h(value), LOG_ACPI); |
| this.status = value; |
| }); |
| |
| // ACPI, pmtimer |
| io.register_read(0xB008, this, undefined, undefined, function() |
| { |
| var value = this.get_timer(v86.microtick()) & 0xFFFFFF; |
| //dbg_log("pmtimer read: " + h(value >>> 0), LOG_ACPI); |
| return value; |
| }); |
| } |
| |
| ACPI.prototype.timer = function(now) |
| { |
| var timer = this.get_timer(now); |
| var highest_bit_changed = ((timer ^ this.last_timer) & (1 << 23)) !== 0; |
| |
| if((this.pm1_enable & 1) && highest_bit_changed) |
| { |
| dbg_log("ACPI raise irq", LOG_ACPI); |
| this.pm1_status |= 1; |
| this.cpu.device_raise_irq(9); |
| } |
| else |
| { |
| this.cpu.device_lower_irq(9); |
| } |
| |
| this.last_timer = timer; |
| }; |
| |
| ACPI.prototype.get_timer = function(now) |
| { |
| return now * (PMTIMER_FREQ / 1000) | 0; |
| }; |
| |
| ACPI.prototype.get_state = function() |
| { |
| var state = []; |
| state[0] = this.status; |
| state[1] = this.pm1_status; |
| state[2] = this.pm1_enable; |
| return state; |
| }; |
| |
| ACPI.prototype.set_state = function(state) |
| { |
| this.status = state[0]; |
| this.pm1_status = state[1]; |
| this.pm1_enable = state[2]; |
| }; |