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 170 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) { 171 dprintf("registering power button\n"); 172 device_attr attrs[] = { 173 // info about device 174 { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, 175 176 // info about the device 177 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FPB" }}, 178 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }}, 179 180 // consumer specification 181 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 182 { NULL } 183 }; 184 device_node* deviceNode; 185 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 186 NULL, &deviceNode); 187 } 188 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) { 189 dprintf("registering sleep button\n"); 190 device_attr attrs[] = { 191 // info about device 192 { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, 193 194 // info about the device 195 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FSB" }}, 196 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }}, 197 198 // consumer specification 199 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, 200 { NULL } 201 }; 202 device_node* deviceNode; 203 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, 204 NULL, &deviceNode); 205 206 } 207 208 return acpi_enumerate_child_devices(node, "\\"); 209 } 210 211 212 static status_t 213 acpi_module_init(device_node* node, void** _cookie) 214 { 215 *_cookie = node; 216 return B_OK; 217 } 218 219 220 static void 221 acpi_module_uninit(void* cookie) 222 { 223 } 224 225 226 static int32 227 acpi_module_std_ops(int32 op, ...) 228 { 229 switch (op) { 230 case B_MODULE_INIT: 231 { 232 module_info* module; 233 return get_module(B_ACPI_MODULE_NAME, &module); 234 // this serializes our module initialization 235 } 236 237 case B_MODULE_UNINIT: 238 return put_module(B_ACPI_MODULE_NAME); 239 } 240 241 return B_BAD_VALUE; 242 } 243 244 245 static struct acpi_root_info sACPIRootModule = { 246 { 247 { 248 ACPI_ROOT_MODULE_NAME, 249 0, 250 acpi_module_std_ops 251 }, 252 253 acpi_module_supports_device, 254 acpi_module_register_device, 255 acpi_module_init, 256 acpi_module_uninit, 257 acpi_module_register_child_devices, 258 NULL, // rescan devices 259 NULL, // device removed 260 }, 261 262 get_handle, 263 get_name, 264 acquire_global_lock, 265 release_global_lock, 266 install_notify_handler, 267 remove_notify_handler, 268 update_all_gpes, 269 enable_gpe, 270 disable_gpe, 271 clear_gpe, 272 set_gpe, 273 finish_gpe, 274 install_gpe_handler, 275 remove_gpe_handler, 276 install_address_space_handler, 277 remove_address_space_handler, 278 enable_fixed_event, 279 disable_fixed_event, 280 fixed_event_status, 281 reset_fixed_event, 282 install_fixed_event_handler, 283 remove_fixed_event_handler, 284 get_next_entry, 285 get_next_object, 286 get_device, 287 get_device_info, 288 get_object_type, 289 get_object, 290 get_object_typed, 291 ns_handle_to_pathname, 292 evaluate_object, 293 evaluate_method, 294 get_irq_routing_table, 295 get_current_resources, 296 get_possible_resources, 297 set_current_resources, 298 walk_resources, 299 prepare_sleep_state, 300 enter_sleep_state, 301 reboot, 302 get_table 303 }; 304 305 306 module_info* modules[] = { 307 (module_info*)&gACPIModule, 308 (module_info*)&sACPIRootModule, 309 (module_info*)&acpi_ns_dump_module, 310 (module_info*)&gACPIDeviceModule, 311 (module_info*)&embedded_controller_driver_module, 312 (module_info*)&embedded_controller_device_module, 313 NULL 314 }; 315