00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00039 #include <genarch/acpi/acpi.h>
00040 #include <genarch/acpi/madt.h>
00041 #include <arch/bios/bios.h>
00042 #include <mm/as.h>
00043 #include <mm/page.h>
00044 #include <print.h>
00045
00046 #define RSDP_SIGNATURE "RSD PTR "
00047 #define RSDP_REVISION_OFFS 15
00048
00049 struct acpi_rsdp *acpi_rsdp = NULL;
00050 struct acpi_rsdt *acpi_rsdt = NULL;
00051 struct acpi_xsdt *acpi_xsdt = NULL;
00052
00053 struct acpi_signature_map signature_map[] = {
00054 { (__u8 *)"APIC", (void *) &acpi_madt, "Multiple APIC Description Table" }
00055 };
00056
00057 static int rsdp_check(__u8 *rsdp) {
00058 struct acpi_rsdp *r = (struct acpi_rsdp *) rsdp;
00059 __u8 sum = 0;
00060 int i;
00061
00062 for (i=0; i<20; i++)
00063 sum += rsdp[i];
00064
00065 if (sum)
00066 return 0;
00067
00068 if (r->revision == 0)
00069 return 1;
00070
00071 for (; i<r->length; i++)
00072 sum += rsdp[i];
00073
00074 return !sum;
00075
00076 }
00077
00078 int acpi_sdt_check(__u8 *sdt)
00079 {
00080 struct acpi_sdt_header *h = (struct acpi_sdt_header *) sdt;
00081 __u8 sum = 0;
00082 int i;
00083
00084 for (i=0; i<h->length; i++)
00085 sum += sdt[i];
00086
00087 return !sum;
00088 }
00089
00090 static void map_sdt(struct acpi_sdt_header *sdt)
00091 {
00092 page_mapping_insert(AS_KERNEL, (__address) sdt, (__address) sdt, PAGE_NOT_CACHEABLE);
00093 map_structure((__address) sdt, sdt->length);
00094 }
00095
00096 static void configure_via_rsdt(void)
00097 {
00098 int i, j, cnt = (acpi_rsdt->header.length - sizeof(struct acpi_sdt_header))/sizeof(__u32);
00099
00100 for (i=0; i<cnt; i++) {
00101 for (j=0; j<sizeof(signature_map)/sizeof(struct acpi_signature_map); j++) {
00102 struct acpi_sdt_header *h = (struct acpi_sdt_header *) (__native) acpi_rsdt->entry[i];
00103
00104 map_sdt(h);
00105 if (*((__u32 *) &h->signature[0])==*((__u32 *) &signature_map[j].signature[0])) {
00106 if (!acpi_sdt_check((__u8 *) h))
00107 goto next;
00108 *signature_map[j].sdt_ptr = h;
00109 printf("%#zx: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
00110 }
00111 }
00112 next:
00113 ;
00114 }
00115 }
00116
00117 static void configure_via_xsdt(void)
00118 {
00119 int i, j, cnt = (acpi_xsdt->header.length - sizeof(struct acpi_sdt_header))/sizeof(__u64);
00120
00121 for (i=0; i<cnt; i++) {
00122 for (j=0; j<sizeof(signature_map)/sizeof(struct acpi_signature_map); j++) {
00123 struct acpi_sdt_header *h = (struct acpi_sdt_header *) ((__address) acpi_rsdt->entry[i]);
00124
00125 map_sdt(h);
00126 if (*((__u32 *) &h->signature[0])==*((__u32 *) &signature_map[j].signature[0])) {
00127 if (!acpi_sdt_check((__u8 *) h))
00128 goto next;
00129 *signature_map[j].sdt_ptr = h;
00130 printf("%#zx: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
00131 }
00132 }
00133 next:
00134 ;
00135 }
00136
00137 }
00138
00139 void acpi_init(void)
00140 {
00141 __u8 *addr[2] = { NULL, (__u8 *) PA2KA(0xe0000) };
00142 int i, j, length[2] = { 1024, 128*1024 };
00143 __u64 *sig = (__u64 *) RSDP_SIGNATURE;
00144
00145
00146
00147
00148
00149
00150
00151 addr[0] = (__u8 *) PA2KA(ebda);
00152 for (i = (ebda ? 0 : 1); i < 2; i++) {
00153 for (j = 0; j < length[i]; j += 16) {
00154 if (*((__u64 *) &addr[i][j]) == *sig && rsdp_check(&addr[i][j])) {
00155 acpi_rsdp = (struct acpi_rsdp *) &addr[i][j];
00156 goto rsdp_found;
00157 }
00158 }
00159 }
00160
00161 return;
00162
00163 rsdp_found:
00164 printf("%#zx: ACPI Root System Description Pointer\n", acpi_rsdp);
00165
00166 acpi_rsdt = (struct acpi_rsdt *) (__native) acpi_rsdp->rsdt_address;
00167 if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((__address) acpi_rsdp->xsdt_address);
00168
00169 if (acpi_rsdt) map_sdt((struct acpi_sdt_header *) acpi_rsdt);
00170 if (acpi_xsdt) map_sdt((struct acpi_sdt_header *) acpi_xsdt);
00171
00172 if (acpi_rsdt && !acpi_sdt_check((__u8 *) acpi_rsdt)) {
00173 printf("RSDT: %s\n", "bad checksum");
00174 return;
00175 }
00176 if (acpi_xsdt && !acpi_sdt_check((__u8 *) acpi_xsdt)) {
00177 printf("XSDT: %s\n", "bad checksum");
00178 return;
00179 }
00180
00181 if (acpi_xsdt) configure_via_xsdt();
00182 else if (acpi_rsdt) configure_via_rsdt();
00183
00184 }
00185
00186