1 /* 2 * Copyright 2009, Clemens Zeidler. All rights reserved. 3 * Copyright 2006, Jérôme Duval. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <stdlib.h> 10 #include <string.h> 11 12 13 #include "ACPIPrivate.h" 14 extern "C" { 15 #include "acpi.h" 16 } 17 #include <dpc.h> 18 #include <PCI.h> 19 20 21 //#define TRACE_ACPI_MODULE 22 #ifdef TRACE_ACPI_MODULE 23 # define TRACE(x) dprintf x 24 #else 25 # define TRACE(x) ; 26 #endif 27 28 29 device_manager_info* gDeviceManager = NULL; 30 pci_module_info* gPCIManager = NULL; 31 dpc_module_info* gDPC = NULL; 32 33 module_dependency module_dependencies[] = { 34 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 35 {B_PCI_MODULE_NAME, (module_info**)&gPCIManager}, 36 {B_DPC_MODULE_NAME, (module_info**)&gDPC}, 37 {} 38 }; 39 40 41 static float 42 acpi_module_supports_device(device_node* parent) 43 { 44 // make sure parent is really device root 45 const char* bus; 46 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 47 return B_ERROR; 48 49 if (strcmp(bus, "root")) 50 return 0.0; 51 52 return 1.0; 53 } 54 55 56 static status_t 57 acpi_module_register_device(device_node* parent) 58 { 59 device_attr attrs[] = { 60 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "ACPI" }}, 61 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_KEEP_DRIVER_LOADED }}, 62 {} 63 }; 64 65 return gDeviceManager->register_node(parent, ACPI_ROOT_MODULE_NAME, attrs, 66 NULL, NULL); 67 } 68 69 70 static status_t 71 acpi_enumerate_child_devices(device_node* node, const char* root) 72 { 73 char result[255]; 74 void* counter = NULL; 75 76 TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root)); 77 78 while (get_next_entry(ACPI_TYPE_ANY, root, result, 79 sizeof(result), &counter) == B_OK) { 80 uint32 type = get_object_type(result); 81 device_node* deviceNode; 82 83 switch (type) { 84 case ACPI_TYPE_POWER: 85 case ACPI_TYPE_PROCESSOR: 86 case ACPI_TYPE_THERMAL: 87 case ACPI_TYPE_DEVICE: { 88 device_attr attrs[16] = { 89 // info about device 90 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 91 92 // location on ACPI bus 93 { ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { .string = result }}, 94 95 // info about the device 96 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = type }}, 97 98 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }}, 99 { NULL } 100 }; 101 102 uint32 attrCount = 4; 103 char* hid = NULL; 104 char* cidList[8] = { NULL }; 105 char* uid = NULL; 106 if (type == ACPI_TYPE_DEVICE) { 107 if (get_device_info(result, &hid, (char**)&cidList, 8, 108 &uid) == B_OK) { 109 if (hid != NULL) { 110 attrs[attrCount].name = ACPI_DEVICE_HID_ITEM; 111 attrs[attrCount].type = B_STRING_TYPE; 112 attrs[attrCount].value.string = hid; 113 attrCount++; 114 } 115 for (int i = 0; cidList[i] != NULL; i++) { 116 attrs[attrCount].name = ACPI_DEVICE_CID_ITEM; 117 attrs[attrCount].type = B_STRING_TYPE; 118 attrs[attrCount].value.string = cidList[i]; 119 attrCount++; 120 } 121 if (uid != NULL) { 122 attrs[attrCount].name = ACPI_DEVICE_UID_ITEM; 123 attrs[attrCount].type = B_STRING_TYPE; 124 attrs[attrCount].value.string = uid; 125 attrCount++; 126 } 127 } 128 uint32 addr; 129 if (get_device_addr(result, &addr) == B_OK) { 130 attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM; 131 attrs[attrCount].type = B_UINT32_TYPE; 132 attrs[attrCount].value.ui32 = addr; 133 attrCount++; 134 } 135 } 136 137 status_t status = gDeviceManager->register_node(node, 138 ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode); 139 free(hid); 140 free(uid); 141 for (int i = 0; cidList[i] != NULL; i++) 142 free(cidList[i]); 143 if (status != B_OK) 144 break; 145 acpi_enumerate_child_devices(deviceNode, result); 146 break; 147 } 148 default: 149 acpi_enumerate_child_devices(node, result); 150 break; 151 } 152 153 } 154 155 return B_OK; 156 } 157 158 159 static status_t 160 acpi_module_register_child_devices(void* cookie) 161 { 162 device_node* node = (device_node*)cookie; 163 164 status_t status = gDeviceManager->publish_device(node, "acpi/namespace", 165 ACPI_NS_DUMP_DEVICE_MODULE_NAME); 166 if (status != B_OK) 167 return status; 168 status = gDeviceManager->publish_device(node, "acpi/call", 169 ACPI_CALL_DEVICE_MODULE_NAME); 170 if (status != B_OK) 171 return status; 172 173 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 174 dprintf("registering power button\n"); 175 device_attr attrs[] = { 176 // info about device 177 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 178 179 // info about the device 180 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FPB" }}, 181 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }}, 182 183 // consumer specification 184 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }}, 185 { NULL } 186 }; 187 device_node* deviceNode; 188 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 189 NULL, &deviceNode); 190 } 191 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 192 dprintf("registering sleep button\n"); 193 device_attr attrs[] = { 194 // info about device 195 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 196 197 // info about the device 198 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FSB" }}, 199 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }}, 200 201 // consumer specification 202 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }}, 203 { NULL } 204 }; 205 device_node* deviceNode; 206 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 207 NULL, &deviceNode); 208 209 } 210 211 return acpi_enumerate_child_devices(node, "\\"); 212 } 213 214 215 static status_t 216 acpi_module_init(device_node* node, void** _cookie) 217 { 218 *_cookie = node; 219 return B_OK; 220 } 221 222 223 static void 224 acpi_module_uninit(void* cookie) 225 { 226 } 227 228 229 static int32 230 acpi_module_std_ops(int32 op, ...) 231 { 232 switch (op) { 233 case B_MODULE_INIT: 234 { 235 module_info* module; 236 return get_module(B_ACPI_MODULE_NAME, &module); 237 // this serializes our module initialization 238 } 239 240 case B_MODULE_UNINIT: 241 return put_module(B_ACPI_MODULE_NAME); 242 } 243 244 return B_BAD_VALUE; 245 } 246 247 248 static struct acpi_root_info sACPIRootModule = { 249 { 250 { 251 ACPI_ROOT_MODULE_NAME, 252 0, 253 acpi_module_std_ops 254 }, 255 256 acpi_module_supports_device, 257 acpi_module_register_device, 258 acpi_module_init, 259 acpi_module_uninit, 260 acpi_module_register_child_devices, 261 NULL, // rescan devices 262 NULL, // device removed 263 }, 264 265 get_handle, 266 get_name, 267 acquire_global_lock, 268 release_global_lock, 269 install_notify_handler, 270 remove_notify_handler, 271 update_all_gpes, 272 enable_gpe, 273 disable_gpe, 274 clear_gpe, 275 set_gpe, 276 finish_gpe, 277 install_gpe_handler, 278 remove_gpe_handler, 279 install_address_space_handler, 280 remove_address_space_handler, 281 enable_fixed_event, 282 disable_fixed_event, 283 fixed_event_status, 284 reset_fixed_event, 285 install_fixed_event_handler, 286 remove_fixed_event_handler, 287 get_next_entry, 288 get_next_object, 289 get_device, 290 get_device_info, 291 get_object_type, 292 get_object, 293 get_object_typed, 294 ns_handle_to_pathname, 295 evaluate_object, 296 evaluate_method, 297 get_irq_routing_table, 298 get_current_resources, 299 get_possible_resources, 300 set_current_resources, 301 walk_resources, 302 prepare_sleep_state, 303 enter_sleep_state, 304 reboot, 305 get_table 306 }; 307 308 309 module_info* modules[] = { 310 (module_info*)&gACPIModule, 311 (module_info*)&sACPIRootModule, 312 (module_info*)&acpi_ns_dump_module, 313 (module_info*)&gACPIDeviceModule, 314 (module_info*)&embedded_controller_driver_module, 315 (module_info*)&embedded_controller_device_module, 316 (module_info*)&gAcpiCallDeviceModule, 317 NULL 318 }; 319