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 62 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }}, 63 {} 64 }; 65 66 return gDeviceManager->register_node(parent, ACPI_ROOT_MODULE_NAME, attrs, 67 NULL, NULL); 68 } 69 70 71 static status_t 72 acpi_enumerate_child_devices(device_node* node, const char* root) 73 { 74 char result[255]; 75 void* counter = NULL; 76 77 TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root)); 78 79 while (get_next_entry(ACPI_TYPE_ANY, root, result, 80 sizeof(result), &counter) == B_OK) { 81 uint32 type = get_object_type(result); 82 device_node* deviceNode; 83 84 switch (type) { 85 case ACPI_TYPE_POWER: 86 case ACPI_TYPE_PROCESSOR: 87 case ACPI_TYPE_THERMAL: 88 case ACPI_TYPE_DEVICE: { 89 device_attr attrs[16] = { 90 // info about device 91 { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, 92 93 // location on ACPI bus 94 { ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { string: result }}, 95 96 // info about the device 97 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }}, 98 99 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 100 { NULL } 101 }; 102 103 uint32 attrCount = 4; 104 char* hid = NULL; 105 char* cidList[8] = { NULL }; 106 char* uid = NULL; 107 if (type == ACPI_TYPE_DEVICE) { 108 if (get_device_info(result, &hid, (char**)&cidList, 8, 109 &uid) == 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 } 129 uint32 addr; 130 if (get_device_addr(result, &addr) == B_OK) { 131 attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM; 132 attrs[attrCount].type = B_UINT32_TYPE; 133 attrs[attrCount].value.ui32 = addr; 134 attrCount++; 135 } 136 } 137 138 status_t status = gDeviceManager->register_node(node, 139 ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode); 140 free(hid); 141 free(uid); 142 for (int i = 0; cidList[i] != NULL; i++) 143 free(cidList[i]); 144 if (status != B_OK) 145 break; 146 acpi_enumerate_child_devices(deviceNode, result); 147 break; 148 } 149 default: 150 acpi_enumerate_child_devices(node, result); 151 break; 152 } 153 154 } 155 156 return B_OK; 157 } 158 159 160 static status_t 161 acpi_module_register_child_devices(void* cookie) 162 { 163 device_node* node = (device_node*)cookie; 164 165 status_t status = gDeviceManager->publish_device(node, "acpi/namespace", 166 ACPI_NS_DUMP_DEVICE_MODULE_NAME); 167 if (status != B_OK) 168 return status; 169 status = gDeviceManager->publish_device(node, "acpi/call", 170 ACPI_CALL_DEVICE_MODULE_NAME); 171 if (status != B_OK) 172 return status; 173 174 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 175 dprintf("registering power button\n"); 176 device_attr attrs[] = { 177 // info about device 178 { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, 179 180 // info about the device 181 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FPB" }}, 182 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }}, 183 184 // consumer specification 185 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 186 { NULL } 187 }; 188 device_node* deviceNode; 189 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 190 NULL, &deviceNode); 191 } 192 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 193 dprintf("registering sleep button\n"); 194 device_attr attrs[] = { 195 // info about device 196 { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, 197 198 // info about the device 199 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FSB" }}, 200 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }}, 201 202 // consumer specification 203 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 204 { NULL } 205 }; 206 device_node* deviceNode; 207 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 208 NULL, &deviceNode); 209 210 } 211 212 return acpi_enumerate_child_devices(node, "\\"); 213 } 214 215 216 static status_t 217 acpi_module_init(device_node* node, void** _cookie) 218 { 219 *_cookie = node; 220 return B_OK; 221 } 222 223 224 static void 225 acpi_module_uninit(void* cookie) 226 { 227 } 228 229 230 static int32 231 acpi_module_std_ops(int32 op, ...) 232 { 233 switch (op) { 234 case B_MODULE_INIT: 235 { 236 module_info* module; 237 return get_module(B_ACPI_MODULE_NAME, &module); 238 // this serializes our module initialization 239 } 240 241 case B_MODULE_UNINIT: 242 return put_module(B_ACPI_MODULE_NAME); 243 } 244 245 return B_BAD_VALUE; 246 } 247 248 249 static struct acpi_root_info sACPIRootModule = { 250 { 251 { 252 ACPI_ROOT_MODULE_NAME, 253 0, 254 acpi_module_std_ops 255 }, 256 257 acpi_module_supports_device, 258 acpi_module_register_device, 259 acpi_module_init, 260 acpi_module_uninit, 261 acpi_module_register_child_devices, 262 NULL, // rescan devices 263 NULL, // device removed 264 }, 265 266 get_handle, 267 get_name, 268 acquire_global_lock, 269 release_global_lock, 270 install_notify_handler, 271 remove_notify_handler, 272 update_all_gpes, 273 enable_gpe, 274 disable_gpe, 275 clear_gpe, 276 set_gpe, 277 finish_gpe, 278 install_gpe_handler, 279 remove_gpe_handler, 280 install_address_space_handler, 281 remove_address_space_handler, 282 enable_fixed_event, 283 disable_fixed_event, 284 fixed_event_status, 285 reset_fixed_event, 286 install_fixed_event_handler, 287 remove_fixed_event_handler, 288 get_next_entry, 289 get_next_object, 290 get_device, 291 get_device_info, 292 get_object_type, 293 get_object, 294 get_object_typed, 295 ns_handle_to_pathname, 296 evaluate_object, 297 evaluate_method, 298 get_irq_routing_table, 299 get_current_resources, 300 get_possible_resources, 301 set_current_resources, 302 walk_resources, 303 prepare_sleep_state, 304 enter_sleep_state, 305 reboot, 306 get_table 307 }; 308 309 310 module_info* modules[] = { 311 (module_info*)&gACPIModule, 312 (module_info*)&sACPIRootModule, 313 (module_info*)&acpi_ns_dump_module, 314 (module_info*)&gACPIDeviceModule, 315 (module_info*)&embedded_controller_driver_module, 316 (module_info*)&embedded_controller_device_module, 317 (module_info*)&gAcpiCallDeviceModule, 318 NULL 319 }; 320