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[11] = { NULL }; 105 char* uid = NULL; 106 char* cls = NULL; 107 if (type == ACPI_TYPE_DEVICE) { 108 if (get_device_info(result, &hid, (char**)&cidList, 8, 109 &uid, &cls) == B_OK) { 110 if (hid != NULL) { 111 attrs[attrCount].name = ACPI_DEVICE_HID_ITEM; 112 attrs[attrCount].type = B_STRING_TYPE; 113 attrs[attrCount].value.string = hid; 114 attrCount++; 115 } 116 for (int i = 0; cidList[i] != NULL; i++) { 117 attrs[attrCount].name = ACPI_DEVICE_CID_ITEM; 118 attrs[attrCount].type = B_STRING_TYPE; 119 attrs[attrCount].value.string = cidList[i]; 120 attrCount++; 121 } 122 if (uid != NULL) { 123 attrs[attrCount].name = ACPI_DEVICE_UID_ITEM; 124 attrs[attrCount].type = B_STRING_TYPE; 125 attrs[attrCount].value.string = uid; 126 attrCount++; 127 } 128 if (cls != NULL) { 129 uint32 clsClass = strtoul(cls, NULL, 16); 130 attrs[attrCount].name = B_DEVICE_TYPE; 131 attrs[attrCount].type = B_UINT16_TYPE; 132 attrs[attrCount].value.ui16 = (clsClass >> 16) & 0xff ; 133 attrCount++; 134 attrs[attrCount].name = B_DEVICE_SUB_TYPE; 135 attrs[attrCount].type = B_UINT16_TYPE; 136 attrs[attrCount].value.ui16 = (clsClass >> 8) & 0xff ; 137 attrCount++; 138 attrs[attrCount].name = B_DEVICE_INTERFACE; 139 attrs[attrCount].type = B_UINT16_TYPE; 140 attrs[attrCount].value.ui16 = (clsClass >> 0) & 0xff ; 141 attrCount++; 142 } 143 } 144 uint32 addr; 145 if (get_device_addr(result, &addr) == B_OK) { 146 attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM; 147 attrs[attrCount].type = B_UINT32_TYPE; 148 attrs[attrCount].value.ui32 = addr; 149 attrCount++; 150 } 151 } 152 153 status_t status = gDeviceManager->register_node(node, 154 ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode); 155 free(hid); 156 free(uid); 157 free(cls); 158 for (int i = 0; cidList[i] != NULL; i++) 159 free(cidList[i]); 160 if (status != B_OK) 161 break; 162 acpi_enumerate_child_devices(deviceNode, result); 163 break; 164 } 165 default: 166 acpi_enumerate_child_devices(node, result); 167 break; 168 } 169 170 } 171 172 return B_OK; 173 } 174 175 176 static status_t 177 acpi_module_register_child_devices(void* cookie) 178 { 179 device_node* node = (device_node*)cookie; 180 181 status_t status = gDeviceManager->publish_device(node, "acpi/namespace", 182 ACPI_NS_DUMP_DEVICE_MODULE_NAME); 183 if (status != B_OK) 184 return status; 185 status = gDeviceManager->publish_device(node, "acpi/call", 186 ACPI_CALL_DEVICE_MODULE_NAME); 187 if (status != B_OK) 188 return status; 189 190 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 191 dprintf("registering power button\n"); 192 device_attr attrs[] = { 193 // info about device 194 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 195 196 // info about the device 197 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FPB" }}, 198 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }}, 199 200 // consumer specification 201 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }}, 202 { NULL } 203 }; 204 device_node* deviceNode; 205 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 206 NULL, &deviceNode); 207 } 208 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 209 dprintf("registering sleep button\n"); 210 device_attr attrs[] = { 211 // info about device 212 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 213 214 // info about the device 215 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FSB" }}, 216 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }}, 217 218 // consumer specification 219 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }}, 220 { NULL } 221 }; 222 device_node* deviceNode; 223 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 224 NULL, &deviceNode); 225 226 } 227 228 return acpi_enumerate_child_devices(node, "\\"); 229 } 230 231 232 static status_t 233 acpi_module_init(device_node* node, void** _cookie) 234 { 235 *_cookie = node; 236 return B_OK; 237 } 238 239 240 static void 241 acpi_module_uninit(void* cookie) 242 { 243 } 244 245 246 static int32 247 acpi_module_std_ops(int32 op, ...) 248 { 249 switch (op) { 250 case B_MODULE_INIT: 251 { 252 module_info* module; 253 return get_module(B_ACPI_MODULE_NAME, &module); 254 // this serializes our module initialization 255 } 256 257 case B_MODULE_UNINIT: 258 return put_module(B_ACPI_MODULE_NAME); 259 } 260 261 return B_BAD_VALUE; 262 } 263 264 265 static struct acpi_root_info sACPIRootModule = { 266 { 267 { 268 ACPI_ROOT_MODULE_NAME, 269 0, 270 acpi_module_std_ops 271 }, 272 273 acpi_module_supports_device, 274 acpi_module_register_device, 275 acpi_module_init, 276 acpi_module_uninit, 277 acpi_module_register_child_devices, 278 NULL, // rescan devices 279 NULL, // device removed 280 }, 281 282 get_handle, 283 get_name, 284 acquire_global_lock, 285 release_global_lock, 286 install_notify_handler, 287 remove_notify_handler, 288 update_all_gpes, 289 enable_gpe, 290 disable_gpe, 291 clear_gpe, 292 set_gpe, 293 finish_gpe, 294 install_gpe_handler, 295 remove_gpe_handler, 296 install_address_space_handler, 297 remove_address_space_handler, 298 enable_fixed_event, 299 disable_fixed_event, 300 fixed_event_status, 301 reset_fixed_event, 302 install_fixed_event_handler, 303 remove_fixed_event_handler, 304 get_next_entry, 305 get_next_object, 306 get_device, 307 get_device_info, 308 get_object_type, 309 get_object, 310 get_object_typed, 311 ns_handle_to_pathname, 312 evaluate_object, 313 evaluate_method, 314 get_irq_routing_table, 315 get_current_resources, 316 get_possible_resources, 317 set_current_resources, 318 walk_resources, 319 prepare_sleep_state, 320 enter_sleep_state, 321 reboot, 322 get_table 323 }; 324 325 326 module_info* modules[] = { 327 (module_info*)&gACPIModule, 328 (module_info*)&sACPIRootModule, 329 (module_info*)&acpi_ns_dump_module, 330 (module_info*)&gACPIDeviceModule, 331 (module_info*)&embedded_controller_driver_module, 332 (module_info*)&embedded_controller_device_module, 333 (module_info*)&gAcpiCallDeviceModule, 334 NULL 335 }; 336