Preparations for configurable PCI, base address registers

This commit is contained in:
copy 2013-12-20 22:04:58 +01:00
parent 125b7748a1
commit e73c75b8ee
7 changed files with 284 additions and 190 deletions

View file

@ -313,6 +313,7 @@ var
reg8s,
sreg,
dreg,
// sp or esp, depending on stack size attribute
@ -473,6 +474,7 @@ function cpu_init(settings)
reg8 = new Uint8Array(reg32.buffer);
reg8s = new Int8Array(reg32.buffer);
sreg = new Uint16Array(8);
dreg = new Int32Array(8);
protected_mode = false;
idtr_size = 0;
@ -531,6 +533,15 @@ function cpu_init(settings)
last_op_size = 0;
var devapi = {
memory: memory,
reboot: cpu_reboot_internal,
time: function() { return performance.now(); },
};
cpu.dev = {};
devapi.io = cpu.dev.io = io = new IO(memory);
if(settings.bios)
{
@ -548,7 +559,7 @@ function cpu_init(settings)
}
// seabios expects the bios to be mapped to 0xFFF00000 also
memory.mmap_register(0xFFF00000, 0x100000, 1,
io.mmap_register(0xFFF00000, 0x100000, 1,
function(addr)
{
return memory.mem8[addr];
@ -615,17 +626,31 @@ function cpu_init(settings)
}
cpu.dev = {};
var a20_byte = 0;
io.register_read(0x92, function()
{
return a20_byte;
});
io.register_write(0x92, function(out_byte)
{
a20_byte = out_byte;
});
if(DEBUG)
{
// Use by linux for port-IO delay
// Avoid generating tons of debug messages
io.register_write(0x80, function(out_byte)
{
});
}
// TODO: Make this more configurable
if(settings.load_devices)
{
var devapi = {
memory: memory,
reboot: cpu_reboot_internal,
time: function() { return performance.now(); },
};
devapi.io = cpu.dev.io = io = new IO();
devapi.pic = pic = new PIC(devapi, call_interrupt_vector, handle_irqs);
devapi.pci = pci = new PCI(devapi);
devapi.dma = dma = new DMA(devapi);
@ -665,54 +690,58 @@ function cpu_init(settings)
hpet = new HPET(devapi);
}
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: [],
};
// 00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
this.register_device([
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,
], 0x07 << 3);
io.register_device(acpi);
var elcr = 0;
// ACPI, ELCR register
dev.io.register_write(0x4d0, function(data)
io.register_write(0x4d0, function(data)
{
elcr = elcr & 0xFF00 | data;
});
dev.io.register_write(0x4d1, function(data)
io.register_write(0x4d1, function(data)
{
elcr = elcr & 0xFF | data << 8;
});
// ACPI, pmtimer
dev.io.register_read(0xb008, function(data)
io.register_read(0xb008, function(data)
{
return 0;
});
dev.io.register_read(0xb009, function(data)
io.register_read(0xb009, function(data)
{
return 0;
});
dev.io.register_read(0xb00a, function(data)
io.register_read(0xb00a, function(data)
{
return 0;
});
dev.io.register_read(0xb00b, function(data)
io.register_read(0xb00b, function(data)
{
return 0;
});
// ACPI status
dev.io.register_read(0xb004, function(data)
io.register_read(0xb004, function(data)
{
dbg_log("b004 read");
return 1;
});
dev.io.register_read(0xb005, function(data)
io.register_read(0xb005, function(data)
{
dbg_log("b005 read");
return 0;
@ -922,12 +951,12 @@ var npe_functions = {
read_imm8: function()
{
return memory.mem8[instruction_pointer++];
return memory.read8(instruction_pointer++);
},
read_imm8s: function()
{
return memory.mem8s[instruction_pointer++];
return memory.read8(instruction_pointer++) << 24 >> 24;
},
read_imm16 : function()
@ -1262,10 +1291,10 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
//}
//if(interrupt_nr === 14)
//{
// dbg_log("int14 error_code=" + error_code + " cr2=" + h(cr2 >>> 0) + " prev=" + h(previous_ip >>> 0) + " cpl=" + cpl, LOG_CPU);
//}
if(interrupt_nr === 14)
{
dbg_log("int14 error_code=" + error_code + " cr2=" + h(cr2 >>> 0) + " prev=" + h(previous_ip >>> 0) + " cpl=" + cpl, LOG_CPU);
}
if(in_hlt)
@ -1426,6 +1455,7 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
if(flags & flag_vm)
{
dbg_log("return from vm86 mode", LOG_CPU);
flags &= ~flag_vm & ~flag_rf;
push32(sreg[reg_gs]);
@ -1680,14 +1710,15 @@ function test_privileges_for_io(port, size)
{
if(tsr_size >= 0x67)
{
var iomap_base = safe_read16(tsr_offset + 0x64 + 2),
var iomap_base = memory.read16(translate_address_system_read(tsr_offset + 0x64 + 2)),
high_port = port + size - 1;
if(tsr_size >= iomap_base + (high_port >> 3))
{
var mask = ((1 << size) - 1) << (port & 7),
addr = translate_address_system_read(tsr_offset + iomap_base + (port >> 3)),
port_info = (mask & 0xFF00) ?
safe_read16(port >> 3) : safe_read8(port >> 3);
memory.read16(addr) : memory.read8(addr);
if(!(port_info & mask))
{
@ -1750,7 +1781,7 @@ function cpuid()
}
else
{
if(DEBUG) throw "cpuid: unimplemented eax: " + h(id);
//if(DEBUG) throw "cpuid: unimplemented eax: " + h(id);
}
}
@ -2019,7 +2050,7 @@ function switch_seg(reg, selector)
if(!info.dc_bit && info.dpl < cpl)
{
throw unimpl("inter privilege interrupt");
throw unimpl("inter privilege call");
}
else
{
@ -2426,7 +2457,9 @@ function trigger_pagefault(write, user, present)
{
if(LOG_LEVEL & LOG_CPU)
{
//dbg_trace();
//dbg_log("page fault", LOG_CPU);
dbg_trace();
//throw "stop";
}
if(page_fault)

View file

@ -140,7 +140,7 @@ function HPET(dev)
}
}
dev.memory.mmap_register(HPET_ADDR, 0x4000, 4, mmio_read, mmio_write);
dev.io.mmap_register(HPET_ADDR, 0x4000, 4, mmio_read, mmio_write);

View file

@ -21,7 +21,7 @@ function IDEDevice(dev, buffer, is_cd, nr)
}
else
{
this.ata_port = 0x170;
this.ata_port = 0x1F0;
this.irq = 15;
}
@ -63,12 +63,8 @@ function IDEDevice(dev, buffer, is_cd, nr)
}
}
// 00:1f.2 IDE interface: Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller #1
//0x86, 0x80, 0x20, 0x3a, 0x05, 0x00, 0xb0, 0x02, 0x00, 0x8f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
//0x01, 0x90, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x81, 0x88, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00,
//0x81, 0x84, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x10, 0xd4, 0x82,
//0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00,
dev.pci.register_device([
this.pci_id = 0x1F << 3;
this.pci_space = [
0x86, 0x80, 0x20, 0x3a, 0x05, 0x00, 0xa0, 0x02, 0x00, 0x8f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
this.ata_port & 0xFF | 1, this.ata_port >> 8, 0x00, 0x00,
this.ata_port_high & 0xFF | 1, this.ata_port_high >> 8, 0x00, 0x00,
@ -78,8 +74,23 @@ function IDEDevice(dev, buffer, is_cd, nr)
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x43, 0x10, 0xd4, 0x82,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, this.irq, 0x02, 0x00, 0x00,
], 0x1f << 3);
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, this.irq, 0x00, 0x00, 0x00,
];
this.pci_bars = [
{
size: 8,
},
{
size: 4,
},
];
// 00:1f.2 IDE interface: Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller #1
//0x86, 0x80, 0x20, 0x3a, 0x05, 0x00, 0xb0, 0x02, 0x00, 0x8f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
//0x01, 0x90, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x81, 0x88, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00,
//0x81, 0x84, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x10, 0xd4, 0x82,
//0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00,
dev.pci.register_device(this);
// status
this.io.register_read(this.ata_port | 7, read_status);
@ -159,15 +170,16 @@ function IDEDevice(dev, buffer, is_cd, nr)
cylinder_low = transfered_ata_blocks >> 8;
cylinder_high = transfered_ata_blocks;
if(start + byte_count > buffer.byteLength)
if(start >= buffer.byteLength)
{
dbg_log("CD read: Outside of disk", LOG_DISK);
dbg_log("CD read: Outside of disk end=" + h(start + byte_count) + " size=" + h(buffer.byteLength), LOG_DISK);
status = 0xFF;
push_irq();
}
else
{
byte_count = Math.min(byte_count, buffer.byteLength - start);
status = 0xFF;
me.buffer.get(start, byte_count, function(data)
@ -189,14 +201,14 @@ function IDEDevice(dev, buffer, is_cd, nr)
if((data_pointer + 1) % (sectors_per_drq * 512) === 0 ||
data_pointer + 1 === pio_data.length)
{
if(data_pointer + 1 === pio_data.length)
{
status = 0x50;
bytecount = 3;
}
dbg_log("ATA IRQ", LOG_DISK);
push_irq();
//push_irq();
}
if(data_pointer + 1 >= pio_data.length)
{
status = 0x50;
bytecount = 3;
}
if((data_pointer + 1 & 255) === 0)
@ -310,7 +322,11 @@ function IDEDevice(dev, buffer, is_cd, nr)
break;
case 0x43:
// read header
pio_data = new Uint8Array(Math.min(atapi_command[8], 4));
pio_data = new Uint8Array(2048);
pio_data[0] = 0;
pio_data[1] = 10;
pio_data[2] = 1;
pio_data[3] = 1;
status = 0x58;
data_pointer = 0;
bytecount = 2;

View file

@ -6,10 +6,9 @@
*
* @constructor
*/
function IO()
function IO(memory)
{
var a20_byte = 0,
me = this;
var me = this;
function get_port_description(addr)
{
@ -150,25 +149,61 @@ function IO()
write_callbacks[port_addr] = callback;
};
// should maybe be somewhere else?
this.register_read(0x92, function()
/**
* @param addr {number}
* @param size {number}
*
*/
this.mmap_register = function(addr, size, fn_size, read_func, write_func)
{
return a20_byte;
});
dbg_log("mmap_register addr=" + h(addr >>> 0, 8) + " size=" + h(size, 8) + " fn_size=" + fn_size, LOG_IO);
this.register_write(0x92, function(out_byte)
{
a20_byte = out_byte;
});
dbg_assert((addr & MMAP_BLOCK_SIZE - 1) === 0);
dbg_assert(size && (size & MMAP_BLOCK_SIZE - 1) === 0);
dbg_assert(fn_size === 1 || fn_size === 4);
if(DEBUG)
{
// use by linux for timing
this.register_write(0x80, function(out_byte)
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
for(; size > 0; aligned_addr++)
{
});
memory.memory_map_registered[aligned_addr] = fn_size;
memory.memory_map_read[aligned_addr] = do_read;
memory.memory_map_write[aligned_addr] = do_write;
size -= MMAP_BLOCK_SIZE;
}
function do_read(read_addr)
{
return read_func(read_addr - addr | 0);
}
function do_write(write_addr, value)
{
write_func(write_addr - addr | 0, value);
}
};
for(var i = 0; (i << MMAP_BLOCK_BITS) < memory_size; i++)
{
// avoid sparse arrays
memory.memory_map_read[i] = memory.memory_map_write[i] = undefined;
}
this.mmap_register(memory_size, 0x100000000 - memory_size, 1,
function(addr) {
// read outside of the memory size
addr += memory_size;
dbg_log("Read from unmapped memory space, addr=" + h(addr >>> 0, 8), LOG_IO);
return 0xFF;
},
function(addr, value) {
// write outside of the memory size
addr += memory_size;
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value, 2), LOG_IO);
});
// 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

View file

@ -111,82 +111,19 @@ function Memory(buffer, memory_size)
}
};
var
/**
* Arbritary value, the minimum number of bytes that can be mapped
* by one device. This might be spec'd somewhere ...
*
* @const
*/
MMAP_BLOCK_BITS = 14,
/** @const */
MMAP_BLOCK_SIZE = 1 << MMAP_BLOCK_BITS,
// this only supports a 32 bit address space
memory_map_registered = new Int8Array(1 << (32 - MMAP_BLOCK_BITS)),
// this only supports a 32 bit address space
var memory_map_registered = new Uint8Array(1 << (32 - MMAP_BLOCK_BITS)),
memory_map_read = [],
memory_map_write = [];
// managed by IO() in io.js
this.memory_map_registered = memory_map_registered;
this.memory_map_read = memory_map_read;
this.memory_map_write = memory_map_write;
dbg_assert((memory_size & MMAP_BLOCK_SIZE - 1) === 0);
/**
* @param addr {number}
* @param size {number}
*
*/
this.mmap_register = function(addr, size, fn_size, read_func, write_func)
{
dbg_log("mmap_register addr=" + h(addr >>> 0, 8) + " size=" + h(size, 8) + " fn_size=" + fn_size, LOG_IO);
dbg_assert((addr & MMAP_BLOCK_SIZE - 1) === 0);
dbg_assert(size && (size & MMAP_BLOCK_SIZE - 1) === 0);
dbg_assert(fn_size === 1 || fn_size === 4);
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
for(; size > 0; aligned_addr++)
{
memory_map_registered[aligned_addr] = fn_size;
memory_map_read[aligned_addr] = do_read;
memory_map_write[aligned_addr] = do_write;
size -= MMAP_BLOCK_SIZE;
}
function do_read(read_addr)
{
return read_func(read_addr - addr | 0);
}
function do_write(write_addr, value)
{
write_func(write_addr - addr | 0, value);
}
};
for(var i = 0; (i << MMAP_BLOCK_BITS) < memory_size; i++)
{
// avoid sparse arrays
memory_map_read[i] = memory_map_write[i] = undefined;
}
this.mmap_register(memory_size, 0x100000000 - memory_size, 1,
function(addr) {
// read outside of the memory size
addr += memory_size;
dbg_log("Read from unmapped memory space, addr=" + h(addr >>> 0, 8), LOG_IO);
return 0xFF;
},
function(addr, value) {
// write outside of the memory size
addr += memory_size;
dbg_log("Write to unmapped memory space, addr=" + h(addr >>> 0, 8) + " value=" + h(value, 2), LOG_IO);
});
function mmap_read8(addr)
{
return memory_map_read[addr >>> MMAP_BLOCK_BITS](addr);
@ -200,24 +137,27 @@ function Memory(buffer, memory_size)
function mmap_read32(addr)
{
var aligned_addr = addr >>> MMAP_BLOCK_BITS,
size = memory_map_registered[aligned_addr],
fn = memory_map_read[aligned_addr];
if(memory_map_registered[aligned_addr] === 4)
if(size & 4)
{
return fn(addr);
}
else
{
return fn(addr) | fn(addr + 1) << 8 | fn(addr + 2) << 16 | fn(addr + 3) << 24;
return fn(addr) | fn(addr + 1) << 8 |
fn(addr + 2) << 16 | fn(addr + 3) << 24;
}
}
function mmap_write32(addr, value)
{
var aligned_addr = addr >>> MMAP_BLOCK_BITS,
size = memory_map_registered[aligned_addr],
fn = memory_map_write[aligned_addr];
if(memory_map_registered[aligned_addr] === 4)
if(size & 4)
{
fn(addr, value);
}

View file

@ -22,16 +22,17 @@ function PCI(dev)
{
var
io = dev.io,
pci_data = new Uint8Array(4),
pci_addr = new Uint8Array(4),
pci_response = new Uint8Array(4),
pci_status = new Uint8Array(4),
pci_data32 = new Int32Array(pci_data.buffer),
pci_addr32 = new Int32Array(pci_addr.buffer),
pci_response32 = new Int32Array(pci_response.buffer),
pci_status32 = new Int32Array(pci_status.buffer),
pci = this;
this.devices = Array(0x10000);
var device_spaces = Array(0x10000),
devices = Array(0x10000);
/*
io.register_write(0xCF9, function(value)
@ -45,35 +46,26 @@ function PCI(dev)
}
});*/
function pci_write_byte(byte_pos, byte)
{
var bdf = pci_data[2] << 8 | pci_data[1],
addr = pci_data[0] & 0xFC;
//if(bdf === (7 << 3))
//{
// var device = me.devices[bdf];
// (new Uint8Array(device.buffer))[addr] = byte;
//}
}
io.register_write(PCI_CONFIG_DATA, function(out_byte)
{
dbg_log("PCI data0: " + h(out_byte, 2) + " addr=" + h(pci_data32[0] >>> 0), LOG_PCI);
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_data32[0] >>> 0), LOG_PCI);
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_data32[0] >>> 0), LOG_PCI);
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_data32[0] >>> 0), LOG_PCI);
dbg_log("PCI data3: " + h(out_byte, 2) + " addr=" + h(pci_addr32[0] >>> 0), LOG_PCI);
pci_write_byte(3, out_byte);
});
io.register_read(PCI_CONFIG_DATA, function()
@ -112,19 +104,19 @@ function PCI(dev)
io.register_write(PCI_CONFIG_ADDRESS, function(out_byte)
{
pci_data[0] = out_byte;
pci_addr[0] = out_byte;
});
io.register_write(PCI_CONFIG_ADDRESS | 1, function(out_byte)
{
pci_data[1] = out_byte;
pci_addr[1] = out_byte;
});
io.register_write(PCI_CONFIG_ADDRESS | 2, function(out_byte)
{
pci_data[2] = out_byte;
pci_addr[2] = out_byte;
});
io.register_write(PCI_CONFIG_ADDRESS | 3, function(out_byte)
{
pci_data[3] = out_byte;
pci_addr[3] = out_byte;
pci_query();
});
@ -136,25 +128,25 @@ function PCI(dev)
// Bit | .31 .0
// Fmt | EBBBBBBBBDDDDDFFFRRRRRR00
var bdf = pci_data[2] << 8 | pci_data[1],
addr = pci_data[0] & 0xFC,
var bdf = pci_addr[2] << 8 | pci_addr[1],
addr = pci_addr[0] & 0xFC,
devfn = bdf & 0xFF,
bus = bdf >> 8,
dev = bdf >> 3 & 0x1F,
fn = bdf & 7,
enabled = pci_data[3] >> 7;
enabled = pci_addr[3] >> 7;
dbg_line += " enabled=" + (enabled);
dbg_line += " bdf=" + h(bdf, 4);
dbg_line += " addr=" + h(addr, 2);
//dbg_log(dbg_line + " " + h(pci_data32[0] >>> 0, 8), LOG_PCI);
//dbg_log(dbg_line + " " + h(pci_addr32[0] >>> 0, 8), LOG_PCI);
var device = pci.devices[bdf];
var device = device_spaces[bdf];
if(device !== undefined)
{
dbg_log(dbg_line + " " + h(pci_data32[0] >>> 0, 8), LOG_PCI);
dbg_log(dbg_line + " " + h(pci_addr32[0] >>> 0, 8), LOG_PCI);
pci_status32[0] = 0x80000000 | 0;
@ -174,26 +166,97 @@ function PCI(dev)
}
}
this.register_device = function(device, device_id)
function pci_write_byte(byte_pos, byte)
{
var bdf = pci_addr[2] << 8 | pci_addr[1],
addr = pci_addr[0] & 0xFC;
var space = device_spaces[bdf],
device = devices[bdf];
if(space)
{
(new Uint8Array(space.buffer))[addr | byte_pos] = byte;
if(byte_pos === 3 && addr >= 0x10 && addr < 0x28)
{
var bar_nr = addr - 0x10 >> 2,
bar = device.pci_bars[bar_nr],
value = space[addr >> 2];
dbg_log("BAR" + bar_nr + " changed to " + h(space[addr >> 2] >>> 0) + " dev=" + h(bdf, 2), LOG_PCI);
if(bar)
{
dbg_assert(!(bar.size & bar.size - 1));
space[addr >> 2] = value & ~(bar.size - 1) | 3;
}
else
{
space[addr >> 2] = 0;
}
}
}
}
this.register_device = function(device)
{
dbg_assert(device.pci_id !== undefined);
dbg_assert(device.pci_space !== undefined);
dbg_assert(device.pci_bars !== undefined);
var device_id = device.pci_id;
dbg_log("PCI register bdf=" + h(device_id), LOG_PCI);
dbg_assert(!pci.devices[device_id]);
dbg_assert(device.length === 64);
dbg_assert(!devices[device_id]);
dbg_assert(device.pci_space.length === 64);
// convert bytewise notation from lspci to double words
pci.devices[device_id] = new Int32Array(new Uint8Array(device).buffer);
device_spaces[device_id] = new Int32Array(new Uint8Array(device.pci_space).buffer);
devices[device_id] = device;
};
// Some experimental PCI devices taken from my PC:
// 00:00.0 Host bridge: Intel Corporation 4 Series Chipset DRAM Controller (rev 02)
this.register_device([
0x86, 0x80, 0x20, 0x2e, 0x06, 0x00, 0x90, 0x20, 0x02, 0x00, 0x00, 0x06, 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, 0x43, 0x10, 0xd3, 0x82,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
], 0);
//var host_bridge = {
// pci_id: 0,
// pci_space: [
// 0x86, 0x80, 0x20, 0x2e, 0x06, 0x00, 0x90, 0x20, 0x02, 0x00, 0x00, 0x06, 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, 0x43, 0x10, 0xd3, 0x82,
// 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ],
// pci_bars: [],
//};
var host_bridge = {
pci_id: 0,
pci_space: [
// 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
0x86, 0x80, 0x37, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
],
pci_bars: [],
};
this.register_device(host_bridge);
var isa_bridge = {
pci_id: 1 << 3,
pci_space: [
// 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
0x86, 0x80, 0x00, 0x70, 0x07, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 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, 0x00, 0x00, 0x00, 0x00,
],
pci_bars: [],
};
this.register_device(isa_bridge);
// 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 90)
//this.register_device([

View file

@ -110,15 +110,22 @@ function VGAScreen(dev, adapter, vga_memory_size)
plane3;
// Experimental, could probably need some changes
// 01:00.0 VGA compatible controller: NVIDIA Corporation GT216 [GeForce GT 220] (rev a2)
dev.pci.register_device([
this.pci_space = [
0xde, 0x10, 0x20, 0x0a, 0x07, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x00,
0x08, 0x00, 0x00, 0xe0, 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, 0x0a, 0x01, 0x00, 0x00,
], 0x12 << 3);
];
this.pci_id = 0x12 << 3;
this.pci_bars = [
{
size: vga_memory_size,
},
];
dev.pci.register_device(this);
function init()
@ -147,8 +154,8 @@ function VGAScreen(dev, adapter, vga_memory_size)
screen.set_size_text(80, 25);
screen.update_cursor_scanline();
memory.mmap_register(0xA0000, 0x20000, 1, vga_memory_read, vga_memory_write);
memory.mmap_register(0xE0000000, vga_memory_size, 1, svga_memory_read, svga_memory_write);
io.mmap_register(0xA0000, 0x20000, 1, vga_memory_read, vga_memory_write);
io.mmap_register(0xE0000000, vga_memory_size, 1, svga_memory_read, svga_memory_write);
}
function vga_memory_read(addr)