1 #include <minix/driver.h> 2 #include <acpi.h> 3 #include <assert.h> 4 #include <minix/acpi.h> 5 6 #include "pci.h" 7 8 int acpi_enabled; 9 struct machine machine; 10 11 /* don't know where ACPI tables are, we may need to access any memory */ 12 static int init_mem_priv(void) 13 { 14 struct minix_mem_range mr; 15 16 mr.mr_base = 0; 17 mr.mr_limit = 0xffffffff; 18 19 return sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr); 20 } 21 22 static void set_machine_mode(void) 23 { 24 ACPI_OBJECT arg1; 25 ACPI_OBJECT_LIST args; 26 ACPI_STATUS as; 27 28 arg1.Type = ACPI_TYPE_INTEGER; 29 arg1.Integer.Value = machine.apic_enabled ? 1 : 0; 30 args.Count = 1; 31 args.Pointer = &arg1; 32 33 as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL); 34 /* 35 * We can silently ignore failure as it may not be implemented, ACPI should 36 * provide us with correct information anyway 37 */ 38 if (ACPI_SUCCESS(as)) 39 printf("ACPI: machine set to %s mode\n", 40 machine.apic_enabled ? "APIC" : "PIC"); 41 } 42 43 static ACPI_STATUS init_acpica(void) 44 { 45 ACPI_STATUS status; 46 47 status = AcpiInitializeSubsystem(); 48 if (ACPI_FAILURE(status)) 49 return status; 50 51 status = AcpiInitializeTables(NULL, 16, FALSE); 52 if (ACPI_FAILURE(status)) 53 return status; 54 55 status = AcpiLoadTables(); 56 if (ACPI_FAILURE(status)) 57 return status; 58 59 status = AcpiEnableSubsystem(0); 60 if (ACPI_FAILURE(status)) 61 return status; 62 63 status = AcpiInitializeObjects(0); 64 if (ACPI_FAILURE(status)) 65 return status; 66 67 set_machine_mode(); 68 69 pci_scan_devices(); 70 71 return AE_OK; 72 } 73 74 void init_acpi(void) 75 { 76 ACPI_STATUS acpi_err; 77 /* test conditions for acpi */ 78 if (sys_getmachine(&machine)) { 79 printf("ACPI: no machine\n"); 80 return; 81 } 82 if (machine.acpi_rsdp == 0) { 83 printf("ACPI: no RSDP\n"); 84 return; 85 } 86 if (init_mem_priv()) { 87 printf("ACPI: no mem access\n"); 88 return; 89 } 90 91 if ((acpi_err = init_acpica()) == AE_OK) { 92 acpi_enabled = 1; 93 printf("ACPI: ACPI enabled\n"); 94 } 95 else { 96 acpi_enabled = 0; 97 printf("ACPI: ACPI failed with err %d\n", acpi_err); 98 } 99 } 100 101 static int sef_cb_init_fresh(int type, sef_init_info_t *info) 102 { 103 int r; 104 105 init_acpi(); 106 107 /* Let SEF know about ACPI special cache word. */ 108 r = sef_llvm_add_special_mem_region((void*)0xCACACACA, 1, 109 "%MMAP_CACHE_WORD"); 110 if(r < 0) { 111 printf("acpi: sef_llvm_add_special_mem_region failed %d\n", r); 112 } 113 114 /* XXX To-do: acpi requires custom state transfer handlers for 115 * unions acpi_operand_object and acpi_generic_state (and nested unions) 116 * for generic state transfer to work correctly. 117 */ 118 119 return OK; 120 } 121 122 static void sef_local_startup() 123 { 124 /* Register init callbacks. */ 125 sef_setcb_init_fresh(sef_cb_init_fresh); 126 sef_setcb_init_lu(sef_cb_init_fresh); 127 sef_setcb_init_restart(sef_cb_init_fresh); 128 129 /* Let SEF perform startup. */ 130 sef_startup(); 131 } 132 133 int main(void) 134 { 135 int err; 136 message m; 137 int ipc_status; 138 139 sef_local_startup(); 140 141 for(;;) { 142 err = driver_receive(ANY, &m, &ipc_status); 143 if (err != OK) { 144 printf("ACPI: driver_receive failed: %d\n", err); 145 continue; 146 } 147 148 switch (((struct acpi_request_hdr *)&m)->request) { 149 case ACPI_REQ_GET_IRQ: 150 do_get_irq(&m); 151 break; 152 case ACPI_REQ_MAP_BRIDGE: 153 do_map_bridge(&m); 154 break; 155 default: 156 printf("ACPI: ignoring unsupported request %d " 157 "from %d\n", 158 ((struct acpi_request_hdr *)&m)->request, 159 ((struct acpi_request_hdr *)&m)->m_source); 160 } 161 162 err = ipc_send(m.m_source, &m); 163 if (err != OK) { 164 printf("ACPI: ipc_send failed: %d\n", err); 165 } 166 } 167 } 168