1 /* 2 * Copyright 2022, Jérôme Duval, jerome.duval@gmail.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <new> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <ACPI.h> 12 #include <ByteOrder.h> 13 #include <condition_variable.h> 14 15 extern "C" { 16 # include "acpi.h" 17 } 18 19 20 #define DRIVER_NAME "ccp_rng_acpi" 21 #include "ccp.h" 22 23 24 typedef struct { 25 ccp_device_info info; 26 acpi_device_module_info* acpi; 27 acpi_device device; 28 29 } ccp_acpi_sim_info; 30 31 32 struct ccp_crs { 33 uint32 addr_bas; 34 uint32 addr_len; 35 }; 36 37 38 static acpi_status 39 ccp_scan_parse_callback(ACPI_RESOURCE *res, void *context) 40 { 41 struct ccp_crs* crs = (struct ccp_crs*)context; 42 43 if (res->Type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { 44 crs->addr_bas = res->Data.FixedMemory32.Address; 45 crs->addr_len = res->Data.FixedMemory32.AddressLength; 46 } 47 48 return B_OK; 49 } 50 51 52 // #pragma mark - 53 54 55 static status_t 56 init_device(device_node* node, void** device_cookie) 57 { 58 CALLED(); 59 status_t status = B_OK; 60 61 ccp_acpi_sim_info* bus = (ccp_acpi_sim_info*)calloc(1, 62 sizeof(ccp_acpi_sim_info)); 63 if (bus == NULL) 64 return B_NO_MEMORY; 65 66 acpi_device_module_info* acpi; 67 acpi_device device; 68 { 69 device_node* acpiParent = gDeviceManager->get_parent_node(node); 70 gDeviceManager->get_driver(acpiParent, (driver_module_info**)&acpi, 71 (void**)&device); 72 gDeviceManager->put_node(acpiParent); 73 } 74 75 bus->acpi = acpi; 76 bus->device = device; 77 78 struct ccp_crs crs; 79 status = acpi->walk_resources(device, (ACPI_STRING)"_CRS", 80 ccp_scan_parse_callback, &crs); 81 if (status != B_OK) { 82 ERROR("Error while getting resouces\n"); 83 free(bus); 84 return status; 85 } 86 if (crs.addr_bas == 0 || crs.addr_len == 0) { 87 TRACE("skipping non configured CCP devices\n"); 88 free(bus); 89 return B_BAD_VALUE; 90 } 91 92 bus->info.base_addr = crs.addr_bas; 93 bus->info.map_size = crs.addr_len; 94 95 *device_cookie = bus; 96 return B_OK; 97 } 98 99 100 static void 101 uninit_device(void* device_cookie) 102 { 103 ccp_acpi_sim_info* bus = (ccp_acpi_sim_info*)device_cookie; 104 free(bus); 105 } 106 107 108 static status_t 109 register_device(device_node* parent) 110 { 111 device_attr attrs[] = { 112 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "CCP ACPI"}}, 113 {B_DEVICE_BUS, B_STRING_TYPE, {.string = "CCP"}}, 114 {B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {.string = CCP_DEVICE_MODULE_NAME}}, 115 {} 116 }; 117 118 return gDeviceManager->register_node(parent, 119 CCP_ACPI_DEVICE_MODULE_NAME, attrs, NULL, NULL); 120 } 121 122 123 static float 124 supports_device(device_node* parent) 125 { 126 const char* bus; 127 128 // make sure parent is a CCP ACPI device node 129 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) 130 < B_OK) { 131 return -1; 132 } 133 134 if (strcmp(bus, "acpi") != 0) 135 return 0.0f; 136 137 // check whether it's really a device 138 uint32 device_type; 139 if (gDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, 140 &device_type, false) != B_OK 141 || device_type != ACPI_TYPE_DEVICE) { 142 return 0.0; 143 } 144 145 // check whether it's a CCP device 146 const char *name; 147 if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &name, 148 false) != B_OK) { 149 return 0.0; 150 } 151 152 if (strcmp(name, "AMDI0C00") == 0) { 153 TRACE("CCP device found! name %s\n", name); 154 return 0.6f; 155 } 156 157 return 0.0f; 158 } 159 160 161 // #pragma mark - 162 163 164 driver_module_info gCcpAcpiDevice = { 165 { 166 CCP_ACPI_DEVICE_MODULE_NAME, 167 0, 168 NULL 169 }, 170 171 supports_device, 172 register_device, 173 init_device, 174 uninit_device, 175 NULL, // register_child_devices, 176 NULL, // rescan 177 NULL, // device removed 178 }; 179 180 181