1 /*- 2 * Copyright (c) 2001 Mitsuru IWASAKI 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/bus.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/sysctl.h> 35 36 #include <vm/vm.h> 37 #include <vm/pmap.h> 38 39 #include <contrib/dev/acpica/include/acpi.h> 40 #include <contrib/dev/acpica/include/accommon.h> 41 #include <contrib/dev/acpica/include/actables.h> 42 43 #include <dev/acpica/acpivar.h> 44 45 #include <machine/nexusvar.h> 46 47 uint32_t acpi_resume_beep; 48 SYSCTL_UINT(_debug_acpi, OID_AUTO, resume_beep, CTLFLAG_RWTUN, &acpi_resume_beep, 49 0, "Beep the PC speaker when resuming"); 50 51 uint32_t acpi_reset_video; 52 TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video); 53 54 static int intr_model = ACPI_INTR_PIC; 55 56 int 57 acpi_machdep_init(device_t dev) 58 { 59 struct acpi_softc *sc; 60 61 sc = device_get_softc(dev); 62 63 acpi_apm_init(sc); 64 acpi_install_wakeup_handler(sc); 65 66 if (intr_model == ACPI_INTR_PIC) 67 BUS_CONFIG_INTR(dev, AcpiGbl_FADT.SciInterrupt, 68 INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); 69 else 70 acpi_SetIntrModel(intr_model); 71 72 SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx, 73 SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, 74 "reset_video", CTLFLAG_RW, &acpi_reset_video, 0, 75 "Call the VESA reset BIOS vector on the resume path"); 76 77 return (0); 78 } 79 80 void 81 acpi_SetDefaultIntrModel(int model) 82 { 83 84 intr_model = model; 85 } 86 87 /* Check BIOS date. If 1998 or older, disable ACPI. */ 88 int 89 acpi_machdep_quirks(int *quirks) 90 { 91 char *va; 92 int year; 93 94 /* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */ 95 va = pmap_mapbios(0xffff0, 16); 96 sscanf(va + 11, "%2d", &year); 97 pmap_unmapbios((vm_offset_t)va, 16); 98 99 /* 100 * Date must be >= 1/1/1999 or we don't trust ACPI. Note that this 101 * check must be changed by my 114th birthday. 102 */ 103 if (year > 90 && year < 99) 104 *quirks = ACPI_Q_BROKEN; 105 106 return (0); 107 } 108 109 /* 110 * Support for mapping ACPI tables during early boot. This abuses the 111 * crashdump map because the kernel cannot allocate KVA in 112 * pmap_mapbios() when this is used. This makes the following 113 * assumptions about how we use this KVA: pages 0 and 1 are used to 114 * map in the header of each table found via the RSDT or XSDT and 115 * pages 2 to n are used to map in the RSDT or XSDT. This has to use 116 * 2 pages for the table headers in case a header spans a page 117 * boundary. 118 * 119 * XXX: We don't ensure the table fits in the available address space 120 * in the crashdump map. 121 */ 122 123 /* 124 * Map some memory using the crashdump map. 'offset' is an offset in 125 * pages into the crashdump map to use for the start of the mapping. 126 */ 127 static void * 128 table_map(vm_paddr_t pa, int offset, vm_offset_t length) 129 { 130 vm_offset_t va, off; 131 void *data; 132 133 off = pa & PAGE_MASK; 134 length = round_page(length + off); 135 pa = pa & PG_FRAME; 136 va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 137 (offset * PAGE_SIZE); 138 data = (void *)(va + off); 139 length -= PAGE_SIZE; 140 while (length > 0) { 141 va += PAGE_SIZE; 142 pa += PAGE_SIZE; 143 length -= PAGE_SIZE; 144 pmap_kenter(va, pa); 145 invlpg(va); 146 } 147 return (data); 148 } 149 150 /* Unmap memory previously mapped with table_map(). */ 151 static void 152 table_unmap(void *data, vm_offset_t length) 153 { 154 vm_offset_t va, off; 155 156 va = (vm_offset_t)data; 157 off = va & PAGE_MASK; 158 length = round_page(length + off); 159 va &= ~PAGE_MASK; 160 while (length > 0) { 161 pmap_kremove(va); 162 invlpg(va); 163 va += PAGE_SIZE; 164 length -= PAGE_SIZE; 165 } 166 } 167 168 /* 169 * Map a table at a given offset into the crashdump map. It first 170 * maps the header to determine the table length and then maps the 171 * entire table. 172 */ 173 static void * 174 map_table(vm_paddr_t pa, int offset, const char *sig) 175 { 176 ACPI_TABLE_HEADER *header; 177 vm_offset_t length; 178 void *table; 179 180 header = table_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 181 if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { 182 table_unmap(header, sizeof(ACPI_TABLE_HEADER)); 183 return (NULL); 184 } 185 length = header->Length; 186 table_unmap(header, sizeof(ACPI_TABLE_HEADER)); 187 table = table_map(pa, offset, length); 188 if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { 189 if (bootverbose) 190 printf("ACPI: Failed checksum for table %s\n", sig); 191 #if (ACPI_CHECKSUM_ABORT) 192 table_unmap(table, length); 193 return (NULL); 194 #endif 195 } 196 return (table); 197 } 198 199 /* 200 * See if a given ACPI table is the requested table. Returns the 201 * length of the able if it matches or zero on failure. 202 */ 203 static int 204 probe_table(vm_paddr_t address, const char *sig) 205 { 206 ACPI_TABLE_HEADER *table; 207 208 table = table_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 209 if (table == NULL) { 210 if (bootverbose) 211 printf("ACPI: Failed to map table at 0x%jx\n", 212 (uintmax_t)address); 213 return (0); 214 } 215 if (bootverbose) 216 printf("Table '%.4s' at 0x%jx\n", table->Signature, 217 (uintmax_t)address); 218 219 if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) { 220 table_unmap(table, sizeof(ACPI_TABLE_HEADER)); 221 return (0); 222 } 223 table_unmap(table, sizeof(ACPI_TABLE_HEADER)); 224 return (1); 225 } 226 227 /* 228 * Try to map a table at a given physical address previously returned 229 * by acpi_find_table(). 230 */ 231 void * 232 acpi_map_table(vm_paddr_t pa, const char *sig) 233 { 234 235 return (map_table(pa, 0, sig)); 236 } 237 238 /* Unmap a table previously mapped via acpi_map_table(). */ 239 void 240 acpi_unmap_table(void *table) 241 { 242 ACPI_TABLE_HEADER *header; 243 244 header = (ACPI_TABLE_HEADER *)table; 245 table_unmap(table, header->Length); 246 } 247 248 /* 249 * Return the physical address of the requested table or zero if one 250 * is not found. 251 */ 252 vm_paddr_t 253 acpi_find_table(const char *sig) 254 { 255 ACPI_PHYSICAL_ADDRESS rsdp_ptr; 256 ACPI_TABLE_RSDP *rsdp; 257 ACPI_TABLE_RSDT *rsdt; 258 ACPI_TABLE_XSDT *xsdt; 259 ACPI_TABLE_HEADER *table; 260 vm_paddr_t addr; 261 int i, count; 262 263 if (resource_disabled("acpi", 0)) 264 return (0); 265 266 /* 267 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 268 * calls pmap_mapbios() to find the RSDP, we assume that we can use 269 * pmap_mapbios() to map the RSDP. 270 */ 271 if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) 272 return (0); 273 rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); 274 if (rsdp == NULL) { 275 if (bootverbose) 276 printf("ACPI: Failed to map RSDP\n"); 277 return (0); 278 } 279 280 /* 281 * For ACPI >= 2.0, use the XSDT if it is available. 282 * Otherwise, use the RSDT. We map the XSDT or RSDT at page 2 283 * in the crashdump area. Pages 0 and 1 are used to map in the 284 * headers of candidate ACPI tables. 285 */ 286 addr = 0; 287 if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { 288 /* 289 * AcpiOsGetRootPointer only verifies the checksum for 290 * the version 1.0 portion of the RSDP. Version 2.0 has 291 * an additional checksum that we verify first. 292 */ 293 if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { 294 if (bootverbose) 295 printf("ACPI: RSDP failed extended checksum\n"); 296 return (0); 297 } 298 xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); 299 if (xsdt == NULL) { 300 if (bootverbose) 301 printf("ACPI: Failed to map XSDT\n"); 302 return (0); 303 } 304 count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 305 sizeof(UINT64); 306 for (i = 0; i < count; i++) 307 if (probe_table(xsdt->TableOffsetEntry[i], sig)) { 308 addr = xsdt->TableOffsetEntry[i]; 309 break; 310 } 311 acpi_unmap_table(xsdt); 312 } else { 313 rsdt = map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); 314 if (rsdt == NULL) { 315 if (bootverbose) 316 printf("ACPI: Failed to map RSDT\n"); 317 return (0); 318 } 319 count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 320 sizeof(UINT32); 321 for (i = 0; i < count; i++) 322 if (probe_table(rsdt->TableOffsetEntry[i], sig)) { 323 addr = rsdt->TableOffsetEntry[i]; 324 break; 325 } 326 acpi_unmap_table(rsdt); 327 } 328 pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); 329 if (addr == 0) { 330 if (bootverbose) 331 printf("ACPI: No %s table found\n", sig); 332 return (0); 333 } 334 if (bootverbose) 335 printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr); 336 337 /* 338 * Verify that we can map the full table and that its checksum is 339 * correct, etc. 340 */ 341 table = map_table(addr, 0, sig); 342 if (table == NULL) 343 return (0); 344 acpi_unmap_table(table); 345 346 return (addr); 347 } 348 349 /* 350 * ACPI nexus(4) driver. 351 */ 352 static int 353 nexus_acpi_probe(device_t dev) 354 { 355 int error; 356 357 error = acpi_identify(); 358 if (error) 359 return (error); 360 361 return (BUS_PROBE_DEFAULT); 362 } 363 364 static int 365 nexus_acpi_attach(device_t dev) 366 { 367 368 nexus_init_resources(); 369 bus_generic_probe(dev); 370 if (BUS_ADD_CHILD(dev, 10, "acpi", 0) == NULL) 371 panic("failed to add acpi0 device"); 372 373 return (bus_generic_attach(dev)); 374 } 375 376 static device_method_t nexus_acpi_methods[] = { 377 /* Device interface */ 378 DEVMETHOD(device_probe, nexus_acpi_probe), 379 DEVMETHOD(device_attach, nexus_acpi_attach), 380 381 { 0, 0 } 382 }; 383 384 DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, nexus_driver); 385 static devclass_t nexus_devclass; 386 387 DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_devclass, 0, 0); 388