Change license from GPLv3 to LGPLv3.
[seabios.git] / src / pcibios.c
index 545ad8dd59817743131028fbdf6a4e39d4ee753c..0dafcf11de4865c790834313db14b00bad9d69cb 100644 (file)
@@ -3,13 +3,14 @@
 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
-// This file may be distributed under the terms of the GNU GPLv3 license.
+// This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "types.h" // u32
 #include "util.h" // handle_1ab1
 #include "pci.h" // pci_config_readl
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_EBDA
+#include "pci_regs.h" // PCI_VENDOR_ID
 
 #define RET_FUNC_NOT_SUPPORTED 0x81
 #define RET_BAD_VENDOR_ID      0x83
 static void
 handle_1ab101(struct bregs *regs)
 {
-    regs->ax = 0x0001;
-    regs->bx = 0x0210;
-    regs->cx = 0;
-    // XXX - regs->cl should equal max bus number.
+    // Find max bus.
+    int bdf, max;
+    foreachpci(bdf, max) {
+    }
+
+    regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
+    regs->bx = 0x0210; // PCI version 2.10
+    regs->cl = pci_bdf_to_bus(max - 1);
     regs->edx = 0x20494350; // "PCI "
     // XXX - bochs bios code sets edi to point to 32bit code - but no
     // reference to this in spec.
-    set_success(regs);
+    set_code_success(regs);
 }
 
 // find pci device
 static void
 handle_1ab102(struct bregs *regs)
 {
-    PCIDevice d;
-    int ret = pci_find_device(regs->dx, regs->cx, regs->si, &d);
-    if (ret) {
-        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+    u32 id = (regs->cx << 16) | regs->dx;
+    int count = regs->si;
+    int bdf, max;
+    foreachpci(bdf, max) {
+        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
+        if (v != id)
+            continue;
+        if (count--)
+            continue;
+        regs->bx = bdf;
+        set_code_success(regs);
         return;
     }
-    regs->bh = d.bus;
-    regs->bl = d.devfn;
-    set_code_success(regs);
+    set_code_fail(regs, RET_DEVICE_NOT_FOUND);
 }
 
 // find class code
 static void
 handle_1ab103(struct bregs *regs)
 {
-    PCIDevice d;
-    int ret = pci_find_class(regs->ecx, regs->si, &d);
-    if (ret) {
-        set_code_fail(regs, RET_DEVICE_NOT_FOUND);
+    int count = regs->si;
+    u32 classprog = regs->ecx;
+    int bdf, max;
+    foreachpci(bdf, max) {
+        u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
+        if ((v>>8) != classprog)
+            continue;
+        if (count--)
+            continue;
+        regs->bx = bdf;
+        set_code_success(regs);
         return;
     }
-    regs->bh = d.bus;
-    regs->bl = d.devfn;
-    set_code_success(regs);
+    set_code_fail(regs, RET_DEVICE_NOT_FOUND);
 }
 
 // read configuration byte
 static void
 handle_1ab108(struct bregs *regs)
 {
-    regs->cl = pci_config_readb(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->cl = pci_config_readb(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -72,7 +87,7 @@ handle_1ab108(struct bregs *regs)
 static void
 handle_1ab109(struct bregs *regs)
 {
-    regs->cx = pci_config_readw(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->cx = pci_config_readw(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -80,7 +95,7 @@ handle_1ab109(struct bregs *regs)
 static void
 handle_1ab10a(struct bregs *regs)
 {
-    regs->ecx = pci_config_readl(pci_bd(regs->bh, regs->bl), regs->di);
+    regs->ecx = pci_config_readl(regs->bx, regs->di);
     set_code_success(regs);
 }
 
@@ -88,7 +103,7 @@ handle_1ab10a(struct bregs *regs)
 static void
 handle_1ab10b(struct bregs *regs)
 {
-    pci_config_writeb(pci_bd(regs->bh, regs->bl), regs->di, regs->cl);
+    pci_config_writeb(regs->bx, regs->di, regs->cl);
     set_code_success(regs);
 }
 
@@ -96,7 +111,7 @@ handle_1ab10b(struct bregs *regs)
 static void
 handle_1ab10c(struct bregs *regs)
 {
-    pci_config_writew(pci_bd(regs->bh, regs->bl), regs->di, regs->cx);
+    pci_config_writew(regs->bx, regs->di, regs->cx);
     set_code_success(regs);
 }
 
@@ -104,7 +119,7 @@ handle_1ab10c(struct bregs *regs)
 static void
 handle_1ab10d(struct bregs *regs)
 {
-    pci_config_writel(pci_bd(regs->bh, regs->bl), regs->di, regs->ecx);
+    pci_config_writel(regs->bx, regs->di, regs->ecx);
     set_code_success(regs);
 }
 
@@ -112,15 +127,15 @@ handle_1ab10d(struct bregs *regs)
 static void
 handle_1ab10e(struct bregs *regs)
 {
-    struct pir_header *pirtable_far = (struct pir_header*)GET_EBDA(pir_loc);
-    if (! pirtable_far) {
+    struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0);
+    if (! pirtable_g) {
         set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
         return;
     }
 
     // Validate and update size.
     u16 size = GET_FARVAR(regs->es, *(u16*)(regs->di+0));
-    u16 pirsize = (GET_FARPTR(pirtable_far->size)
+    u16 pirsize = (GET_GLOBAL(pirtable_g->size)
                    - sizeof(struct pir_header));
     SET_FARVAR(regs->es, *(u16*)(regs->di+0), pirsize);
     if (size < pirsize) {
@@ -133,10 +148,12 @@ handle_1ab10e(struct bregs *regs)
     u16 destseg = GET_FARVAR(regs->es, *(u16*)(regs->di+4));
 
     // Memcpy pir table slots to dest buffer.
-    memcpy(MAKE_FARPTR(destseg, d), pirtable_far, pirsize);
+    memcpy_far(MAKE_FARPTR(destseg, d)
+               , MAKE_FARPTR(SEG_BIOS, pirtable_g)
+               , pirsize);
 
     // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
-    regs->bx = GET_FARPTR(pirtable_far->exclusive_irqs);
+    regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs);
     set_code_success(regs);
 }