acpi: Factor out SDT functions to locate specified SDT
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 24 Mar 2011 13:20:51 +0000 (21:20 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 25 Mar 2011 14:58:53 +0000 (22:58 +0800)
sys/platform/pc32/acpica5/acpi_madt.c
sys/platform/pc32/acpica5/acpi_sdt.c [new file with mode: 0644]
sys/platform/pc32/acpica5/acpi_sdt.h [new file with mode: 0644]
sys/platform/pc32/acpica5/acpi_sdt_var.h [new file with mode: 0644]
sys/platform/pc32/conf/files
sys/platform/pc64/acpica5/acpi_madt.c
sys/platform/pc64/acpica5/acpi_sdt.c [new file with mode: 0644]
sys/platform/pc64/acpica5/acpi_sdt.h [new file with mode: 0644]
sys/platform/pc64/acpica5/acpi_sdt_var.h [new file with mode: 0644]
sys/platform/pc64/conf/files

index 9183181..ba2a6ed 100644 (file)
 #include <machine/specialreg.h>
 #include <machine_base/apic/mpapic.h>
 
+#include "acpi_sdt.h"
+#include "acpi_sdt_var.h"
+
 #define MADT_VPRINTF(fmt, arg...) \
 do { \
        if (bootverbose) \
                kprintf("ACPI MADT: " fmt , ##arg); \
 } while (0)
 
-#define ACPI_RSDP_EBDA_MAPSZ   1024
-#define ACPI_RSDP_BIOS_MAPSZ   0x20000
-#define ACPI_RSDP_BIOS_MAPADDR 0xe0000
-
-#define ACPI_RSDP_ALIGN                16
-
-#define ACPI_RSDP_SIGLEN       8
-#define ACPI_RSDP_SIG          "RSD PTR "
-
-#define ACPI_SDTH_SIGLEN       4
-#define ACPI_RSDT_SIG          "RSDT"
-#define ACPI_XSDT_SIG          "XSDT"
-#define ACPI_MADT_SIG          "APIC"
-
-/* Root System Description Pointer */
-struct acpi_rsdp {
-       uint8_t                 rsdp_sig[ACPI_RSDP_SIGLEN];
-       uint8_t                 rsdp_cksum;
-       uint8_t                 rsdp_oem_id[6];
-       uint8_t                 rsdp_rev;
-       uint32_t                rsdp_rsdt;
-       uint32_t                rsdp_len;
-       uint64_t                rsdp_xsdt;
-       uint8_t                 rsdp_ext_cksum;
-       uint8_t                 rsdp_rsvd[3];
-} __packed;
-
-/* System Description Table Header */
-struct acpi_sdth {
-       uint8_t                 sdth_sig[ACPI_SDTH_SIGLEN];
-       uint32_t                sdth_len;
-       uint8_t                 sdth_rev;
-       uint8_t                 sdth_cksum;
-       uint8_t                 sdth_oem_id[6];
-       uint8_t                 sdth_oem_tbid[8];
-       uint32_t                sdth_oem_rev;
-       uint32_t                sdth_crt_id;
-       uint32_t                sdth_crt_rev;
-} __packed;
-
-/* Extended System Description Table */
-struct acpi_xsdt {
-       struct acpi_sdth        xsdt_hdr;
-       uint64_t                xsdt_ents[1];
-} __packed;
-
-/* Root System Description Table */
-struct acpi_rsdt {
-       struct acpi_sdth        rsdt_hdr;
-       uint32_t                rsdt_ents[1];
-} __packed;
-
 /* Multiple APIC Description Table */
 struct acpi_madt {
        struct acpi_sdth        madt_hdr;
@@ -170,15 +121,9 @@ struct acpi_madt_lapic_addr {
        uint64_t                mla_lapic_addr;
 } __packed;
 
-typedef        vm_paddr_t              (*madt_search_t)(vm_paddr_t);
 typedef int                    (*madt_iter_t)(void *,
                                    const struct acpi_madt_ent *);
 
-static const struct acpi_rsdp  *madt_rsdp_search(const uint8_t *, int);
-static void                    *madt_sdth_map(vm_paddr_t);
-static void                    madt_sdth_unmap(struct acpi_sdth *);
-static vm_paddr_t              madt_search_xsdt(vm_paddr_t);
-static vm_paddr_t              madt_search_rsdt(vm_paddr_t);
 static int                     madt_check(vm_paddr_t);
 static int                     madt_iterate_entries(struct acpi_madt *,
                                    madt_iter_t, void *);
@@ -193,61 +138,16 @@ static void                       madt_ioapic_enumerate(
                                    struct ioapic_enumerator *);
 static int                     madt_ioapic_probe(struct ioapic_enumerator *);
 
-extern u_long                  ebda_addr;
-
 static vm_paddr_t              madt_phyaddr;
 
 static void
 madt_probe(void)
 {
-       const struct acpi_rsdp *rsdp;
-       madt_search_t search;
-       vm_paddr_t search_paddr, madt_paddr;
-       vm_size_t mapsz;
-       uint8_t *ptr;
+       vm_paddr_t madt_paddr;
 
        KKASSERT(madt_phyaddr == 0);
 
-       if (ebda_addr != 0) {
-               mapsz = ACPI_RSDP_EBDA_MAPSZ;
-               ptr = pmap_mapdev(ebda_addr, mapsz);
-
-               rsdp = madt_rsdp_search(ptr, mapsz);
-               if (rsdp == NULL) {
-                       MADT_VPRINTF("RSDP not in EBDA\n");
-                       pmap_unmapdev((vm_offset_t)ptr, mapsz);
-
-                       ptr = NULL;
-                       mapsz = 0;
-               } else {
-                       MADT_VPRINTF("RSDP in EBDA\n");
-                       goto found_rsdp;
-               }
-       }
-
-       mapsz = ACPI_RSDP_BIOS_MAPSZ;
-       ptr = pmap_mapdev(ACPI_RSDP_BIOS_MAPADDR, mapsz);
-
-       rsdp = madt_rsdp_search(ptr, mapsz);
-       if (rsdp == NULL) {
-               kprintf("madt_probe: no RSDP\n");
-               pmap_unmapdev((vm_offset_t)ptr, mapsz);
-               return;
-       } else {
-               MADT_VPRINTF("RSDP in BIOS mem\n");
-       }
-
-found_rsdp:
-       if (rsdp->rsdp_rev != 2) {
-               search_paddr = rsdp->rsdp_rsdt;
-               search = madt_search_rsdt;
-       } else {
-               search_paddr = rsdp->rsdp_xsdt;
-               search = madt_search_xsdt;
-       }
-       pmap_unmapdev((vm_offset_t)ptr, mapsz);
-
-       madt_paddr = search(search_paddr);
+       madt_paddr = sdt_search(ACPI_MADT_SIG);
        if (madt_paddr == 0) {
                kprintf("madt_probe: can't locate MADT\n");
                return;
@@ -261,162 +161,7 @@ found_rsdp:
 
        madt_phyaddr = madt_paddr;
 }
-SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, madt_probe, 0);
-
-static const struct acpi_rsdp *
-madt_rsdp_search(const uint8_t *target, int size)
-{
-       const struct acpi_rsdp *rsdp;
-       int i;
-
-       KKASSERT(size > sizeof(*rsdp));
-
-       for (i = 0; i < size - sizeof(*rsdp); i += ACPI_RSDP_ALIGN) {
-               rsdp = (const struct acpi_rsdp *)&target[i];
-               if (memcmp(rsdp->rsdp_sig, ACPI_RSDP_SIG,
-                          ACPI_RSDP_SIGLEN) == 0)
-                       return rsdp;
-       }
-       return NULL;
-}
-
-static void *
-madt_sdth_map(vm_paddr_t paddr)
-{
-       struct acpi_sdth *sdth;
-       vm_size_t mapsz;
-
-       sdth = pmap_mapdev(paddr, sizeof(*sdth));
-       mapsz = sdth->sdth_len;
-       pmap_unmapdev((vm_offset_t)sdth, sizeof(*sdth));
-
-       if (mapsz < sizeof(*sdth))
-               return NULL;
-
-       return pmap_mapdev(paddr, mapsz);
-}
-
-static void
-madt_sdth_unmap(struct acpi_sdth *sdth)
-{
-       pmap_unmapdev((vm_offset_t)sdth, sdth->sdth_len);
-}
-
-static vm_paddr_t
-madt_search_xsdt(vm_paddr_t xsdt_paddr)
-{
-       struct acpi_xsdt *xsdt;
-       vm_paddr_t madt_paddr = 0;
-       int i, nent;
-
-       if (xsdt_paddr == 0) {
-               kprintf("madt_search_xsdt: XSDT paddr == 0\n");
-               return 0;
-       }
-
-       xsdt = madt_sdth_map(xsdt_paddr);
-       if (xsdt == NULL) {
-               kprintf("madt_search_xsdt: can't map XSDT\n");
-               return 0;
-       }
-
-       if (memcmp(xsdt->xsdt_hdr.sdth_sig, ACPI_XSDT_SIG,
-                  ACPI_SDTH_SIGLEN) != 0) {
-               kprintf("madt_search_xsdt: not XSDT\n");
-               goto back;
-       }
-
-       if (xsdt->xsdt_hdr.sdth_rev != 1) {
-               kprintf("madt_search_xsdt: unsupported XSDT revision %d\n",
-                       xsdt->xsdt_hdr.sdth_rev);
-               goto back;
-       }
-
-       nent = (xsdt->xsdt_hdr.sdth_len - sizeof(xsdt->xsdt_hdr)) /
-              sizeof(xsdt->xsdt_ents[0]);
-       for (i = 0; i < nent; ++i) {
-               struct acpi_sdth *sdth;
-
-               if (xsdt->xsdt_ents[i] == 0)
-                       continue;
-
-               sdth = madt_sdth_map(xsdt->xsdt_ents[i]);
-               if (sdth != NULL) {
-                       int ret;
-
-                       ret = memcmp(sdth->sdth_sig, ACPI_MADT_SIG,
-                                    ACPI_SDTH_SIGLEN);
-                       madt_sdth_unmap(sdth);
-
-                       if (ret == 0) {
-                               MADT_VPRINTF("MADT in XSDT\n");
-                               madt_paddr = xsdt->xsdt_ents[i];
-                               break;
-                       }
-               }
-       }
-back:
-       madt_sdth_unmap(&xsdt->xsdt_hdr);
-       return madt_paddr;
-}
-
-static vm_paddr_t
-madt_search_rsdt(vm_paddr_t rsdt_paddr)
-{
-       struct acpi_rsdt *rsdt;
-       vm_paddr_t madt_paddr = 0;
-       int i, nent;
-
-       if (rsdt_paddr == 0) {
-               kprintf("madt_search_rsdt: RSDT paddr == 0\n");
-               return 0;
-       }
-
-       rsdt = madt_sdth_map(rsdt_paddr);
-       if (rsdt == NULL) {
-               kprintf("madt_search_rsdt: can't map RSDT\n");
-               return 0;
-       }
-
-       if (memcmp(rsdt->rsdt_hdr.sdth_sig, ACPI_RSDT_SIG,
-                  ACPI_SDTH_SIGLEN) != 0) {
-               kprintf("madt_search_rsdt: not RSDT\n");
-               goto back;
-       }
-
-       if (rsdt->rsdt_hdr.sdth_rev != 1) {
-               kprintf("madt_search_rsdt: unsupported RSDT revision %d\n",
-                       rsdt->rsdt_hdr.sdth_rev);
-               goto back;
-       }
-
-       nent = (rsdt->rsdt_hdr.sdth_len - sizeof(rsdt->rsdt_hdr)) /
-              sizeof(rsdt->rsdt_ents[0]);
-       for (i = 0; i < nent; ++i) {
-               struct acpi_sdth *sdth;
-
-               if (rsdt->rsdt_ents[i] == 0)
-                       continue;
-
-               sdth = madt_sdth_map(rsdt->rsdt_ents[i]);
-               if (sdth != NULL) {
-                       int ret;
-
-                       ret = memcmp(sdth->sdth_sig, ACPI_MADT_SIG,
-                                    ACPI_SDTH_SIGLEN);
-                       madt_sdth_unmap(sdth);
-
-                       if (ret == 0) {
-                               MADT_VPRINTF("MADT in RSDT\n");
-                               madt_paddr = rsdt->rsdt_ents[i];
-                               break;
-                       }
-               }
-       }
-back:
-       madt_sdth_unmap(&rsdt->rsdt_hdr);
-       return madt_paddr;
-}
+SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0);
 
 static int
 madt_check(vm_paddr_t madt_paddr)
@@ -426,7 +171,7 @@ madt_check(vm_paddr_t madt_paddr)
 
        KKASSERT(madt_paddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = sdt_sdth_map(madt_paddr);
        KKASSERT(madt != NULL);
 
        /*
@@ -447,7 +192,7 @@ madt_check(vm_paddr_t madt_paddr)
                goto back;
        }
 back:
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -549,7 +294,7 @@ madt_lapic_pass1(void)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        MADT_VPRINTF("LAPIC address 0x%08x, flags %#x\n",
@@ -569,7 +314,7 @@ madt_lapic_pass1(void)
                lapic_addr = lapic_addr64;
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 
        return lapic_addr;
 }
@@ -615,7 +360,7 @@ madt_lapic_pass2(int bsp_apic_id)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -630,7 +375,7 @@ madt_lapic_pass2(int bsp_apic_id)
        KKASSERT(arg.cpu > 1);
        mp_naps = arg.cpu - 1; /* exclude BSP */
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 
        return 0;
 }
@@ -677,7 +422,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
        if (madt_phyaddr == 0)
                return ENXIO;
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -696,7 +441,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
                }
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -806,7 +551,7 @@ madt_ioapic_probe(struct ioapic_enumerator *e)
        if (madt_phyaddr == 0)
                return ENXIO;
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -823,7 +568,7 @@ madt_ioapic_probe(struct ioapic_enumerator *e)
                }
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -900,14 +645,14 @@ madt_ioapic_enumerate(struct ioapic_enumerator *e)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL);
        if (error)
                panic("madt_ioapic_enumerate failed\n");
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 }
 
 static struct ioapic_enumerator        madt_ioapic_enumerator = {
diff --git a/sys/platform/pc32/acpica5/acpi_sdt.c b/sys/platform/pc32/acpica5/acpi_sdt.c
new file mode 100644 (file)
index 0000000..64c2b9e
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sepherosa Ziehau <sepherosa@gmail.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+#include <machine_base/apic/mpapic.h>
+
+#include "acpi_sdt.h"
+#include "acpi_sdt_var.h"
+
+#define SDT_VPRINTF(fmt, arg...) \
+do { \
+       if (bootverbose) \
+               kprintf("ACPI SDT: " fmt , ##arg); \
+} while (0)
+
+#define ACPI_RSDP_EBDA_MAPSZ   1024
+#define ACPI_RSDP_BIOS_MAPSZ   0x20000
+#define ACPI_RSDP_BIOS_MAPADDR 0xe0000
+
+#define ACPI_RSDP_ALIGN                16
+
+#define ACPI_RSDP_SIGLEN       8
+#define ACPI_RSDP_SIG          "RSD PTR "
+
+/* Root System Description Pointer */
+struct acpi_rsdp {
+       uint8_t                 rsdp_sig[ACPI_RSDP_SIGLEN];
+       uint8_t                 rsdp_cksum;
+       uint8_t                 rsdp_oem_id[6];
+       uint8_t                 rsdp_rev;
+       uint32_t                rsdp_rsdt;
+       uint32_t                rsdp_len;
+       uint64_t                rsdp_xsdt;
+       uint8_t                 rsdp_ext_cksum;
+       uint8_t                 rsdp_rsvd[3];
+} __packed;
+
+/* Extended System Description Table */
+struct acpi_xsdt {
+       struct acpi_sdth        xsdt_hdr;
+       uint64_t                xsdt_ents[1];
+} __packed;
+
+/* Root System Description Table */
+struct acpi_rsdt {
+       struct acpi_sdth        rsdt_hdr;
+       uint32_t                rsdt_ents[1];
+} __packed;
+
+typedef        vm_paddr_t              (*sdt_search_t)(vm_paddr_t, const uint8_t *);
+
+static const struct acpi_rsdp  *sdt_rsdp_search(const uint8_t *, int);
+static vm_paddr_t              sdt_search_xsdt(vm_paddr_t, const uint8_t *);
+static vm_paddr_t              sdt_search_rsdt(vm_paddr_t, const uint8_t *);
+
+extern u_long                  ebda_addr;
+
+static sdt_search_t            sdt_search_func;
+static vm_paddr_t              sdt_search_paddr;
+
+static void
+sdt_probe(void)
+{
+       const struct acpi_rsdp *rsdp;
+       vm_size_t mapsz;
+       uint8_t *ptr;
+
+       if (ebda_addr != 0) {
+               mapsz = ACPI_RSDP_EBDA_MAPSZ;
+               ptr = pmap_mapdev(ebda_addr, mapsz);
+
+               rsdp = sdt_rsdp_search(ptr, mapsz);
+               if (rsdp == NULL) {
+                       SDT_VPRINTF("RSDP not in EBDA\n");
+                       pmap_unmapdev((vm_offset_t)ptr, mapsz);
+
+                       ptr = NULL;
+                       mapsz = 0;
+               } else {
+                       SDT_VPRINTF("RSDP in EBDA\n");
+                       goto found_rsdp;
+               }
+       }
+
+       mapsz = ACPI_RSDP_BIOS_MAPSZ;
+       ptr = pmap_mapdev(ACPI_RSDP_BIOS_MAPADDR, mapsz);
+
+       rsdp = sdt_rsdp_search(ptr, mapsz);
+       if (rsdp == NULL) {
+               kprintf("sdt_probe: no RSDP\n");
+               pmap_unmapdev((vm_offset_t)ptr, mapsz);
+               return;
+       } else {
+               SDT_VPRINTF("RSDP in BIOS mem\n");
+       }
+
+found_rsdp:
+       if (rsdp->rsdp_rev != 2) {
+               sdt_search_func = sdt_search_rsdt;
+               sdt_search_paddr = rsdp->rsdp_rsdt;
+       } else {
+               sdt_search_func = sdt_search_xsdt;
+               sdt_search_paddr = rsdp->rsdp_xsdt;
+       }
+       pmap_unmapdev((vm_offset_t)ptr, mapsz);
+}
+SYSINIT(sdt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, sdt_probe, 0);
+
+static const struct acpi_rsdp *
+sdt_rsdp_search(const uint8_t *target, int size)
+{
+       const struct acpi_rsdp *rsdp;
+       int i;
+
+       KKASSERT(size > sizeof(*rsdp));
+
+       for (i = 0; i < size - sizeof(*rsdp); i += ACPI_RSDP_ALIGN) {
+               rsdp = (const struct acpi_rsdp *)&target[i];
+               if (memcmp(rsdp->rsdp_sig, ACPI_RSDP_SIG,
+                          ACPI_RSDP_SIGLEN) == 0)
+                       return rsdp;
+       }
+       return NULL;
+}
+
+void *
+sdt_sdth_map(vm_paddr_t paddr)
+{
+       struct acpi_sdth *sdth;
+       vm_size_t mapsz;
+
+       sdth = pmap_mapdev(paddr, sizeof(*sdth));
+       mapsz = sdth->sdth_len;
+       pmap_unmapdev((vm_offset_t)sdth, sizeof(*sdth));
+
+       if (mapsz < sizeof(*sdth))
+               return NULL;
+
+       return pmap_mapdev(paddr, mapsz);
+}
+
+void
+sdt_sdth_unmap(struct acpi_sdth *sdth)
+{
+       pmap_unmapdev((vm_offset_t)sdth, sdth->sdth_len);
+}
+
+static vm_paddr_t
+sdt_search_xsdt(vm_paddr_t xsdt_paddr, const uint8_t *sig)
+{
+       struct acpi_xsdt *xsdt;
+       vm_paddr_t sdt_paddr = 0;
+       int i, nent;
+
+       if (xsdt_paddr == 0) {
+               kprintf("sdt_search_xsdt: XSDT paddr == 0\n");
+               return 0;
+       }
+
+       xsdt = sdt_sdth_map(xsdt_paddr);
+       if (xsdt == NULL) {
+               kprintf("sdt_search_xsdt: can't map XSDT\n");
+               return 0;
+       }
+
+       if (memcmp(xsdt->xsdt_hdr.sdth_sig, ACPI_XSDT_SIG,
+                  ACPI_SDTH_SIGLEN) != 0) {
+               kprintf("sdt_search_xsdt: not XSDT\n");
+               goto back;
+       }
+
+       if (xsdt->xsdt_hdr.sdth_rev != 1) {
+               kprintf("sdt_search_xsdt: unsupported XSDT revision %d\n",
+                       xsdt->xsdt_hdr.sdth_rev);
+               goto back;
+       }
+
+       nent = (xsdt->xsdt_hdr.sdth_len - sizeof(xsdt->xsdt_hdr)) /
+              sizeof(xsdt->xsdt_ents[0]);
+       for (i = 0; i < nent; ++i) {
+               struct acpi_sdth *sdth;
+
+               if (xsdt->xsdt_ents[i] == 0)
+                       continue;
+
+               sdth = sdt_sdth_map(xsdt->xsdt_ents[i]);
+               if (sdth != NULL) {
+                       int ret;
+
+                       ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN);
+                       sdt_sdth_unmap(sdth);
+
+                       if (ret == 0) {
+                               sdt_paddr = xsdt->xsdt_ents[i];
+                               break;
+                       }
+               }
+       }
+back:
+       sdt_sdth_unmap(&xsdt->xsdt_hdr);
+       return sdt_paddr;
+}
+
+static vm_paddr_t
+sdt_search_rsdt(vm_paddr_t rsdt_paddr, const uint8_t *sig)
+{
+       struct acpi_rsdt *rsdt;
+       vm_paddr_t sdt_paddr = 0;
+       int i, nent;
+
+       if (rsdt_paddr == 0) {
+               kprintf("sdt_search_rsdt: RSDT paddr == 0\n");
+               return 0;
+       }
+
+       rsdt = sdt_sdth_map(rsdt_paddr);
+       if (rsdt == NULL) {
+               kprintf("sdt_search_rsdt: can't map RSDT\n");
+               return 0;
+       }
+
+       if (memcmp(rsdt->rsdt_hdr.sdth_sig, ACPI_RSDT_SIG,
+                  ACPI_SDTH_SIGLEN) != 0) {
+               kprintf("sdt_search_rsdt: not RSDT\n");
+               goto back;
+       }
+
+       if (rsdt->rsdt_hdr.sdth_rev != 1) {
+               kprintf("sdt_search_rsdt: unsupported RSDT revision %d\n",
+                       rsdt->rsdt_hdr.sdth_rev);
+               goto back;
+       }
+
+       nent = (rsdt->rsdt_hdr.sdth_len - sizeof(rsdt->rsdt_hdr)) /
+              sizeof(rsdt->rsdt_ents[0]);
+       for (i = 0; i < nent; ++i) {
+               struct acpi_sdth *sdth;
+
+               if (rsdt->rsdt_ents[i] == 0)
+                       continue;
+
+               sdth = sdt_sdth_map(rsdt->rsdt_ents[i]);
+               if (sdth != NULL) {
+                       int ret;
+
+                       ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN);
+                       sdt_sdth_unmap(sdth);
+
+                       if (ret == 0) {
+                               sdt_paddr = rsdt->rsdt_ents[i];
+                               break;
+                       }
+               }
+       }
+back:
+       sdt_sdth_unmap(&rsdt->rsdt_hdr);
+       return sdt_paddr;
+}
+
+vm_paddr_t
+sdt_search(const uint8_t *sig)
+{
+       if (sdt_search_func == NULL)
+               return 0;
+       return sdt_search_func(sdt_search_paddr, sig);
+}
diff --git a/sys/platform/pc32/acpica5/acpi_sdt.h b/sys/platform/pc32/acpica5/acpi_sdt.h
new file mode 100644 (file)
index 0000000..02edcf9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sepherosa Ziehau <sepherosa@gmail.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ACPI_SDT_H_
+#define _ACPI_SDT_H_
+
+#define ACPI_SDTH_SIGLEN       4
+#define ACPI_RSDT_SIG          "RSDT"
+#define ACPI_XSDT_SIG          "XSDT"
+#define ACPI_MADT_SIG          "APIC"
+
+/* System Description Table Header */
+struct acpi_sdth {
+       uint8_t                 sdth_sig[ACPI_SDTH_SIGLEN];
+       uint32_t                sdth_len;
+       uint8_t                 sdth_rev;
+       uint8_t                 sdth_cksum;
+       uint8_t                 sdth_oem_id[6];
+       uint8_t                 sdth_oem_tbid[8];
+       uint32_t                sdth_oem_rev;
+       uint32_t                sdth_crt_id;
+       uint32_t                sdth_crt_rev;
+} __packed;
+
+#endif /* !_ACPI_SDT_H_ */
diff --git a/sys/platform/pc32/acpica5/acpi_sdt_var.h b/sys/platform/pc32/acpica5/acpi_sdt_var.h
new file mode 100644 (file)
index 0000000..2ca615c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ACPI_SDT_VAR_H_
+#define _ACPI_SDT_VAR_H_
+
+void           *sdt_sdth_map(vm_paddr_t);
+void           sdt_sdth_unmap(struct acpi_sdth *);
+
+vm_paddr_t     sdt_search(const uint8_t *);
+
+#endif /* !_ACPI_SDT_VAR_H_ */
index 17c370b..69263fd 100644 (file)
@@ -220,6 +220,7 @@ platform/pc32/i386/vm86.c           standard
 platform/pc32/i386/vm_machdep.c                standard
 platform/pc32/i386/cpufreq_machdep.c   standard
 platform/pc32/acpica5/acpi_madt.c      optional        smp
+platform/pc32/acpica5/acpi_sdt.c       optional        smp
 platform/pc32/isa/asc.c                        optional        asc
 platform/pc32/isa/clock.c              standard nowerror
 platform/pc32/isa/elcr.c               standard
index f386ee9..1dd1ef5 100644 (file)
 #include <machine/specialreg.h>
 #include <machine_base/apic/mpapic.h>
 
+#include "acpi_sdt.h"
+#include "acpi_sdt_var.h"
+
 #define MADT_VPRINTF(fmt, arg...) \
 do { \
        if (bootverbose) \
                kprintf("ACPI MADT: " fmt , ##arg); \
 } while (0)
 
-#define ACPI_RSDP_EBDA_MAPSZ   1024
-#define ACPI_RSDP_BIOS_MAPSZ   0x20000
-#define ACPI_RSDP_BIOS_MAPADDR 0xe0000
-
-#define ACPI_RSDP_ALIGN                16
-
-#define ACPI_RSDP_SIGLEN       8
-#define ACPI_RSDP_SIG          "RSD PTR "
-
-#define ACPI_SDTH_SIGLEN       4
-#define ACPI_RSDT_SIG          "RSDT"
-#define ACPI_XSDT_SIG          "XSDT"
-#define ACPI_MADT_SIG          "APIC"
-
-/* Root System Description Pointer */
-struct acpi_rsdp {
-       uint8_t                 rsdp_sig[ACPI_RSDP_SIGLEN];
-       uint8_t                 rsdp_cksum;
-       uint8_t                 rsdp_oem_id[6];
-       uint8_t                 rsdp_rev;
-       uint32_t                rsdp_rsdt;
-       uint32_t                rsdp_len;
-       uint64_t                rsdp_xsdt;
-       uint8_t                 rsdp_ext_cksum;
-       uint8_t                 rsdp_rsvd[3];
-} __packed;
-
-/* System Description Table Header */
-struct acpi_sdth {
-       uint8_t                 sdth_sig[ACPI_SDTH_SIGLEN];
-       uint32_t                sdth_len;
-       uint8_t                 sdth_rev;
-       uint8_t                 sdth_cksum;
-       uint8_t                 sdth_oem_id[6];
-       uint8_t                 sdth_oem_tbid[8];
-       uint32_t                sdth_oem_rev;
-       uint32_t                sdth_crt_id;
-       uint32_t                sdth_crt_rev;
-} __packed;
-
-/* Extended System Description Table */
-struct acpi_xsdt {
-       struct acpi_sdth        xsdt_hdr;
-       uint64_t                xsdt_ents[1];
-} __packed;
-
-/* Root System Description Table */
-struct acpi_rsdt {
-       struct acpi_sdth        rsdt_hdr;
-       uint32_t                rsdt_ents[1];
-} __packed;
-
 /* Multiple APIC Description Table */
 struct acpi_madt {
        struct acpi_sdth        madt_hdr;
@@ -170,15 +121,9 @@ struct acpi_madt_lapic_addr {
        uint64_t                mla_lapic_addr;
 } __packed;
 
-typedef        vm_paddr_t              (*madt_search_t)(vm_paddr_t);
 typedef int                    (*madt_iter_t)(void *,
                                    const struct acpi_madt_ent *);
 
-static const struct acpi_rsdp  *madt_rsdp_search(const uint8_t *, int);
-static void                    *madt_sdth_map(vm_paddr_t);
-static void                    madt_sdth_unmap(struct acpi_sdth *);
-static vm_paddr_t              madt_search_xsdt(vm_paddr_t);
-static vm_paddr_t              madt_search_rsdt(vm_paddr_t);
 static int                     madt_check(vm_paddr_t);
 static int                     madt_iterate_entries(struct acpi_madt *,
                                    madt_iter_t, void *);
@@ -193,61 +138,16 @@ static void                       madt_ioapic_enumerate(
                                    struct ioapic_enumerator *);
 static int                     madt_ioapic_probe(struct ioapic_enumerator *);
 
-extern u_long                  ebda_addr;
-
 static vm_paddr_t              madt_phyaddr;
 
 static void
 madt_probe(void)
 {
-       const struct acpi_rsdp *rsdp;
-       madt_search_t search;
-       vm_paddr_t search_paddr, madt_paddr;
-       vm_size_t mapsz;
-       uint8_t *ptr;
+       vm_paddr_t madt_paddr;
 
        KKASSERT(madt_phyaddr == 0);
 
-       if (ebda_addr != 0) {
-               mapsz = ACPI_RSDP_EBDA_MAPSZ;
-               ptr = pmap_mapdev(ebda_addr, mapsz);
-
-               rsdp = madt_rsdp_search(ptr, mapsz);
-               if (rsdp == NULL) {
-                       MADT_VPRINTF("RSDP not in EBDA\n");
-                       pmap_unmapdev((vm_offset_t)ptr, mapsz);
-
-                       ptr = NULL;
-                       mapsz = 0;
-               } else {
-                       MADT_VPRINTF("RSDP in EBDA\n");
-                       goto found_rsdp;
-               }
-       }
-
-       mapsz = ACPI_RSDP_BIOS_MAPSZ;
-       ptr = pmap_mapdev(ACPI_RSDP_BIOS_MAPADDR, mapsz);
-
-       rsdp = madt_rsdp_search(ptr, mapsz);
-       if (rsdp == NULL) {
-               kprintf("madt_probe: no RSDP\n");
-               pmap_unmapdev((vm_offset_t)ptr, mapsz);
-               return;
-       } else {
-               MADT_VPRINTF("RSDP in BIOS mem\n");
-       }
-
-found_rsdp:
-       if (rsdp->rsdp_rev != 2) {
-               search_paddr = rsdp->rsdp_rsdt;
-               search = madt_search_rsdt;
-       } else {
-               search_paddr = rsdp->rsdp_xsdt;
-               search = madt_search_xsdt;
-       }
-       pmap_unmapdev((vm_offset_t)ptr, mapsz);
-
-       madt_paddr = search(search_paddr);
+       madt_paddr = sdt_search(ACPI_MADT_SIG);
        if (madt_paddr == 0) {
                kprintf("madt_probe: can't locate MADT\n");
                return;
@@ -261,162 +161,7 @@ found_rsdp:
 
        madt_phyaddr = madt_paddr;
 }
-SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, madt_probe, 0);
-
-static const struct acpi_rsdp *
-madt_rsdp_search(const uint8_t *target, int size)
-{
-       const struct acpi_rsdp *rsdp;
-       int i;
-
-       KKASSERT(size > sizeof(*rsdp));
-
-       for (i = 0; i < size - sizeof(*rsdp); i += ACPI_RSDP_ALIGN) {
-               rsdp = (const struct acpi_rsdp *)&target[i];
-               if (memcmp(rsdp->rsdp_sig, ACPI_RSDP_SIG,
-                          ACPI_RSDP_SIGLEN) == 0)
-                       return rsdp;
-       }
-       return NULL;
-}
-
-static void *
-madt_sdth_map(vm_paddr_t paddr)
-{
-       struct acpi_sdth *sdth;
-       vm_size_t mapsz;
-
-       sdth = pmap_mapdev(paddr, sizeof(*sdth));
-       mapsz = sdth->sdth_len;
-       pmap_unmapdev((vm_offset_t)sdth, sizeof(*sdth));
-
-       if (mapsz < sizeof(*sdth))
-               return NULL;
-
-       return pmap_mapdev(paddr, mapsz);
-}
-
-static void
-madt_sdth_unmap(struct acpi_sdth *sdth)
-{
-       pmap_unmapdev((vm_offset_t)sdth, sdth->sdth_len);
-}
-
-static vm_paddr_t
-madt_search_xsdt(vm_paddr_t xsdt_paddr)
-{
-       struct acpi_xsdt *xsdt;
-       vm_paddr_t madt_paddr = 0;
-       int i, nent;
-
-       if (xsdt_paddr == 0) {
-               kprintf("madt_search_xsdt: XSDT paddr == 0\n");
-               return 0;
-       }
-
-       xsdt = madt_sdth_map(xsdt_paddr);
-       if (xsdt == NULL) {
-               kprintf("madt_search_xsdt: can't map XSDT\n");
-               return 0;
-       }
-
-       if (memcmp(xsdt->xsdt_hdr.sdth_sig, ACPI_XSDT_SIG,
-                  ACPI_SDTH_SIGLEN) != 0) {
-               kprintf("madt_search_xsdt: not XSDT\n");
-               goto back;
-       }
-
-       if (xsdt->xsdt_hdr.sdth_rev != 1) {
-               kprintf("madt_search_xsdt: unsupported XSDT revision %d\n",
-                       xsdt->xsdt_hdr.sdth_rev);
-               goto back;
-       }
-
-       nent = (xsdt->xsdt_hdr.sdth_len - sizeof(xsdt->xsdt_hdr)) /
-              sizeof(xsdt->xsdt_ents[0]);
-       for (i = 0; i < nent; ++i) {
-               struct acpi_sdth *sdth;
-
-               if (xsdt->xsdt_ents[i] == 0)
-                       continue;
-
-               sdth = madt_sdth_map(xsdt->xsdt_ents[i]);
-               if (sdth != NULL) {
-                       int ret;
-
-                       ret = memcmp(sdth->sdth_sig, ACPI_MADT_SIG,
-                                    ACPI_SDTH_SIGLEN);
-                       madt_sdth_unmap(sdth);
-
-                       if (ret == 0) {
-                               MADT_VPRINTF("MADT in XSDT\n");
-                               madt_paddr = xsdt->xsdt_ents[i];
-                               break;
-                       }
-               }
-       }
-back:
-       madt_sdth_unmap(&xsdt->xsdt_hdr);
-       return madt_paddr;
-}
-
-static vm_paddr_t
-madt_search_rsdt(vm_paddr_t rsdt_paddr)
-{
-       struct acpi_rsdt *rsdt;
-       vm_paddr_t madt_paddr = 0;
-       int i, nent;
-
-       if (rsdt_paddr == 0) {
-               kprintf("madt_search_rsdt: RSDT paddr == 0\n");
-               return 0;
-       }
-
-       rsdt = madt_sdth_map(rsdt_paddr);
-       if (rsdt == NULL) {
-               kprintf("madt_search_rsdt: can't map RSDT\n");
-               return 0;
-       }
-
-       if (memcmp(rsdt->rsdt_hdr.sdth_sig, ACPI_RSDT_SIG,
-                  ACPI_SDTH_SIGLEN) != 0) {
-               kprintf("madt_search_rsdt: not RSDT\n");
-               goto back;
-       }
-
-       if (rsdt->rsdt_hdr.sdth_rev != 1) {
-               kprintf("madt_search_rsdt: unsupported RSDT revision %d\n",
-                       rsdt->rsdt_hdr.sdth_rev);
-               goto back;
-       }
-
-       nent = (rsdt->rsdt_hdr.sdth_len - sizeof(rsdt->rsdt_hdr)) /
-              sizeof(rsdt->rsdt_ents[0]);
-       for (i = 0; i < nent; ++i) {
-               struct acpi_sdth *sdth;
-
-               if (rsdt->rsdt_ents[i] == 0)
-                       continue;
-
-               sdth = madt_sdth_map(rsdt->rsdt_ents[i]);
-               if (sdth != NULL) {
-                       int ret;
-
-                       ret = memcmp(sdth->sdth_sig, ACPI_MADT_SIG,
-                                    ACPI_SDTH_SIGLEN);
-                       madt_sdth_unmap(sdth);
-
-                       if (ret == 0) {
-                               MADT_VPRINTF("MADT in RSDT\n");
-                               madt_paddr = rsdt->rsdt_ents[i];
-                               break;
-                       }
-               }
-       }
-back:
-       madt_sdth_unmap(&rsdt->rsdt_hdr);
-       return madt_paddr;
-}
+SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0);
 
 static int
 madt_check(vm_paddr_t madt_paddr)
@@ -426,7 +171,7 @@ madt_check(vm_paddr_t madt_paddr)
 
        KKASSERT(madt_paddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = sdt_sdth_map(madt_paddr);
        KKASSERT(madt != NULL);
 
        /*
@@ -447,7 +192,7 @@ madt_check(vm_paddr_t madt_paddr)
                goto back;
        }
 back:
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -549,7 +294,7 @@ madt_lapic_pass1(void)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        MADT_VPRINTF("LAPIC address 0x%08x, flags %#x\n",
@@ -568,7 +313,7 @@ madt_lapic_pass1(void)
                lapic_addr = lapic_addr64;
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 
        return lapic_addr;
 }
@@ -614,7 +359,7 @@ madt_lapic_pass2(int bsp_apic_id)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -629,7 +374,7 @@ madt_lapic_pass2(int bsp_apic_id)
        KKASSERT(arg.cpu > 1);
        mp_naps = arg.cpu - 1; /* exclude BSP */
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 
        return 0;
 }
@@ -676,7 +421,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
        if (madt_phyaddr == 0)
                return ENXIO;
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -695,7 +440,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
                }
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -805,7 +550,7 @@ madt_ioapic_probe(struct ioapic_enumerator *e)
        if (madt_phyaddr == 0)
                return ENXIO;
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -822,7 +567,7 @@ madt_ioapic_probe(struct ioapic_enumerator *e)
                }
        }
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
        return error;
 }
 
@@ -899,14 +644,14 @@ madt_ioapic_enumerate(struct ioapic_enumerator *e)
 
        KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_phyaddr);
+       madt = sdt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL);
        if (error)
                panic("madt_ioapic_enumerate failed\n");
 
-       madt_sdth_unmap(&madt->madt_hdr);
+       sdt_sdth_unmap(&madt->madt_hdr);
 }
 
 static struct ioapic_enumerator        madt_ioapic_enumerator = {
diff --git a/sys/platform/pc64/acpica5/acpi_sdt.c b/sys/platform/pc64/acpica5/acpi_sdt.c
new file mode 100644 (file)
index 0000000..64c2b9e
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sepherosa Ziehau <sepherosa@gmail.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+#include <machine_base/apic/mpapic.h>
+
+#include "acpi_sdt.h"
+#include "acpi_sdt_var.h"
+
+#define SDT_VPRINTF(fmt, arg...) \
+do { \
+       if (bootverbose) \
+               kprintf("ACPI SDT: " fmt , ##arg); \
+} while (0)
+
+#define ACPI_RSDP_EBDA_MAPSZ   1024
+#define ACPI_RSDP_BIOS_MAPSZ   0x20000
+#define ACPI_RSDP_BIOS_MAPADDR 0xe0000
+
+#define ACPI_RSDP_ALIGN                16
+
+#define ACPI_RSDP_SIGLEN       8
+#define ACPI_RSDP_SIG          "RSD PTR "
+
+/* Root System Description Pointer */
+struct acpi_rsdp {
+       uint8_t                 rsdp_sig[ACPI_RSDP_SIGLEN];
+       uint8_t                 rsdp_cksum;
+       uint8_t                 rsdp_oem_id[6];
+       uint8_t                 rsdp_rev;
+       uint32_t                rsdp_rsdt;
+       uint32_t                rsdp_len;
+       uint64_t                rsdp_xsdt;
+       uint8_t                 rsdp_ext_cksum;
+       uint8_t                 rsdp_rsvd[3];
+} __packed;
+
+/* Extended System Description Table */
+struct acpi_xsdt {
+       struct acpi_sdth        xsdt_hdr;
+       uint64_t                xsdt_ents[1];
+} __packed;
+
+/* Root System Description Table */
+struct acpi_rsdt {
+       struct acpi_sdth        rsdt_hdr;
+       uint32_t                rsdt_ents[1];
+} __packed;
+
+typedef        vm_paddr_t              (*sdt_search_t)(vm_paddr_t, const uint8_t *);
+
+static const struct acpi_rsdp  *sdt_rsdp_search(const uint8_t *, int);
+static vm_paddr_t              sdt_search_xsdt(vm_paddr_t, const uint8_t *);
+static vm_paddr_t              sdt_search_rsdt(vm_paddr_t, const uint8_t *);
+
+extern u_long                  ebda_addr;
+
+static sdt_search_t            sdt_search_func;
+static vm_paddr_t              sdt_search_paddr;
+
+static void
+sdt_probe(void)
+{
+       const struct acpi_rsdp *rsdp;
+       vm_size_t mapsz;
+       uint8_t *ptr;
+
+       if (ebda_addr != 0) {
+               mapsz = ACPI_RSDP_EBDA_MAPSZ;
+               ptr = pmap_mapdev(ebda_addr, mapsz);
+
+               rsdp = sdt_rsdp_search(ptr, mapsz);
+               if (rsdp == NULL) {
+                       SDT_VPRINTF("RSDP not in EBDA\n");
+                       pmap_unmapdev((vm_offset_t)ptr, mapsz);
+
+                       ptr = NULL;
+                       mapsz = 0;
+               } else {
+                       SDT_VPRINTF("RSDP in EBDA\n");
+                       goto found_rsdp;
+               }
+       }
+
+       mapsz = ACPI_RSDP_BIOS_MAPSZ;
+       ptr = pmap_mapdev(ACPI_RSDP_BIOS_MAPADDR, mapsz);
+
+       rsdp = sdt_rsdp_search(ptr, mapsz);
+       if (rsdp == NULL) {
+               kprintf("sdt_probe: no RSDP\n");
+               pmap_unmapdev((vm_offset_t)ptr, mapsz);
+               return;
+       } else {
+               SDT_VPRINTF("RSDP in BIOS mem\n");
+       }
+
+found_rsdp:
+       if (rsdp->rsdp_rev != 2) {
+               sdt_search_func = sdt_search_rsdt;
+               sdt_search_paddr = rsdp->rsdp_rsdt;
+       } else {
+               sdt_search_func = sdt_search_xsdt;
+               sdt_search_paddr = rsdp->rsdp_xsdt;
+       }
+       pmap_unmapdev((vm_offset_t)ptr, mapsz);
+}
+SYSINIT(sdt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, sdt_probe, 0);
+
+static const struct acpi_rsdp *
+sdt_rsdp_search(const uint8_t *target, int size)
+{
+       const struct acpi_rsdp *rsdp;
+       int i;
+
+       KKASSERT(size > sizeof(*rsdp));
+
+       for (i = 0; i < size - sizeof(*rsdp); i += ACPI_RSDP_ALIGN) {
+               rsdp = (const struct acpi_rsdp *)&target[i];
+               if (memcmp(rsdp->rsdp_sig, ACPI_RSDP_SIG,
+                          ACPI_RSDP_SIGLEN) == 0)
+                       return rsdp;
+       }
+       return NULL;
+}
+
+void *
+sdt_sdth_map(vm_paddr_t paddr)
+{
+       struct acpi_sdth *sdth;
+       vm_size_t mapsz;
+
+       sdth = pmap_mapdev(paddr, sizeof(*sdth));
+       mapsz = sdth->sdth_len;
+       pmap_unmapdev((vm_offset_t)sdth, sizeof(*sdth));
+
+       if (mapsz < sizeof(*sdth))
+               return NULL;
+
+       return pmap_mapdev(paddr, mapsz);
+}
+
+void
+sdt_sdth_unmap(struct acpi_sdth *sdth)
+{
+       pmap_unmapdev((vm_offset_t)sdth, sdth->sdth_len);
+}
+
+static vm_paddr_t
+sdt_search_xsdt(vm_paddr_t xsdt_paddr, const uint8_t *sig)
+{
+       struct acpi_xsdt *xsdt;
+       vm_paddr_t sdt_paddr = 0;
+       int i, nent;
+
+       if (xsdt_paddr == 0) {
+               kprintf("sdt_search_xsdt: XSDT paddr == 0\n");
+               return 0;
+       }
+
+       xsdt = sdt_sdth_map(xsdt_paddr);
+       if (xsdt == NULL) {
+               kprintf("sdt_search_xsdt: can't map XSDT\n");
+               return 0;
+       }
+
+       if (memcmp(xsdt->xsdt_hdr.sdth_sig, ACPI_XSDT_SIG,
+                  ACPI_SDTH_SIGLEN) != 0) {
+               kprintf("sdt_search_xsdt: not XSDT\n");
+               goto back;
+       }
+
+       if (xsdt->xsdt_hdr.sdth_rev != 1) {
+               kprintf("sdt_search_xsdt: unsupported XSDT revision %d\n",
+                       xsdt->xsdt_hdr.sdth_rev);
+               goto back;
+       }
+
+       nent = (xsdt->xsdt_hdr.sdth_len - sizeof(xsdt->xsdt_hdr)) /
+              sizeof(xsdt->xsdt_ents[0]);
+       for (i = 0; i < nent; ++i) {
+               struct acpi_sdth *sdth;
+
+               if (xsdt->xsdt_ents[i] == 0)
+                       continue;
+
+               sdth = sdt_sdth_map(xsdt->xsdt_ents[i]);
+               if (sdth != NULL) {
+                       int ret;
+
+                       ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN);
+                       sdt_sdth_unmap(sdth);
+
+                       if (ret == 0) {
+                               sdt_paddr = xsdt->xsdt_ents[i];
+                               break;
+                       }
+               }
+       }
+back:
+       sdt_sdth_unmap(&xsdt->xsdt_hdr);
+       return sdt_paddr;
+}
+
+static vm_paddr_t
+sdt_search_rsdt(vm_paddr_t rsdt_paddr, const uint8_t *sig)
+{
+       struct acpi_rsdt *rsdt;
+       vm_paddr_t sdt_paddr = 0;
+       int i, nent;
+
+       if (rsdt_paddr == 0) {
+               kprintf("sdt_search_rsdt: RSDT paddr == 0\n");
+               return 0;
+       }
+
+       rsdt = sdt_sdth_map(rsdt_paddr);
+       if (rsdt == NULL) {
+               kprintf("sdt_search_rsdt: can't map RSDT\n");
+               return 0;
+       }
+
+       if (memcmp(rsdt->rsdt_hdr.sdth_sig, ACPI_RSDT_SIG,
+                  ACPI_SDTH_SIGLEN) != 0) {
+               kprintf("sdt_search_rsdt: not RSDT\n");
+               goto back;
+       }
+
+       if (rsdt->rsdt_hdr.sdth_rev != 1) {
+               kprintf("sdt_search_rsdt: unsupported RSDT revision %d\n",
+                       rsdt->rsdt_hdr.sdth_rev);
+               goto back;
+       }
+
+       nent = (rsdt->rsdt_hdr.sdth_len - sizeof(rsdt->rsdt_hdr)) /
+              sizeof(rsdt->rsdt_ents[0]);
+       for (i = 0; i < nent; ++i) {
+               struct acpi_sdth *sdth;
+
+               if (rsdt->rsdt_ents[i] == 0)
+                       continue;
+
+               sdth = sdt_sdth_map(rsdt->rsdt_ents[i]);
+               if (sdth != NULL) {
+                       int ret;
+
+                       ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN);
+                       sdt_sdth_unmap(sdth);
+
+                       if (ret == 0) {
+                               sdt_paddr = rsdt->rsdt_ents[i];
+                               break;
+                       }
+               }
+       }
+back:
+       sdt_sdth_unmap(&rsdt->rsdt_hdr);
+       return sdt_paddr;
+}
+
+vm_paddr_t
+sdt_search(const uint8_t *sig)
+{
+       if (sdt_search_func == NULL)
+               return 0;
+       return sdt_search_func(sdt_search_paddr, sig);
+}
diff --git a/sys/platform/pc64/acpica5/acpi_sdt.h b/sys/platform/pc64/acpica5/acpi_sdt.h
new file mode 100644 (file)
index 0000000..02edcf9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sepherosa Ziehau <sepherosa@gmail.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ACPI_SDT_H_
+#define _ACPI_SDT_H_
+
+#define ACPI_SDTH_SIGLEN       4
+#define ACPI_RSDT_SIG          "RSDT"
+#define ACPI_XSDT_SIG          "XSDT"
+#define ACPI_MADT_SIG          "APIC"
+
+/* System Description Table Header */
+struct acpi_sdth {
+       uint8_t                 sdth_sig[ACPI_SDTH_SIGLEN];
+       uint32_t                sdth_len;
+       uint8_t                 sdth_rev;
+       uint8_t                 sdth_cksum;
+       uint8_t                 sdth_oem_id[6];
+       uint8_t                 sdth_oem_tbid[8];
+       uint32_t                sdth_oem_rev;
+       uint32_t                sdth_crt_id;
+       uint32_t                sdth_crt_rev;
+} __packed;
+
+#endif /* !_ACPI_SDT_H_ */
diff --git a/sys/platform/pc64/acpica5/acpi_sdt_var.h b/sys/platform/pc64/acpica5/acpi_sdt_var.h
new file mode 100644 (file)
index 0000000..2ca615c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ACPI_SDT_VAR_H_
+#define _ACPI_SDT_VAR_H_
+
+void           *sdt_sdth_map(vm_paddr_t);
+void           sdt_sdth_unmap(struct acpi_sdth *);
+
+vm_paddr_t     sdt_search(const uint8_t *);
+
+#endif /* !_ACPI_SDT_VAR_H_ */
index c6453f3..c18215c 100644 (file)
@@ -199,6 +199,7 @@ platform/pc64/x86_64/console.c      standard
 platform/pc64/x86_64/ipl_funcs.c       standard
 kern/syscalls.c                        standard
 platform/pc64/x86_64/mp_machdep.c              optional        smp
+platform/pc64/acpica5/acpi_sdt.c       optional        smp
 platform/pc64/acpica5/acpi_madt.c      optional        smp
 dev/misc/atkbd/atkbd_isa.c             optional        atkbd
 dev/misc/atkbdc_layer/atkbdc_isa.c     optional        atkbdc