Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1646
-gerrit
commit dfdca1655cd73597ed71cbb21b9b04e33798934f Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Sun Oct 28 11:13:35 2012 +0200
Add legacy PC80 devices in IO space
These devices appear at fixed IO addresses and are mostly implemented in the southbridge chip.
Change-Id: I4a20058e0cbc31f1b5777fe99966c0499909a553 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- SerialICE/simba/pc80.lua | 546 ++++++++++++++++++++++++++++++++++++++++++ SerialICE/simba/serialice.lua | 11 + 2 files changed, 557 insertions(+)
diff --git a/SerialICE/simba/pc80.lua b/SerialICE/simba/pc80.lua new file mode 100644 index 0000000..7ce439c --- /dev/null +++ b/SerialICE/simba/pc80.lua @@ -0,0 +1,546 @@ +-- ********************************************************** +-- +-- Debug POST port at IO 0x80 + +function debugport_post(f, action) + if action.write then + printk(f, action, "*** %02x ***\n", action.data) + return true + end + return false +end + +filter_debugport = { + id = -1, + name = "POST", + pre = handle_action, + post = debugport_post, + hide = true, + base = 0x80, + size = 0x1 +} + + +-- ********************************************************** +-- +-- i8259 PIC + +function i8259_pre(f, action) + local master = (bit32.rshift(0x05, action.addr) == 0x1) + local slave = (bit32.rshift(0x05, action.addr) == 0x5) + local reg = bit32.band(0x03, action.addr) + if reg == 0 or reg == 1 then + return handle_action(f, action) + end + return skip_filter(f, action) +end + +function i8259_post(f,action) + local reg = bit32.band(0x03, action.addr) + if reg == 0 or reg == 1 then + return true + end + return false +end + +function i8259_edge_pre(f, action) + return handle_action(f, action) +end + +function i8259_edge_post(f,action) + return true +end + +filter_i8259_master = { + id = -1, + name = "i8259 A", + pre = i8259_pre, + post = i8259_post, + hide = hide_i8259_io, + base = 0x20, + size = 0x20 +} + +filter_i8259_slave = { + id = -1, + name = "i8259 B", + pre = i8259_pre, + post = i8259_post, + hide = hide_i8259_io, + base = 0xa0, + size = 0x20 +} + +filter_i8259_edge = { + id = -1, + name = "i8259 C", + pre = i8259_edge_pre, + post = i8259_edge_post, + hide = hide_i8259_io, + base = 0x4d0, + size = 0x2 +} + +-- ********************************************************** +-- +-- i8237 DMA + +function i8237_pre(f, action) + if action.addr == 0x80 then + return skip_filter(f, action) + end + return handle_action(f, action) +end + +function i8237_post(f, action) + if action.addr == 0x80 then + return false + end + return true +end + + +filter_i8237_a = { + id = -1, + name = "i8237 A", + pre = i8237_pre, + post = i8237_post, + hide = hide_i8237_io, + base = 0x00, + size = 0x20 +} +filter_i8237_b = { + id = -1, + name = "i8237 B", + pre = i8237_pre, + post = i8237_post, + hide = hide_i8237_io, + base = 0x80, + size = 0x20 +} +filter_i8237_c = { + id = -1, + name = "i8237 C", + pre = i8237_pre, + post = i8237_post, + hide = hide_i8237_io, + base = 0xc0, + size = 0x20 +} + + +-- ********************************************************** +-- +-- i8254 IRQ0 and Speaker + +function i8254_pre(f, action) + + -- nothing to do on reads + if not action.write then + return handle_action(f, action) + end + + local reg = bit32.band(0x03, action.addr) + if reg >= 0x0 and reg < 0x03 then + local counter_n = 0 + local counter_p = 0 + if f.counter[reg].lsb then + f.counter[reg].lsb = f.counter[reg].after_lsb + counter_n = action.data + counter_p = bit32.band(0xff00, f.counter[reg].init) + else + counter_n = bit32.lshift(action.data, 8) + counter_p = bit32.band(0x00ff, f.counter[reg].init) + end + f.counter[reg].init = bit32.bor(counter_n, counter_p) + elseif reg == 0x03 then + local reg2 = bit32.rshift(action.data, 6) + local rwsel = bit32.band(0x3, bit32.rshift(action.data, 4)) + if reg2 == 0x3 then + if bit32.band(0x10, action.data) == 0 then + f.counter[0].readback = (bit32.band(0x2, action.data) ~= 0) + f.counter[1].readback = (bit32.band(0x4, action.data) ~= 0) + f.counter[2].readback = (bit32.band(0x8, action.data) ~= 0) + end + if bit32.band(0x20, action.data) == 0 then + f.counter[0].latch = (bit32.band(0x2, action.data) ~= 0) + f.counter[1].latch = (bit32.band(0x4, action.data) ~= 0) + f.counter[2].latch = (bit32.band(0x8, action.data) ~= 0) + end + elseif rwsel == 0x0 then + f.counter[reg2].latch = true + else + f.counter[reg2].mode = bit32.band(0xf, action.data) + if rwsel == 0x1 then + f.counter[reg2].lsb = true + f.counter[reg2].after_lsb = true + elseif rwsel == 0x2 then + f.counter[reg2].lsb = false + f.counter[reg2].after_lsb = false + elseif rwsel == 03 then + f.counter[reg2].lsb = true + f.counter[reg2].after_lsb = false + end + end + end + return handle_action(f, action) +end + +function i8254_post(f, action) + local reg = bit32.band(0x03, action.addr) + if reg >= 0x0 and reg < 0x03 then + if action.write then + local mode = bit32.band(0x0f, f.counter[reg].mode); + local modestr = "Mode" .. mode + if mode == 0x4 then + modestr = "Square Wave" + elseif mode == 0x6 then + modestr = "Rate Generator" + end + if bit32.band(0x01, mode) ~= 0 then + modestr = modestr .. " (BCD)" + end + + local period = 838 * f.counter[reg].init + if reg == 0 then + if period == 0 then + printk(f, action, "IRQ0 disabled\n") + else + printk(f, action, "IRQ0 (%s): %d ns\n", modestr, period) + end + elseif reg == 1 then + if period == 0 then + printk(f, action, "Refresh disabled\n") + else + printk(f, action, "Refresh (%s): %d ns\n", modestr, period) + end + elseif reg == 2 then + if period ~= 0 then + local spktone = 1193000 / f.counter[reg].init + printk(f, action, "Speaker Tone (%s): %d kHz\n", modestr, spktone) + end + end + else + if f.counter[reg].readback then + f.counter[reg].readback = false + f.counter[reg].status = action.data + printk(f, action, "[%d] status = %02x\n", reg, f.counter[reg].status) + end + if f.counter[reg].latch then + f.counter[reg].latch = false + f.counter[reg].current = action.data + printk(f, action, "[%d] current = %d\n", reg, f.counter[reg].current) + end + end + elseif reg == 0x03 then + end + return true +end + +i8254_counters = {} +i8254_counters[0x0] = { init=0, current=0, latch, readback, status=0 } +i8254_counters[0x1] = { init=0, current=0, latch, readback, status=0 } +i8254_counters[0x2] = { init=0, current=0, latch, readback, status=0 } + +filter_i8254_a = { + id = -1, + name = "i8254 A", + pre = i8254_pre, + post = i8254_post, + base = 0x40, + hide = hide_i8254_io, + size = 4, + counter = i8254_counters, +} +filter_i8254_b = { + id = -1, + name = "i8254 B", + pre = i8254_pre, + post = i8254_post, + base = 0x50, + hide = hide_i8254_io, + size = 4, + counter = i8254_counters, +} + + +-- ********************************************************** +-- +-- i8042 KBD, A20, Reset(?) + +function i8042_write(f, action) + if action.addr == 0x60 then + f.reg.data = action.data + f.reg.sts = bit32.band(f.reg.sts, 0xf7) + if (f.reg.cmd == 0xd1) then + f.reg.A20 = (bit32.band(0x02, action.data) == 0x02) + end + return handle_action(f, action) + end + if action.addr == 0x64 then + f.reg.cmd = action.data + f.reg.sts = bit32.bor(f.reg.sts, 0x0a) + return handle_action(f, action) + end + return skip_filter(f, action) +end + +function i8042_read(f, action) + if action.addr == 0x60 then + f.reg.sts = bit32.band(f.reg.sts, 0xfe) + return handle_action(f, action) + end + if action.addr == 0x64 then + return handle_action(f, action) + end + return skip_filter(f, action) +end + +function i8042_pre(f, action) + if (action.write) then + return i8042_write(f, action) + else + return i8042_read(f, action) + end +end + +function i8042_post(f, action) + if action.addr == 0x60 then + if action.write and f.reg.cmd == 0xd1 then + if f.reg.A20 then + printk(f, action, "A20 enabled\n") + else + printk(f, action, "A20 disabled\n") + end + end + return true + end + if action.addr == 0x64 then + return true + end + return false +end + +filter_i8042 = { + id = -1, + name = "i8042", + pre = i8042_pre, + post = i8042_post, + hide = hide_i8042_io, + base = 0x60, + size = 0x5, + reg = { data = 0, sts = 0, cmd = 0, A20 = 0 } +} + + +-- ********************************************************** +-- +-- CMOS nvram + + +function nvram_bank(addr) + if bit32.band(0xfe, addr) == 0x70 then + return 1 + elseif bit32.band(0xfe, addr) == 0x72 then + return 2 + elseif bit32.band(0xfe, addr) == 0x74 then + return 2 + else + return 0 + end +end + +function nvram_write(f, action) + local val = action.data + local rtc = false + local is_index = (bit32.band(0x01, action.addr) == 0x0) + local bank = nvram_bank(action.addr) + + if bank == 1 then + if is_index then + f.reg.p70 = bit32.band(0x7f, val) + if f.reg.p70 < 0x0E then + rtc = true + end + else + f.nvram_data[f.reg.p70] = val + f.nvram_set[f.reg.p70] = true + if f.reg.p70 < 0x0E then + rtc = true + end + end + elseif bank == 2 then + if is_index then + f.reg.p72 = bit32.band(0x7f, val) + else + local index = 0x80 + f.reg.p72 + f.nvram_data[index] = val + f.nvram_set[index] = true + end + end + if cache_nvram and not rtc then + return fake_action(f, action, val) + else + return handle_action(f, action) + end +end + +function nvram_read(f, action) + local val = 0 + local rtc = false + local is_index = (bit32.band(0x01, action.addr) == 0x0) + local bank = nvram_bank(action.addr) + + if bank == 1 then + if is_index then + -- NMI returned as 0 + val = f.reg.p70 + if f.reg.p70 < 0x0E then + rtc = true + end + else + if f.reg.p70 < 0x0E then + rtc = true + elseif f.nvram_set[f.reg.p70] then + val = f.nvram_data[f.reg.p70] + end + end + else -- bank + if is_index then + -- NMI returned as 0 + val = f.reg.p72 + else + local index = 0x80 + f.reg.p72 + if f.nvram_set[index] then + val = f.nvram_data[index] + end + end + end + if cache_nvram and not rtc then + return fake_action(f, action, val) + else + return handle_action(f, action) + end +end + +function nvram_pre(f, action) + if (action.write) then + return nvram_write(f, action) + else + return nvram_read(f, action) + end +end + +function nvram_post(f, action) + if bit32.band(0x01, action.addr) == 0x0 then + return true + end + + local bank = nvram_bank(action.addr) + if (action.write) then + if bank == 1 then + printk(f, action, "[%02x] <= %02x\n", f.reg.p70, action.data) + elseif bank == 2 then + printk(f, action, "[%02x] <= %02x\n", 0x80 + f.reg.p72, action.data) + end + else + if bank == 1 then + printk(f, action, "[%02x] => %02x\n", f.reg.p70, action.data) + elseif bank == 2 then + printk(f, action, "[%02x] => %02x\n", 0x80 + f.reg.p72, action.data) + end + end + return true +end + +filter_nvram = { + id = -1, + name = "NVram", + pre = nvram_pre, + post = nvram_post, + base = 0x70, + size = 8, + hide = hide_nvram_io, + reg = { p70 = 0, p72 = 0 }, + nvram_data = {}, + nvram_set = {}, +} + + +-- ********************************************************** +-- +-- Reset at 0xcf9 + +function sys_rst_pre(f, action) + if action.size == 1 then + if action.write and bit32.band(action.data, 0x04) == 0x04 then + SerialICE_system_reset() + end + return handle_action(f, action) + end + return skip_filter(f, action) +end + +function sys_rst_post(f, action) + if action.size == 1 then + if action.write then + printk(f, action, "Control = %02x\n", action.data) + return true + end + end + return false +end + +filter_reset = { + id = -1, + name = "Reset", + pre = sys_rst_pre, + post = sys_rst_post, + hide = false, + base = 0xcf9, + size = 1 +} + +-- ********************************************************** +-- +-- VGA io + +function vga_io_pre(f, action) + return skip_filter(f, action) +end + +function vga_io_post(f, action) + return true +end + +filter_vga_io = { + id = -1, + name = "VGA", + pre = vga_io_pre, + post = vga_io_post, + hide = false, + base = 0x3c0, + size = 0x20, +} + + +-- ********************************************************** +-- +-- Enable all PC80 stuff + +function enable_hook_pc80() + enable_hook(io_hooks, filter_i8237_a) + enable_hook(io_hooks, filter_i8237_b) + enable_hook(io_hooks, filter_i8237_c) + enable_hook(io_hooks, filter_i8259_master) + enable_hook(io_hooks, filter_i8259_slave) + enable_hook(io_hooks, filter_i8259_edge) + enable_hook(io_hooks, filter_i8042) + enable_hook(io_hooks, filter_i8254_a) + enable_hook(io_hooks, filter_i8254_b) + enable_hook(io_hooks, filter_reset) + enable_hook(io_hooks, filter_nvram) + enable_hook(io_hooks, filter_vga_io) + enable_hook(io_hooks, filter_debugport) +end + diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua index 5529068..4b63e25 100644 --- a/SerialICE/simba/serialice.lua +++ b/SerialICE/simba/serialice.lua @@ -29,11 +29,20 @@ io.write("SerialICE: Starting LUA script\n") hide_rom_access = true hide_pci_io_cfg = true hide_pci_mm_cfg = true +hide_nvram_io = true +hide_i8042_io = false +hide_i8237_io = true +hide_i8254_io = true +hide_i8259_io = true
-- Set to "true" to log every memory and IO access log_everything = false
+-- Use lua table for NVram +-- RTC registers 0x0-0xd go to HW +cache_nvram = false + rom_size = 4 * 1024 * 1024 rom_base = 0x100000000 - rom_size
@@ -49,6 +58,7 @@ dofile("core_io.lua") dofile("memory.lua") dofile("cpu.lua") dofile("pci_cfg.lua") +dofile("pc80.lua")
function do_minimal_setup() enable_hook(io_hooks, filter_io_fallback) @@ -62,6 +72,7 @@ end function do_default_setup() enable_ram() enable_hook(io_hooks, filter_pci_io_cfg) + enable_hook_pc80() end
do_minimal_setup()