summaryrefslogtreecommitdiff
path: root/src/devices/emulator/pcbios
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/emulator/pcbios')
-rw-r--r--src/devices/emulator/pcbios/Config.lb1
-rw-r--r--src/devices/emulator/pcbios/pcibios.c142
-rw-r--r--src/devices/emulator/pcbios/pcibios.h24
3 files changed, 167 insertions, 0 deletions
diff --git a/src/devices/emulator/pcbios/Config.lb b/src/devices/emulator/pcbios/Config.lb
new file mode 100644
index 0000000000..231b6629b5
--- /dev/null
+++ b/src/devices/emulator/pcbios/Config.lb
@@ -0,0 +1 @@
+object pcibios.o \ No newline at end of file
diff --git a/src/devices/emulator/pcbios/pcibios.c b/src/devices/emulator/pcbios/pcibios.c
new file mode 100644
index 0000000000..74d25dc627
--- /dev/null
+++ b/src/devices/emulator/pcbios/pcibios.c
@@ -0,0 +1,142 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <x86emu/x86emu.h>
+
+#include "pcibios.h"
+
+int pcibios_handler()
+{
+ int i, ret = 0;
+ struct device *dev = 0;
+
+ printk_debug("%s AX = %x\n", __func__, X86_AX);
+
+ switch (X86_AX) {
+ case PCI_BIOS_PRESENT:
+ X86_AH = 0x00; /* no config space/special cycle support */
+ X86_AL = 0x01; /* config mechanism 1 */
+ X86_EDX = 'P' | 'C' << 8 | 'I' | ' ' << 24;
+ X86_EBX = 0x0210; /* Version 2.10 */
+ X86_ECX = 0xFF00; /* FixME: Max bus number */
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ break;
+ case FIND_PCI_DEVICE:
+ /* FixME: support SI != 0 */
+ dev = dev_find_device(X86_DX, X86_CX, dev);
+ if (dev != 0) {
+ X86_BH = dev->bus->secondary;
+ X86_BL = dev->path.u.pci.devfn;
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case FIND_PCI_CLASS_CODE:
+ /* FixME: support SI != 0 */
+ dev = dev_find_class(X86_ECX, dev);
+ if (dev != 0) {
+ X86_BH = dev->bus->secondary;
+ X86_BL = dev->path.u.pci.devfn;
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case READ_CONFIG_BYTE:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ X86_CL = pci_read_config8(dev, X86_DI);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case READ_CONFIG_WORD:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ X86_CX = pci_read_config16(dev, X86_DI);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case READ_CONFIG_DWORD:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ X86_ECX = pci_read_config32(dev, X86_DI);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case WRITE_CONFIG_BYTE:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ pci_write_config8(dev, X86_DI, X86_CL);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case WRITE_CONFIG_WORD:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ pci_write_config16(dev, X86_DI, X86_CX);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ case WRITE_CONFIG_DWORD:
+ dev = dev_find_slot(X86_BH, X86_BL);
+ if (dev != 0) {
+ pci_write_config16(dev, X86_DI, X86_ECX);
+ X86_AH = SUCCESSFUL;
+ X86_EFLAGS &= ~FB_CF; /* clear carry flag */
+ ret = 1;
+ } else {
+ X86_AH = DEVICE_NOT_FOUND;
+ X86_EFLAGS |= FB_CF; /* set carry flag */
+ ret = 0;
+ }
+ break;
+ default:
+ X86_AH = FUNC_NOT_SUPPORTED;
+ X86_EFLAGS |= FB_CF;
+ break;
+ }
+
+ return ret;
+}
diff --git a/src/devices/emulator/pcbios/pcibios.h b/src/devices/emulator/pcbios/pcibios.h
new file mode 100644
index 0000000000..d99bee695e
--- /dev/null
+++ b/src/devices/emulator/pcbios/pcibios.h
@@ -0,0 +1,24 @@
+enum {
+ PCI_BIOS_PRESENT = 0xB101,
+ FIND_PCI_DEVICE = 0xB102,
+ FIND_PCI_CLASS_CODE = 0xB103,
+ GENERATE_SPECIAL_CYCLE = 0xB106,
+ READ_CONFIG_BYTE = 0xB108,
+ READ_CONFIG_WORD = 0xB109,
+ READ_CONFIG_DWORD = 0xB10A,
+ WRITE_CONFIG_BYTE = 0xB10B,
+ WRITE_CONFIG_WORD = 0xB10C,
+ WRITE_CONFIG_DWORD = 0xB10D,
+ GET_IRQ_ROUTING_OPTIONS = 0xB10E,
+ SET_PCI_IRQ = 0xB10F
+};
+
+enum {
+ SUCCESSFUL = 0x00,
+ FUNC_NOT_SUPPORTED = 0x81,
+ BAD_VENDOR_ID = 0x83,
+ DEVICE_NOT_FOUND = 0x86,
+ BAD_REGISTER_NUMBER = 0x87,
+ SET_FAILED = 0x88,
+ BUFFER_TOO_SMALL = 0x89
+};