SandboXP

Форк
0
/
acpi.js 
207 строк · 5.4 Кб
1
"use strict";
2

3
// http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf
4

5
/** @const */
6
var PMTIMER_FREQ_SECONDS = 3579545;
7

8
/**
9
 * @constructor
10
 * @param {CPU} cpu
11
 */
12
function ACPI(cpu)
13
{
14
    /** @type {CPU} */
15
    this.cpu = cpu;
16

17
    var io = cpu.io;
18

19
    var acpi = {
20
        pci_id: 0x07 << 3,
21
        pci_space: [
22
            0x86, 0x80, 0x13, 0x71, 0x07, 0x00, 0x80, 0x02, 0x08, 0x00, 0x80, 0x06, 0x00, 0x00, 0x80, 0x00,
23
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00,
26
        ],
27
        pci_bars: [],
28
        name: "acpi",
29
    };
30

31
    // 00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
32
    cpu.devices.pci.register_device(acpi);
33

34
    this.timer_last_value = 0;
35
    this.timer_imprecision_offset = 0;
36

37
    this.status = 1;
38
    this.pm1_status = 0;
39
    this.pm1_enable = 0;
40
    this.last_timer = this.get_timer(v86.microtick());
41

42
    this.gpe = new Uint8Array(4);
43

44
    io.register_read(0xB000, this, undefined, function()
45
    {
46
        dbg_log("ACPI pm1_status read", LOG_ACPI);
47
        return this.pm1_status;
48
    });
49
    io.register_write(0xB000, this, undefined, function(value)
50
    {
51
        dbg_log("ACPI pm1_status write: " + h(value, 4), LOG_ACPI);
52
        this.pm1_status &= ~value;
53
    });
54

55
    io.register_read(0xB002, this, undefined, function()
56
    {
57
        dbg_log("ACPI pm1_enable read", LOG_ACPI);
58
        return this.pm1_enable;
59
    });
60
    io.register_write(0xB002, this, undefined, function(value)
61
    {
62
        dbg_log("ACPI pm1_enable write: " + h(value), LOG_ACPI);
63
        this.pm1_enable = value;
64
    });
65

66
    // ACPI status
67
    io.register_read(0xB004, this, undefined, function()
68
    {
69
        dbg_log("ACPI status read", LOG_ACPI);
70
        return this.status;
71
    });
72
    io.register_write(0xB004, this, undefined, function(value)
73
    {
74
        dbg_log("ACPI status write: " + h(value), LOG_ACPI);
75
        this.status = value;
76
    });
77

78
    // ACPI, pmtimer
79
    io.register_read(0xB008, this, undefined, undefined, function()
80
    {
81
        var value = this.get_timer(v86.microtick()) & 0xFFFFFF;
82
        //dbg_log("pmtimer read: " + h(value >>> 0), LOG_ACPI);
83
        return value;
84
    });
85

86
    // ACPI, gpe
87
    io.register_read(0xAFE0, this, function()
88
    {
89
        dbg_log("Read gpe#0", LOG_ACPI);
90
        return this.gpe[0];
91
    });
92
    io.register_read(0xAFE1, this, function()
93
    {
94
        dbg_log("Read gpe#1", LOG_ACPI);
95
        return this.gpe[1];
96
    });
97
    io.register_read(0xAFE2, this, function()
98
    {
99
        dbg_log("Read gpe#2", LOG_ACPI);
100
        return this.gpe[2];
101
    });
102
    io.register_read(0xAFE3, this, function()
103
    {
104
        dbg_log("Read gpe#3", LOG_ACPI);
105
        return this.gpe[3];
106
    });
107

108
    io.register_write(0xAFE0, this, function(value)
109
    {
110
        dbg_log("Write gpe#0: " + h(value), LOG_ACPI);
111
        this.gpe[0] = value;
112
    });
113
    io.register_write(0xAFE1, this, function(value)
114
    {
115
        dbg_log("Write gpe#1: " + h(value), LOG_ACPI);
116
        this.gpe[1] = value;
117
    });
118
    io.register_write(0xAFE2, this, function(value)
119
    {
120
        dbg_log("Write gpe#2: " + h(value), LOG_ACPI);
121
        this.gpe[2] = value;
122
    });
123
    io.register_write(0xAFE3, this, function(value)
124
    {
125
        dbg_log("Write gpe#3: " + h(value), LOG_ACPI);
126
        this.gpe[3] = value;
127
    });
128
}
129

130
ACPI.prototype.timer = function(now)
131
{
132
    var timer = this.get_timer(now);
133
    var highest_bit_changed = ((timer ^ this.last_timer) & (1 << 23)) !== 0;
134

135
    if((this.pm1_enable & 1) && highest_bit_changed)
136
    {
137
        dbg_log("ACPI raise irq", LOG_ACPI);
138
        this.pm1_status |= 1;
139
        this.cpu.device_raise_irq(9);
140
    }
141
    else
142
    {
143
        this.cpu.device_lower_irq(9);
144
    }
145

146
    this.last_timer = timer;
147
    return 100; // TODO
148
};
149

150
ACPI.prototype.get_timer = function(now)
151
{
152
    const t = Math.round(now * (PMTIMER_FREQ_SECONDS / 1000));
153

154
    // Due to the low precision of JavaScript's time functions we increment the
155
    // returned timer value every time it is read
156

157
    if(t === this.timer_last_value)
158
    {
159
        // don't go past 1ms
160

161
        if(this.timer_imprecision_offset < PMTIMER_FREQ_SECONDS / 1000)
162
        {
163
            this.timer_imprecision_offset++;
164
        }
165
    }
166
    else
167
    {
168
        dbg_assert(t > this.timer_last_value);
169

170
        const previous_timer = this.timer_last_value + this.timer_imprecision_offset;
171

172
        // don't go back in time
173

174
        if(previous_timer <= t)
175
        {
176
            this.timer_imprecision_offset = 0;
177
            this.timer_last_value = t;
178
        }
179
        else
180
        {
181
            dbg_log("Warning: Overshot pmtimer, waiting;" +
182
                    " current=" + t +
183
                    " last=" + this.timer_last_value +
184
                    " offset=" + this.timer_imprecision_offset, LOG_ACPI);
185
        }
186
    }
187

188
    return this.timer_last_value + this.timer_imprecision_offset;
189
};
190

191
ACPI.prototype.get_state = function()
192
{
193
    var state = [];
194
    state[0] = this.status;
195
    state[1] = this.pm1_status;
196
    state[2] = this.pm1_enable;
197
    state[3] = this.gpe;
198
    return state;
199
};
200

201
ACPI.prototype.set_state = function(state)
202
{
203
    this.status = state[0];
204
    this.pm1_status = state[1];
205
    this.pm1_enable = state[2];
206
    this.gpe = state[3];
207
};
208

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.