1433d6423SLionel Sambuc 2433d6423SLionel Sambuc #include <string.h> 3433d6423SLionel Sambuc 4433d6423SLionel Sambuc #include "kernel/kernel.h" 5433d6423SLionel Sambuc #include "acpi.h" 6433d6423SLionel Sambuc #include "arch_proto.h" 7433d6423SLionel Sambuc 8433d6423SLionel Sambuc typedef int ((* acpi_read_t)(phys_bytes addr, void * buff, size_t size)); 9433d6423SLionel Sambuc 10433d6423SLionel Sambuc struct acpi_rsdp acpi_rsdp; 11433d6423SLionel Sambuc 12433d6423SLionel Sambuc static acpi_read_t read_func; 13433d6423SLionel Sambuc 14433d6423SLionel Sambuc #define MAX_RSDT 35 /* ACPI defines 35 signatures */ 15433d6423SLionel Sambuc #define SLP_EN_CODE (1 << 13) /* ACPI SLP_EN_CODE code */ 16433d6423SLionel Sambuc #define AMI_PACKAGE_OP_CODE (0x12) 17433d6423SLionel Sambuc #define AMI_NAME_OP_CODE (0x8) 18433d6423SLionel Sambuc #define AMI_BYTE_PREFIX_CODE (0xA) 19433d6423SLionel Sambuc #define AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK (0xC0) 20433d6423SLionel Sambuc #define AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT (6) 21433d6423SLionel Sambuc #define AMI_MIN_PACKAGE_LENGTH (1) 22433d6423SLionel Sambuc #define AMI_NUM_ELEMENTS_LENGTH (1) 23433d6423SLionel Sambuc #define AMI_SLP_TYPA_SHIFT (10) 24433d6423SLionel Sambuc #define AMI_SLP_TYPB_SHIFT (10) 25433d6423SLionel Sambuc #define AMI_S5_NAME_OP_OFFSET_1 (-1) 26433d6423SLionel Sambuc #define AMI_S5_NAME_OP_OFFSET_2 (-2) 27433d6423SLionel Sambuc #define AMI_S5_PACKAGE_OP_OFFSET (4) 28433d6423SLionel Sambuc #define AMI_S5_PACKET_LENGTH_OFFSET (5) 29433d6423SLionel Sambuc 30433d6423SLionel Sambuc static struct acpi_rsdt { 31433d6423SLionel Sambuc struct acpi_sdt_header hdr; 32433d6423SLionel Sambuc u32_t data[MAX_RSDT]; 33433d6423SLionel Sambuc } rsdt; 34433d6423SLionel Sambuc 35433d6423SLionel Sambuc static struct { 36433d6423SLionel Sambuc char signature [ACPI_SDT_SIGNATURE_LEN + 1]; 37433d6423SLionel Sambuc size_t length; 38433d6423SLionel Sambuc } sdt_trans[MAX_RSDT]; 39433d6423SLionel Sambuc 40433d6423SLionel Sambuc static int sdt_count; 41433d6423SLionel Sambuc static u16_t pm1a_cnt_blk = 0; 42433d6423SLionel Sambuc static u16_t pm1b_cnt_blk = 0; 43433d6423SLionel Sambuc static u16_t slp_typa = 0; 44433d6423SLionel Sambuc static u16_t slp_typb = 0; 45433d6423SLionel Sambuc 46433d6423SLionel Sambuc static int acpi_check_csum(struct acpi_sdt_header * tb, size_t size) 47433d6423SLionel Sambuc { 48433d6423SLionel Sambuc u8_t total = 0; 49433d6423SLionel Sambuc int i; 50433d6423SLionel Sambuc for (i = 0; i < size; i++) 51433d6423SLionel Sambuc total += ((unsigned char *)tb)[i]; 52433d6423SLionel Sambuc return total == 0 ? 0 : -1; 53433d6423SLionel Sambuc } 54433d6423SLionel Sambuc 55433d6423SLionel Sambuc static int acpi_check_signature(const char * orig, const char * match) 56433d6423SLionel Sambuc { 57433d6423SLionel Sambuc return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN); 58433d6423SLionel Sambuc } 59433d6423SLionel Sambuc 60433d6423SLionel Sambuc static u32_t acpi_phys2vir(u32_t p) 61433d6423SLionel Sambuc { 62433d6423SLionel Sambuc if(!vm_running) { 63*da9af514SLionel Sambuc DEBUGEXTRA(("acpi: returning 0x%lx as vir addr\n", p)); 64433d6423SLionel Sambuc return p; 65433d6423SLionel Sambuc } 66433d6423SLionel Sambuc panic("acpi: can't get virtual address of arbitrary physical address"); 67433d6423SLionel Sambuc } 68433d6423SLionel Sambuc 69433d6423SLionel Sambuc static int acpi_phys_copy(phys_bytes phys, void *target, size_t len) 70433d6423SLionel Sambuc { 71433d6423SLionel Sambuc if(!vm_running) { 72433d6423SLionel Sambuc memcpy(target, (void *) phys, len); 73433d6423SLionel Sambuc return 0; 74433d6423SLionel Sambuc } 75433d6423SLionel Sambuc panic("can't acpi_phys_copy with vm"); 76433d6423SLionel Sambuc } 77433d6423SLionel Sambuc 78433d6423SLionel Sambuc static int acpi_read_sdt_at(phys_bytes addr, 79433d6423SLionel Sambuc struct acpi_sdt_header * tb, 80433d6423SLionel Sambuc size_t size, 81433d6423SLionel Sambuc const char * name) 82433d6423SLionel Sambuc { 83433d6423SLionel Sambuc struct acpi_sdt_header hdr; 84433d6423SLionel Sambuc 85433d6423SLionel Sambuc /* if NULL is supplied, we only return the size of the table */ 86433d6423SLionel Sambuc if (tb == NULL) { 87433d6423SLionel Sambuc if (read_func(addr, &hdr, sizeof(struct acpi_sdt_header))) { 88433d6423SLionel Sambuc printf("ERROR acpi cannot read %s header\n", name); 89433d6423SLionel Sambuc return -1; 90433d6423SLionel Sambuc } 91433d6423SLionel Sambuc 92433d6423SLionel Sambuc return hdr.length; 93433d6423SLionel Sambuc } 94433d6423SLionel Sambuc 95433d6423SLionel Sambuc if (read_func(addr, tb, sizeof(struct acpi_sdt_header))) { 96433d6423SLionel Sambuc printf("ERROR acpi cannot read %s header\n", name); 97433d6423SLionel Sambuc return -1; 98433d6423SLionel Sambuc } 99433d6423SLionel Sambuc 100433d6423SLionel Sambuc if (acpi_check_signature(tb->signature, name)) { 101433d6423SLionel Sambuc printf("ERROR acpi %s signature does not match\n", name); 102433d6423SLionel Sambuc return -1; 103433d6423SLionel Sambuc } 104433d6423SLionel Sambuc 105433d6423SLionel Sambuc if (size < tb->length) { 106433d6423SLionel Sambuc printf("ERROR acpi buffer too small for %s\n", name); 107433d6423SLionel Sambuc return -1; 108433d6423SLionel Sambuc } 109433d6423SLionel Sambuc 110433d6423SLionel Sambuc if (read_func(addr, tb, size)) { 111433d6423SLionel Sambuc printf("ERROR acpi cannot read %s\n", name); 112433d6423SLionel Sambuc return -1; 113433d6423SLionel Sambuc } 114433d6423SLionel Sambuc 115433d6423SLionel Sambuc if (acpi_check_csum(tb, tb->length)) { 116433d6423SLionel Sambuc printf("ERROR acpi %s checksum does not match\n", name); 117433d6423SLionel Sambuc return -1; 118433d6423SLionel Sambuc } 119433d6423SLionel Sambuc 120433d6423SLionel Sambuc return tb->length; 121433d6423SLionel Sambuc } 122433d6423SLionel Sambuc 123433d6423SLionel Sambuc phys_bytes acpi_get_table_base(const char * name) 124433d6423SLionel Sambuc { 125433d6423SLionel Sambuc int i; 126433d6423SLionel Sambuc 127433d6423SLionel Sambuc for(i = 0; i < sdt_count; i++) { 128433d6423SLionel Sambuc if (strncmp(name, sdt_trans[i].signature, 129433d6423SLionel Sambuc ACPI_SDT_SIGNATURE_LEN) == 0) 130433d6423SLionel Sambuc return (phys_bytes) rsdt.data[i]; 131433d6423SLionel Sambuc } 132433d6423SLionel Sambuc 133433d6423SLionel Sambuc return (phys_bytes) NULL; 134433d6423SLionel Sambuc } 135433d6423SLionel Sambuc 136433d6423SLionel Sambuc size_t acpi_get_table_length(const char * name) 137433d6423SLionel Sambuc { 138433d6423SLionel Sambuc int i; 139433d6423SLionel Sambuc 140433d6423SLionel Sambuc for(i = 0; i < sdt_count; i++) { 141433d6423SLionel Sambuc if (strncmp(name, sdt_trans[i].signature, 142433d6423SLionel Sambuc ACPI_SDT_SIGNATURE_LEN) == 0) 143433d6423SLionel Sambuc return sdt_trans[i].length; 144433d6423SLionel Sambuc } 145433d6423SLionel Sambuc 146433d6423SLionel Sambuc return 0; 147433d6423SLionel Sambuc } 148433d6423SLionel Sambuc 149433d6423SLionel Sambuc static void * acpi_madt_get_typed_item(struct acpi_madt_hdr * hdr, 150433d6423SLionel Sambuc unsigned char type, 151433d6423SLionel Sambuc unsigned idx) 152433d6423SLionel Sambuc { 153433d6423SLionel Sambuc u8_t * t, * end; 154433d6423SLionel Sambuc int i; 155433d6423SLionel Sambuc 156433d6423SLionel Sambuc t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr); 157433d6423SLionel Sambuc end = (u8_t *) hdr + hdr->hdr.length; 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc i = 0; 160433d6423SLionel Sambuc while(t < end) { 161433d6423SLionel Sambuc if (type == ((struct acpi_madt_item_hdr *) t)->type) { 162433d6423SLionel Sambuc if (i == idx) 163433d6423SLionel Sambuc return t; 164433d6423SLionel Sambuc else 165433d6423SLionel Sambuc i++; 166433d6423SLionel Sambuc } 167433d6423SLionel Sambuc t += ((struct acpi_madt_item_hdr *) t)->length; 168433d6423SLionel Sambuc } 169433d6423SLionel Sambuc 170433d6423SLionel Sambuc return NULL; 171433d6423SLionel Sambuc } 172433d6423SLionel Sambuc 173433d6423SLionel Sambuc #if 0 174433d6423SLionel Sambuc static void * acpi_madt_get_item(struct acpi_madt_hdr * hdr, 175433d6423SLionel Sambuc unsigned idx) 176433d6423SLionel Sambuc { 177433d6423SLionel Sambuc u8_t * t, * end; 178433d6423SLionel Sambuc int i; 179433d6423SLionel Sambuc 180433d6423SLionel Sambuc t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr); 181433d6423SLionel Sambuc end = (u8_t *) hdr + hdr->hdr.length; 182433d6423SLionel Sambuc 183433d6423SLionel Sambuc for(i = 0 ; i <= idx && t < end; i++) { 184433d6423SLionel Sambuc if (i == idx) 185433d6423SLionel Sambuc return t; 186433d6423SLionel Sambuc t += ((struct acpi_madt_item_hdr *) t)->length; 187433d6423SLionel Sambuc } 188433d6423SLionel Sambuc 189433d6423SLionel Sambuc return NULL; 190433d6423SLionel Sambuc } 191433d6423SLionel Sambuc #endif 192433d6423SLionel Sambuc 193433d6423SLionel Sambuc static int acpi_rsdp_test(void * buff) 194433d6423SLionel Sambuc { 195433d6423SLionel Sambuc struct acpi_rsdp * rsdp = (struct acpi_rsdp *) buff; 196433d6423SLionel Sambuc 197433d6423SLionel Sambuc if (!platform_tbl_checksum_ok(buff, 20)) 198433d6423SLionel Sambuc return 0; 199433d6423SLionel Sambuc if (strncmp(rsdp->signature, "RSD PTR ", 8)) 200433d6423SLionel Sambuc return 0; 201433d6423SLionel Sambuc 202433d6423SLionel Sambuc return 1; 203433d6423SLionel Sambuc } 204433d6423SLionel Sambuc 205433d6423SLionel Sambuc static int get_acpi_rsdp(void) 206433d6423SLionel Sambuc { 207433d6423SLionel Sambuc u16_t ebda; 208433d6423SLionel Sambuc /* 209433d6423SLionel Sambuc * Read 40:0Eh - to find the starting address of the EBDA. 210433d6423SLionel Sambuc */ 211433d6423SLionel Sambuc acpi_phys_copy (0x40E, &ebda, sizeof(ebda)); 212433d6423SLionel Sambuc if (ebda) { 213433d6423SLionel Sambuc ebda <<= 4; 214433d6423SLionel Sambuc if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp, 215433d6423SLionel Sambuc sizeof(acpi_rsdp), &machine.acpi_rsdp, 216433d6423SLionel Sambuc acpi_rsdp_test)) 217433d6423SLionel Sambuc return 1; 218433d6423SLionel Sambuc } 219433d6423SLionel Sambuc 220433d6423SLionel Sambuc /* try BIOS read only mem space */ 221433d6423SLionel Sambuc if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp, 222433d6423SLionel Sambuc sizeof(acpi_rsdp), &machine.acpi_rsdp, 223433d6423SLionel Sambuc acpi_rsdp_test)) 224433d6423SLionel Sambuc return 1; 225433d6423SLionel Sambuc 226433d6423SLionel Sambuc machine.acpi_rsdp = 0; /* RSDP cannot be found at this address therefore 227433d6423SLionel Sambuc it is a valid negative value */ 228433d6423SLionel Sambuc return 0; 229433d6423SLionel Sambuc } 230433d6423SLionel Sambuc 231433d6423SLionel Sambuc static void acpi_init_poweroff(void) 232433d6423SLionel Sambuc { 233433d6423SLionel Sambuc u8_t *ptr = NULL; 234433d6423SLionel Sambuc u8_t *start = NULL; 235433d6423SLionel Sambuc u8_t *end = NULL; 236433d6423SLionel Sambuc struct acpi_fadt_header *fadt_header = NULL; 237433d6423SLionel Sambuc struct acpi_rsdt * dsdt_header = NULL; 238433d6423SLionel Sambuc char *msg = NULL; 239433d6423SLionel Sambuc 240433d6423SLionel Sambuc /* Everything used here existed since ACPI spec 1.0 */ 241433d6423SLionel Sambuc /* So we can safely use them */ 242433d6423SLionel Sambuc fadt_header = (struct acpi_fadt_header *) 243433d6423SLionel Sambuc acpi_phys2vir(acpi_get_table_base("FACP")); 244433d6423SLionel Sambuc if (fadt_header == NULL) { 245433d6423SLionel Sambuc msg = "Could not load FACP"; 246433d6423SLionel Sambuc goto exit; 247433d6423SLionel Sambuc } 248433d6423SLionel Sambuc 249433d6423SLionel Sambuc dsdt_header = (struct acpi_rsdt *) 250433d6423SLionel Sambuc acpi_phys2vir((phys_bytes) fadt_header->dsdt); 251433d6423SLionel Sambuc if (dsdt_header == NULL) { 252433d6423SLionel Sambuc msg = "Could not load DSDT"; 253433d6423SLionel Sambuc goto exit; 254433d6423SLionel Sambuc } 255433d6423SLionel Sambuc 256433d6423SLionel Sambuc pm1a_cnt_blk = fadt_header->pm1a_cnt_blk; 257433d6423SLionel Sambuc pm1b_cnt_blk = fadt_header->pm1b_cnt_blk; 258433d6423SLionel Sambuc 259433d6423SLionel Sambuc ptr = start = (u8_t *) dsdt_header->data; 260433d6423SLionel Sambuc end = start + dsdt_header->hdr.length - 4; 261433d6423SLionel Sambuc 262433d6423SLionel Sambuc /* See http://forum.osdev.org/viewtopic.php?t=16990 */ 263433d6423SLionel Sambuc /* for layout of \_S5 */ 264433d6423SLionel Sambuc while (ptr < end && memcmp(ptr, "_S5_", 4) != 0) 265433d6423SLionel Sambuc ptr++; 266433d6423SLionel Sambuc 267433d6423SLionel Sambuc msg = "Could not read S5 data. Use default SLP_TYPa and SLP_TYPb"; 268433d6423SLionel Sambuc if (ptr >= end || ptr == start) 269433d6423SLionel Sambuc goto exit; 270433d6423SLionel Sambuc 271433d6423SLionel Sambuc /* validate AML structure */ 272433d6423SLionel Sambuc if (*(ptr + AMI_S5_PACKAGE_OP_OFFSET) != AMI_PACKAGE_OP_CODE) 273433d6423SLionel Sambuc goto exit; 274433d6423SLionel Sambuc 275433d6423SLionel Sambuc if ((ptr < start + (-AMI_S5_NAME_OP_OFFSET_2) || 276433d6423SLionel Sambuc (*(ptr + AMI_S5_NAME_OP_OFFSET_2) != AMI_NAME_OP_CODE || 277433d6423SLionel Sambuc *(ptr + AMI_S5_NAME_OP_OFFSET_2 + 1) != '\\')) && 278433d6423SLionel Sambuc *(ptr + AMI_S5_NAME_OP_OFFSET_1) != AMI_NAME_OP_CODE) 279433d6423SLionel Sambuc goto exit; 280433d6423SLionel Sambuc 281433d6423SLionel Sambuc ptr += AMI_S5_PACKET_LENGTH_OFFSET; 282433d6423SLionel Sambuc if (ptr >= end) 283433d6423SLionel Sambuc goto exit; 284433d6423SLionel Sambuc 285433d6423SLionel Sambuc /* package length */ 286433d6423SLionel Sambuc ptr += ((*ptr & AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK) >> 287433d6423SLionel Sambuc AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT) + 288433d6423SLionel Sambuc AMI_MIN_PACKAGE_LENGTH + AMI_NUM_ELEMENTS_LENGTH; 289433d6423SLionel Sambuc if (ptr >= end) 290433d6423SLionel Sambuc goto exit; 291433d6423SLionel Sambuc 292433d6423SLionel Sambuc if (*ptr == AMI_BYTE_PREFIX_CODE) 293433d6423SLionel Sambuc ptr++; /* skip byte prefix */ 294433d6423SLionel Sambuc 295433d6423SLionel Sambuc slp_typa = (*ptr) << AMI_SLP_TYPA_SHIFT; 296433d6423SLionel Sambuc 297433d6423SLionel Sambuc ptr++; /* move to SLP_TYPb */ 298433d6423SLionel Sambuc if (*ptr == AMI_BYTE_PREFIX_CODE) 299433d6423SLionel Sambuc ptr++; /* skip byte prefix */ 300433d6423SLionel Sambuc 301433d6423SLionel Sambuc slp_typb = (*ptr) << AMI_SLP_TYPB_SHIFT; 302433d6423SLionel Sambuc 303433d6423SLionel Sambuc msg = "poweroff initialized"; 304433d6423SLionel Sambuc 305433d6423SLionel Sambuc exit: 306433d6423SLionel Sambuc if (msg) { 307*da9af514SLionel Sambuc DEBUGBASIC(("acpi: %s\n", msg)); 308433d6423SLionel Sambuc } 309433d6423SLionel Sambuc } 310433d6423SLionel Sambuc 311433d6423SLionel Sambuc void acpi_init(void) 312433d6423SLionel Sambuc { 313433d6423SLionel Sambuc int s, i; 314433d6423SLionel Sambuc read_func = acpi_phys_copy; 315433d6423SLionel Sambuc 316433d6423SLionel Sambuc if (!get_acpi_rsdp()) { 317433d6423SLionel Sambuc printf("WARNING : Cannot configure ACPI\n"); 318433d6423SLionel Sambuc return; 319433d6423SLionel Sambuc } 320433d6423SLionel Sambuc 321433d6423SLionel Sambuc s = acpi_read_sdt_at(acpi_rsdp.rsdt_addr, (struct acpi_sdt_header *) &rsdt, 322433d6423SLionel Sambuc sizeof(struct acpi_rsdt), ACPI_SDT_SIGNATURE(RSDT)); 323433d6423SLionel Sambuc 324433d6423SLionel Sambuc sdt_count = (s - sizeof(struct acpi_sdt_header)) / sizeof(u32_t); 325433d6423SLionel Sambuc 326433d6423SLionel Sambuc for (i = 0; i < sdt_count; i++) { 327433d6423SLionel Sambuc struct acpi_sdt_header hdr; 328433d6423SLionel Sambuc int j; 329433d6423SLionel Sambuc if (read_func(rsdt.data[i], &hdr, sizeof(struct acpi_sdt_header))) { 330433d6423SLionel Sambuc printf("ERROR acpi cannot read header at 0x%x\n", 331433d6423SLionel Sambuc rsdt.data[i]); 332433d6423SLionel Sambuc return; 333433d6423SLionel Sambuc } 334433d6423SLionel Sambuc 335433d6423SLionel Sambuc for (j = 0 ; j < ACPI_SDT_SIGNATURE_LEN; j++) 336433d6423SLionel Sambuc sdt_trans[i].signature[j] = hdr.signature[j]; 337433d6423SLionel Sambuc sdt_trans[i].signature[ACPI_SDT_SIGNATURE_LEN] = '\0'; 338433d6423SLionel Sambuc sdt_trans[i].length = hdr.length; 339433d6423SLionel Sambuc } 340433d6423SLionel Sambuc 341433d6423SLionel Sambuc acpi_init_poweroff(); 342433d6423SLionel Sambuc } 343433d6423SLionel Sambuc 344433d6423SLionel Sambuc struct acpi_madt_ioapic * acpi_get_ioapic_next(void) 345433d6423SLionel Sambuc { 346433d6423SLionel Sambuc static unsigned idx = 0; 347433d6423SLionel Sambuc static struct acpi_madt_hdr * madt_hdr; 348433d6423SLionel Sambuc 349433d6423SLionel Sambuc struct acpi_madt_ioapic * ret; 350433d6423SLionel Sambuc 351433d6423SLionel Sambuc if (idx == 0) { 352433d6423SLionel Sambuc madt_hdr = (struct acpi_madt_hdr *) 353433d6423SLionel Sambuc acpi_phys2vir(acpi_get_table_base("APIC")); 354433d6423SLionel Sambuc if (madt_hdr == NULL) 355433d6423SLionel Sambuc return NULL; 356433d6423SLionel Sambuc } 357433d6423SLionel Sambuc 358433d6423SLionel Sambuc ret = (struct acpi_madt_ioapic *) 359433d6423SLionel Sambuc acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC, idx); 360433d6423SLionel Sambuc if (ret) 361433d6423SLionel Sambuc idx++; 362433d6423SLionel Sambuc 363433d6423SLionel Sambuc return ret; 364433d6423SLionel Sambuc } 365433d6423SLionel Sambuc 366433d6423SLionel Sambuc struct acpi_madt_lapic * acpi_get_lapic_next(void) 367433d6423SLionel Sambuc { 368433d6423SLionel Sambuc static unsigned idx = 0; 369433d6423SLionel Sambuc static struct acpi_madt_hdr * madt_hdr; 370433d6423SLionel Sambuc 371433d6423SLionel Sambuc struct acpi_madt_lapic * ret; 372433d6423SLionel Sambuc 373433d6423SLionel Sambuc if (idx == 0) { 374433d6423SLionel Sambuc madt_hdr = (struct acpi_madt_hdr *) 375433d6423SLionel Sambuc acpi_phys2vir(acpi_get_table_base("APIC")); 376433d6423SLionel Sambuc if (madt_hdr == NULL) 377433d6423SLionel Sambuc return NULL; 378433d6423SLionel Sambuc } 379433d6423SLionel Sambuc 380433d6423SLionel Sambuc for (;;) { 381433d6423SLionel Sambuc ret = (struct acpi_madt_lapic *) 382433d6423SLionel Sambuc acpi_madt_get_typed_item(madt_hdr, 383433d6423SLionel Sambuc ACPI_MADT_TYPE_LAPIC, idx); 384433d6423SLionel Sambuc if (!ret) 385433d6423SLionel Sambuc break; 386433d6423SLionel Sambuc 387433d6423SLionel Sambuc idx++; 388433d6423SLionel Sambuc 389433d6423SLionel Sambuc /* report only usable CPUs */ 390433d6423SLionel Sambuc if (ret->flags & 1) 391433d6423SLionel Sambuc break; 392433d6423SLionel Sambuc } 393433d6423SLionel Sambuc 394433d6423SLionel Sambuc return ret; 395433d6423SLionel Sambuc } 396433d6423SLionel Sambuc 397433d6423SLionel Sambuc void __k_unpaged_acpi_poweroff(void) 398433d6423SLionel Sambuc { 399433d6423SLionel Sambuc /* NO OP poweroff symbol*/ 400433d6423SLionel Sambuc } 401433d6423SLionel Sambuc 402433d6423SLionel Sambuc void acpi_poweroff(void) 403433d6423SLionel Sambuc { 404433d6423SLionel Sambuc if (pm1a_cnt_blk == 0) { 405433d6423SLionel Sambuc return; 406433d6423SLionel Sambuc } 407433d6423SLionel Sambuc outw(pm1a_cnt_blk, slp_typa | SLP_EN_CODE); 408433d6423SLionel Sambuc if (pm1b_cnt_blk != 0) { 409433d6423SLionel Sambuc outw(pm1b_cnt_blk, slp_typb | SLP_EN_CODE); 410433d6423SLionel Sambuc } 411433d6423SLionel Sambuc } 412