18
for(var i = 0; i < 0x10000; i++)
20
this.ports[i] = this.create_empty_entry();
23
var memory_size = cpu.memory_size[0];
25
for(var i = 0; (i << MMAP_BLOCK_BITS) < memory_size; i++)
28
cpu.memory_map_read8[i] = cpu.memory_map_write8[i] = undefined;
29
cpu.memory_map_read32[i] = cpu.memory_map_write32[i] = undefined;
32
this.mmap_register(memory_size, 0x100000000 - memory_size,
35
dbg_log("Read from unmapped memory space, addr=" + h(addr >>> 0, 8), LOG_IO);
38
function(addr, value) {
40
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value, 2), LOG_IO);
43
dbg_log("Read from unmapped memory space, addr=" + h(addr >>> 0, 8), LOG_IO);
46
function(addr, value) {
47
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value >>> 0, 8), LOG_IO);
52
IO.prototype.create_empty_entry = function()
55
read8: this.empty_port_read8,
56
read16: this.empty_port_read16,
57
read32: this.empty_port_read32,
59
write8: this.empty_port_write,
60
write16: this.empty_port_write,
61
write32: this.empty_port_write,
67
IO.prototype.empty_port_read8 = function()
72
IO.prototype.empty_port_read16 = function()
77
IO.prototype.empty_port_read32 = function()
82
IO.prototype.empty_port_write = function(x)
94
IO.prototype.register_read = function(port_addr, device, r8, r16, r32)
96
dbg_assert(typeof port_addr === "number");
97
dbg_assert(typeof device === "object");
98
dbg_assert(!r8 || typeof r8 === "function");
99
dbg_assert(!r16 || typeof r16 === "function");
100
dbg_assert(!r32 || typeof r32 === "function");
101
dbg_assert(r8 || r16 || r32);
105
var fail = function(n) {
106
dbg_assert(false, "Overlapped read" + n + " " + h(port_addr, 4) + " (" + device.name + ")");
107
return -1 >>> (32 - n) | 0;
109
if(!r8) r8 = fail.bind(this, 8);
110
if(!r16) r16 = fail.bind(this, 16);
111
if(!r32) r32 = fail.bind(this, 32);
114
if(r8) this.ports[port_addr].read8 = r8;
115
if(r16) this.ports[port_addr].read16 = r16;
116
if(r32) this.ports[port_addr].read32 = r32;
117
this.ports[port_addr].device = device;
127
IO.prototype.register_write = function(port_addr, device, w8, w16, w32)
129
dbg_assert(typeof port_addr === "number");
130
dbg_assert(typeof device === "object");
131
dbg_assert(!w8 || typeof w8 === "function");
132
dbg_assert(!w16 || typeof w16 === "function");
133
dbg_assert(!w32 || typeof w32 === "function");
134
dbg_assert(w8 || w16 || w32);
138
var fail = function(n) {
139
dbg_assert(false, "Overlapped write" + n + " " + h(port_addr) + " (" + device.name + ")");
141
if(!w8) w8 = fail.bind(this, 8);
142
if(!w16) w16 = fail.bind(this, 16);
143
if(!w32) w32 = fail.bind(this, 32);
146
if(w8) this.ports[port_addr].write8 = w8;
147
if(w16) this.ports[port_addr].write16 = w16;
148
if(w32) this.ports[port_addr].write32 = w32;
149
this.ports[port_addr].device = device;
169
IO.prototype.register_read_consecutive = function(port_addr, device, r8_1, r8_2, r8_3, r8_4)
171
dbg_assert(arguments.length === 4 || arguments.length === 6);
175
return r8_1.call(this) |
176
r8_2.call(this) << 8;
180
return r8_3.call(this) |
181
r8_4.call(this) << 8;
185
return r8_1.call(this) |
186
r8_2.call(this) << 8 |
187
r8_3.call(this) << 16 |
188
r8_4.call(this) << 24;
193
this.register_read(port_addr, device, r8_1, r16_1, r32);
194
this.register_read(port_addr + 1, device, r8_2);
195
this.register_read(port_addr + 2, device, r8_3, r16_2);
196
this.register_read(port_addr + 3, device, r8_4);
200
this.register_read(port_addr, device, r8_1, r16_1);
201
this.register_read(port_addr + 1, device, r8_2);
213
IO.prototype.register_write_consecutive = function(port_addr, device, w8_1, w8_2, w8_3, w8_4)
215
dbg_assert(arguments.length === 4 || arguments.length === 6);
219
w8_1.call(this, data & 0xFF);
220
w8_2.call(this, data >> 8 & 0xFF);
224
w8_3.call(this, data & 0xFF);
225
w8_4.call(this, data >> 8 & 0xFF);
229
w8_1.call(this, data & 0xFF);
230
w8_2.call(this, data >> 8 & 0xFF);
231
w8_3.call(this, data >> 16 & 0xFF);
232
w8_4.call(this, data >>> 24);
237
this.register_write(port_addr, device, w8_1, w16_1, w32);
238
this.register_write(port_addr + 1, device, w8_2);
239
this.register_write(port_addr + 2, device, w8_3, w16_2);
240
this.register_write(port_addr + 3, device, w8_4);
244
this.register_write(port_addr, device, w8_1, w16_1);
245
this.register_write(port_addr + 1, device, w8_2);
249
IO.prototype.mmap_read32_shim = function(addr)
251
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
252
var fn = this.cpu.memory_map_read8[aligned_addr];
254
return fn(addr) | fn(addr + 1) << 8 |
255
fn(addr + 2) << 16 | fn(addr + 3) << 24;
258
IO.prototype.mmap_write32_shim = function(addr, value)
260
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
261
var fn = this.cpu.memory_map_write8[aligned_addr];
263
fn(addr, value & 0xFF);
264
fn(addr + 1, value >> 8 & 0xFF);
265
fn(addr + 2, value >> 16 & 0xFF);
266
fn(addr + 3, value >>> 24);
277
IO.prototype.mmap_register = function(addr, size, read_func8, write_func8, read_func32, write_func32)
279
dbg_log("mmap_register addr=" + h(addr >>> 0, 8) + " size=" + h(size, 8), LOG_IO);
281
dbg_assert((addr & MMAP_BLOCK_SIZE - 1) === 0);
282
dbg_assert(size && (size & MMAP_BLOCK_SIZE - 1) === 0);
285
read_func32 = this.mmap_read32_shim.bind(this);
288
write_func32 = this.mmap_write32_shim.bind(this);
290
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
292
for(; size > 0; aligned_addr++)
294
this.cpu.memory_map_read8[aligned_addr] = read_func8;
295
this.cpu.memory_map_write8[aligned_addr] = write_func8;
296
this.cpu.memory_map_read32[aligned_addr] = read_func32;
297
this.cpu.memory_map_write32[aligned_addr] = write_func32;
299
size -= MMAP_BLOCK_SIZE;
304
IO.prototype.port_write8 = function(port_addr, data)
306
var entry = this.ports[port_addr];
308
if(entry.write8 === this.empty_port_write || LOG_ALL_IO)
311
"write8 port #" + h(port_addr, 4) + " <- " + h(data, 2) + this.get_port_description(port_addr),
315
return entry.write8.call(entry.device, data);
318
IO.prototype.port_write16 = function(port_addr, data)
320
var entry = this.ports[port_addr];
322
if(entry.write16 === this.empty_port_write || LOG_ALL_IO)
325
"write16 port #" + h(port_addr, 4) + " <- " + h(data, 4) + this.get_port_description(port_addr),
329
return entry.write16.call(entry.device, data);
332
IO.prototype.port_write32 = function(port_addr, data)
334
var entry = this.ports[port_addr];
336
if(entry.write32 === this.empty_port_write || LOG_ALL_IO)
339
"write32 port #" + h(port_addr, 4) + " <- " + h(data >>> 0, 8) + this.get_port_description(port_addr),
343
return entry.write32.call(entry.device, data);
346
IO.prototype.port_read8 = function(port_addr)
348
var entry = this.ports[port_addr];
350
if(entry.read8 === this.empty_port_read8 || LOG_ALL_IO)
353
"read8 port #" + h(port_addr, 4) + this.get_port_description(port_addr),
357
var value = entry.read8.call(entry.device);
358
dbg_assert(value < 0x100, "8 bit port returned large value: " + h(port_addr));
362
IO.prototype.port_read16 = function(port_addr)
364
var entry = this.ports[port_addr];
366
if(entry.read16 === this.empty_port_read16 || LOG_ALL_IO)
369
"read16 port #" + h(port_addr, 4) + this.get_port_description(port_addr),
373
var value = entry.read16.call(entry.device);
374
dbg_assert(value < 0x10000 && value >= 0, "16 bit port returned large value: " + h(port_addr));
378
IO.prototype.port_read32 = function(port_addr)
380
var entry = this.ports[port_addr];
382
if(entry.read32 === this.empty_port_read32 || LOG_ALL_IO)
385
"read32 port #" + h(port_addr, 4) + this.get_port_description(port_addr),
389
var value = entry.read32.call(entry.device);
390
dbg_assert((value | 0) === value);
395
var debug_port_list = {
396
0x0004: "PORT_DMA_ADDR_2",
397
0x0005: "PORT_DMA_CNT_2",
398
0x000a: "PORT_DMA1_MASK_REG",
399
0x000b: "PORT_DMA1_MODE_REG",
400
0x000c: "PORT_DMA1_CLEAR_FF_REG",
401
0x000d: "PORT_DMA1_MASTER_CLEAR",
402
0x0020: "PORT_PIC1_CMD",
403
0x0021: "PORT_PIC1_DATA",
404
0x0040: "PORT_PIT_COUNTER0",
405
0x0041: "PORT_PIT_COUNTER1",
406
0x0042: "PORT_PIT_COUNTER2",
407
0x0043: "PORT_PIT_MODE",
408
0x0060: "PORT_PS2_DATA",
409
0x0061: "PORT_PS2_CTRLB",
410
0x0064: "PORT_PS2_STATUS",
411
0x0070: "PORT_CMOS_INDEX",
412
0x0071: "PORT_CMOS_DATA",
414
0x0081: "PORT_DMA_PAGE_2",
416
0x00a0: "PORT_PIC2_CMD",
417
0x00a1: "PORT_PIC2_DATA",
418
0x00b2: "PORT_SMI_CMD",
419
0x00b3: "PORT_SMI_STATUS",
420
0x00d4: "PORT_DMA2_MASK_REG",
421
0x00d6: "PORT_DMA2_MODE_REG",
422
0x00da: "PORT_DMA2_MASTER_CLEAR",
423
0x00f0: "PORT_MATH_CLEAR",
424
0x0170: "PORT_ATA2_CMD_BASE",
425
0x01f0: "PORT_ATA1_CMD_BASE",
427
0x02e8: "PORT_SERIAL4",
428
0x02f8: "PORT_SERIAL2",
429
0x0374: "PORT_ATA2_CTRL_BASE",
431
0x03e8: "PORT_SERIAL3",
433
0x03f0: "PORT_FD_BASE",
434
0x03f2: "PORT_FD_DOR",
435
0x03f4: "PORT_FD_STATUS",
436
0x03f5: "PORT_FD_DATA",
437
0x03f6: "PORT_HD_DATA",
438
0x03f7: "PORT_FD_DIR",
439
0x03f8: "PORT_SERIAL1",
440
0x0cf8: "PORT_PCI_CMD",
441
0x0cf9: "PORT_PCI_REBOOT",
442
0x0cfc: "PORT_PCI_DATA",
443
0x0402: "PORT_BIOS_DEBUG",
444
0x0510: "PORT_QEMU_CFG_CTL",
445
0x0511: "PORT_QEMU_CFG_DATA",
446
0xb000: "PORT_ACPI_PM_BASE",
447
0xb100: "PORT_SMB_BASE",
448
0x8900: "PORT_BIOS_APM"
451
IO.prototype.get_port_description = function(addr)
453
if(debug_port_list[addr])
455
return " (" + debug_port_list[addr] + ")";