aboutsummaryrefslogtreecommitdiff
path: root/util/x86emu/x86_interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/x86emu/x86_interrupts.c')
-rw-r--r--util/x86emu/x86_interrupts.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/util/x86emu/x86_interrupts.c b/util/x86emu/x86_interrupts.c
new file mode 100644
index 0000000000..c20c01725c
--- /dev/null
+++ b/util/x86emu/x86_interrupts.c
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2001 Ronald G. Minnich
+ * Copyright (C) 2005 Nick.Barker9@btinternet.com
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <string.h>
+#ifdef CONFIG_COREBOOT_V2
+#include <console/console.h>
+#include <arch/io.h>
+#define printk(x...) do_printk(x)
+#else
+#include <console.h>
+#include <io.h>
+#endif
+
+struct eregs {
+ uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+ uint32_t vector;
+ uint32_t error_code;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+};
+
+enum {
+ CHECK = 0xb001,
+ FINDDEV = 0xb102,
+ READCONFBYTE = 0xb108,
+ READCONFWORD = 0xb109,
+ READCONFDWORD = 0xb10a,
+ WRITECONFBYTE = 0xb10b,
+ WRITECONFWORD = 0xb10c,
+ WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS.
+enum {
+ PCIBIOS_NODEV = 0x8600,
+ PCIBIOS_BADREG = 0x8700
+};
+
+int int12_handler(struct eregs *regs)
+{
+ regs->eax = 64 * 1024;
+ return 0;
+}
+
+int int1a_handler(struct eregs *regs)
+{
+ unsigned short func = (unsigned short) regs->eax;
+ int retval = 0;
+ unsigned short devid, vendorid, devfn;
+ /* Use short to get rid of gabage in upper half of 32-bit register */
+ short devindex;
+ unsigned char bus;
+ struct device *dev;
+
+ switch(func) {
+ case CHECK:
+ regs->edx = 0x4350;
+ regs->ecx = 0x2049;
+ retval = 0;
+ break;
+ case FINDDEV:
+ {
+ devid = regs->ecx;
+ vendorid = regs->edx;
+ devindex = regs->esi;
+ dev = 0;
+#ifdef CONFIG_COREBOOT_V2
+ while ((dev = dev_find_device(vendorid, devid, dev))) {
+#else
+ while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
+#endif
+ if (devindex <= 0)
+ break;
+ devindex--;
+ }
+ if (dev) {
+ unsigned short busdevfn;
+ regs->eax = 0;
+ // busnum is an unsigned char;
+ // devfn is an int, so we mask it off.
+ busdevfn = (dev->bus->secondary << 8)
+ | (dev->path.pci.devfn & 0xff);
+ printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
+ regs->ebx = busdevfn;
+ retval = 0;
+ } else {
+ regs->eax = PCIBIOS_NODEV;
+ retval = -1;
+ }
+ }
+ break;
+ case READCONFDWORD:
+ case READCONFWORD:
+ case READCONFBYTE:
+ case WRITECONFDWORD:
+ case WRITECONFWORD:
+ case WRITECONFBYTE:
+ {
+ unsigned long dword;
+ unsigned short word;
+ unsigned char byte;
+ unsigned char reg;
+
+ devfn = regs->ebx & 0xff;
+ bus = regs->ebx >> 8;
+ reg = regs->edi;
+ dev = dev_find_slot(bus, devfn);
+ if (! dev) {
+ printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
+ // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
+ regs->eax = PCIBIOS_BADREG;
+ retval = -1;
+ }
+ switch(func) {
+ case READCONFBYTE:
+ byte = pci_read_config8(dev, reg);
+ regs->ecx = byte;
+ break;
+ case READCONFWORD:
+ word = pci_read_config16(dev, reg);
+ regs->ecx = word;
+ break;
+ case READCONFDWORD:
+ dword = pci_read_config32(dev, reg);
+ regs->ecx = dword;
+ break;
+ case WRITECONFBYTE:
+ byte = regs->ecx;
+ pci_write_config8(dev, reg, byte);
+ break;
+ case WRITECONFWORD:
+ word = regs->ecx;
+ pci_write_config16(dev, reg, word);
+ break;
+ case WRITECONFDWORD:
+ dword = regs->ecx;
+ pci_write_config32(dev, reg, dword);
+ break;
+ }
+
+ if (retval)
+ retval = PCIBIOS_BADREG;
+ printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
+ func, bus, devfn, reg, regs->ecx);
+ regs->eax = 0;
+ retval = 0;
+ }
+ break;
+ default:
+ printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
+ break;
+ }
+
+ return retval;
+}
+
+int int15_handler(struct eregs *regs)
+{
+ int res = -1;
+
+ /* This int15 handler is VIA Tech. specific. Other chipsets need other
+ * handlers. The right way to do this is to move this handler code into
+ * the mainboard or northbridge code.
+ */
+ switch (regs->eax & 0xffff) {
+ case 0x5f19:
+ break;
+ case 0x5f18:
+ regs->eax = 0x5f;
+ // MCLK = 133, 32M frame buffer, 256 M main memory
+ regs->ebx = 0x545;
+ regs->ecx = 0x060;
+ res = 0;
+ break;
+ case 0x5f00:
+ regs->eax = 0x8600;
+ break;
+ case 0x5f01:
+ regs->eax = 0x5f;
+ regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
+ res = 0;
+ break;
+ case 0x5f02:
+ regs->eax = 0x5f;
+ regs->ebx = (regs->ebx & 0xffff0000) | 2;
+ regs->ecx = (regs->ecx & 0xffff0000) | 0x401; // PAL + crt only
+ regs->edx = (regs->edx & 0xffff0000) | 0; // TV Layout - default
+ res = 0;
+ break;
+ case 0x5f0f:
+ regs->eax = 0x860f;
+ break;
+ /* And now Intel IGD code */
+#define BOOT_DISPLAY_CRT (1 << 0)
+#define BOOT_DISPLAY_TV (1 << 1)
+#define BOOT_DISPLAY_EFP (1 << 2)
+#define BOOT_DISPLAY_LCD (1 << 3)
+#define BOOT_DISPLAY_CRT2 (1 << 4)
+#define BOOT_DISPLAY_TV2 (1 << 5)
+#define BOOT_DISPLAY_EFP2 (1 << 6)
+#define BOOT_DISPLAY_LCD2 (1 << 7)
+
+ case 0x5f35:
+ regs->eax = 0x5f;
+ regs->ecx = BOOT_DISPLAY_LCD|BOOT_DISPLAY_CRT;
+ res = 0;
+ break;
+ case 0x5f40:
+ regs->eax = 0x5f;
+ regs->ecx = 3; // This is mainboard specific
+ printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
+ res = 0;
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n",
+ regs->eax & 0xffff);
+ }
+
+ return res;
+}
+