[SerialICE] New patch to review for serialice: eb43380 Add superio filtering
Kyösti Mälkki (kyosti.malkki@gmail.com)
gerrit at coreboot.org
Sun Oct 28 21:09:07 CET 2012
Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1647
-gerrit
commit eb43380a5a24737214e43f9200630ef96fdbcc79
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date: Sun Oct 28 11:32:48 2012 +0200
Add superio filtering
Decoder is able to pretty-print the config cycles to port 0x2e/0x4e
and activate new IO regions. One should provide a map of LDN functions
with the size of each IO region as part of the mainboard script.
Change-Id: I976f43818b43a30db97b4e679de04e399f691b97
Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
SerialICE/simba/serialice.lua | 11 ++
SerialICE/simba/superio.lua | 259 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 270 insertions(+)
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 4b63e25..3700589 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -34,6 +34,7 @@ hide_i8042_io = false
hide_i8237_io = true
hide_i8254_io = true
hide_i8259_io = true
+hide_superio_cfg = true
-- Set to "true" to log every memory and IO access
log_everything = false
@@ -43,6 +44,9 @@ log_everything = false
-- RTC registers 0x0-0xd go to HW
cache_nvram = false
+-- SMSC 0x07, Winbond 0x06 ?
+DEFAULT_SUPERIO_LDN_REGISTER = 0x07
+
rom_size = 4 * 1024 * 1024
rom_base = 0x100000000 - rom_size
@@ -59,6 +63,7 @@ dofile("memory.lua")
dofile("cpu.lua")
dofile("pci_cfg.lua")
dofile("pc80.lua")
+dofile("superio.lua")
function do_minimal_setup()
enable_hook(io_hooks, filter_io_fallback)
@@ -73,6 +78,12 @@ function do_default_setup()
enable_ram()
enable_hook(io_hooks, filter_pci_io_cfg)
enable_hook_pc80()
+ enable_hook_superio(0x2e, DEFAULT_SUPERIO_LDN_REGISTER)
+ enable_hook_superio(0x4e, DEFAULT_SUPERIO_LDN_REGISTER)
+ enable_hook(io_hooks, filter_com1)
+ if superio_initialization then
+ superio_initialization()
+ end
end
do_minimal_setup()
diff --git a/SerialICE/simba/superio.lua b/SerialICE/simba/superio.lua
new file mode 100644
index 0000000..1248af5
--- /dev/null
+++ b/SerialICE/simba/superio.lua
@@ -0,0 +1,259 @@
+
+
+function pnp_switch_ldn(f, data)
+ if not f.ldn[data] then
+ f.ldn[data] = { data = {}, set = {}, bar0 = {}, bar1 = {} }
+ end
+ f.pnp.active_ldn = data
+end
+
+function pnp_select_cfg(f, data)
+ f.pnp.reg = data
+end
+
+function pnp_store_cfg(f, data)
+ local reg = f.pnp.reg
+ if reg < 0x30 then
+ f.chip.data[reg] = data;
+ f.chip.set[reg] = true;
+ else
+ local ldn = f.pnp.active_ldn
+ f.ldn[ldn].data[reg] = data;
+ f.ldn[ldn].set[reg] = true;
+ end
+end
+
+
+-- **********************************************************
+--
+-- SuperIO device handling
+
+function superio_pnpdev(f)
+ return string.format("%s %02x:%02x", f.name, f.base, f.pnp.active_ldn)
+end
+
+function superio_dev_post(f, action)
+ if f.pnp.reg < 0x30 then
+ printk(f, action, "%02x: ", f.base)
+ else
+ printk(f, action, "%02x:%02x ", f.base, f.pnp.active_ldn)
+ end
+end
+
+function superio_register_post(f, action)
+ superio_dev_post(f, action)
+ if action.write then
+ printf("[%02x] <= %02x\n", f.pnp.reg, action.data)
+ else
+ printf("[%02x] => %02x\n", f.pnp.reg, action.data)
+ end
+end
+
+function superio_try_enable_io(f, idx)
+
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ if ldn.set[0x30] and ldn.data[0x30] ~= 0x0 then
+ if idx == 0 and ldn.set[0x60] and ldn.set[0x61] then
+ local iobase = bit32.bor(bit32.lshift(ldn.data[0x60], 8), ldn.data[0x61])
+ if not ldn.bar0.size then
+ ldn.bar0.size = 1
+ end
+ if not ldn.bar0.name then
+ ldn.bar0.name = superio_pnpdev(f)
+ end
+ ldn.bar0.val = iobase
+ generic_io_bar(ldn.bar0)
+ end
+ if idx == 1 and ldn.set[0x62] and ldn.set[0x63] then
+ local iobase = bit32.bor(bit32.lshift(ldn.data[0x62], 8), ldn.data[0x63])
+ if not ldn.bar1.size then
+ ldn.bar1.size = 1
+ end
+ if not ldn.bar1.name then
+ ldn.bar1.name = superio_pnpdev(f)
+ end
+ ldn.bar1.val = iobase
+ generic_io_bar(ldn.bar1)
+ end
+ end
+end
+
+function superio_try_enable_ldn(f, action)
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ if ldn.set[0x30] and ldn.data[0x30] == 0x0 then
+ superio_dev_post(f, action)
+ printf("disabled\n")
+ else
+ superio_dev_post(f, action)
+ printf("enabled\n")
+ end
+end
+
+function superio_pre(f, action)
+ if not action.write then
+ return handle_action(f, action)
+ end
+
+ if action.addr == f.base then
+ pnp_select_cfg(f, action.data)
+ return handle_action(f, action)
+ end
+
+ if action.addr == f.base + 0x01 then
+ -- Also creates new LDN instance, if necessary.
+ if f.pnp.reg == f.pnp.ldn_register then
+ pnp_switch_ldn(f, action.data)
+ end
+
+ pnp_store_cfg(f, action.data)
+
+ -- Don't allow that our SIO power gets disabled.
+ if f.pnp.reg == 0x02 then
+ return drop_action(f, action, 0)
+ end
+
+ -- Don't mess with oscillator setup.
+ if f.pnp.reg == 0x24 then
+ return drop_action(f, action, 0)
+ end
+ return handle_action(f, action)
+ end
+
+ -- should not reach here
+ return skip_filter(f, action)
+end
+
+function superio_post(f, action)
+
+ -- Do not log change of register or LDN.
+ if action.addr == f.base or f.pnp.reg == f.pnp.ldn_register then
+ return true
+ end
+
+ if not action.write then
+ superio_register_post(f, action)
+ return true
+ end
+
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ -- Log base address once both bytes are set.
+
+ if ( f.pnp.reg == 0x60 or f.pnp.reg == 0x61 ) then
+ superio_try_enable_io(f, 0)
+ return true
+ end
+
+ if ( f.pnp.reg == 0x62 or f.pnp.reg == 0x63 ) then
+ superio_try_enable_io(f, 1)
+ return true
+ end
+
+ if f.pnp.reg == 0x30 then
+ superio_try_enable_io(f, 0)
+ superio_try_enable_io(f, 1)
+ superio_try_enable_ldn(f, action)
+ return true
+ end
+
+ if f.pnp.reg == 0x70 then
+ superio_dev_post(f, action)
+ printf("irq = %d\n", ldn.data[0x70])
+ return true
+ end
+ if f.pnp.reg == 0x72 then
+ superio_dev_post(f, action)
+ printf("irq2 = %d\n", ldn.data[0x72])
+ return true
+ end
+
+ superio_register_post(f, action)
+ return true
+end
+
+
+filter_superio_2e = {
+ id = -1,
+ name = "PnP",
+ pre = superio_pre,
+ post = superio_post,
+ base = 0x2e,
+ size = 0x02,
+ hide = hide_superio_cfg,
+ chip = { data = {}, set = {} },
+ pnp = { reg = 0, active_ldn = -1, ldn_register = 0 },
+ ldn = {},
+}
+filter_superio_4e = {
+ id = -1,
+ name = "PnP",
+ pre = superio_pre,
+ post = superio_post,
+ base = 0x4e,
+ size = 0x02,
+ hide = hide_superio_cfg,
+ chip = { data = {}, set = {} },
+ pnp = { reg = 0, active_ldn = -1, ldn_register = 0 },
+ ldn = {},
+}
+
+
+function superio_get_filter(cfg_base)
+ if cfg_base == 0x2e then
+ return filter_superio_2e
+ elseif cfg_base == 0x4e then
+ return filter_superio_4e
+ else
+ return nil
+ end
+end
+
+function superio_set_ldn_register(f, ldn_register)
+ f.pnp.ldn_register = ldn_register
+end
+
+function superio_new_ldn(f, idx)
+ if not f.ldn[idx] then
+ f.ldn[idx] = { data = {}, set = {}, bar0 = {}, bar1 = {} }
+ end
+end
+
+function superio_ldn_iobase0(f, idx, name, size)
+ f.ldn[idx].bar0.name = name
+ f.ldn[idx].bar0.size = size
+end
+
+function superio_ldn_iobase1(f, idx, name, size)
+ f.ldn[idx].bar1.name = name
+ f.ldn[idx].bar1.size = size
+end
+
+function enable_hook_superio(base, ldn_register)
+ local sio = superio_get_filter(base)
+ superio_set_ldn_register(sio, ldn_register)
+ enable_hook(io_hooks, sio)
+end
+
+-- **********************************************************
+--
+-- Serial Port handling
+
+function com_pre(f, action)
+ if (action.write) then
+ return drop_action(f, action, action.data)
+ else
+ return drop_action(f, action, 0xff)
+ end
+end
+
+filter_com1 = {
+ id = -1,
+ name = "COM1",
+ pre = com_pre,
+ post = io_post,
+ base = 0x3f8,
+ size = 8,
+ hide = false,
+}
More information about the SerialICE
mailing list