ReactOS 0.4.17-dev-1190-g4c812f4
opregion.c
Go to the documentation of this file.
1#include <uacpi/kernel_api.h>
2
10
11#ifndef UACPI_BAREBONES_MODE
12
14
16{
18}
19
21{
23}
24
27)
28{
29 const uacpi_char *path, *space_string = "<unknown>";
31
33
36 );
38 space_string = uacpi_address_space_to_string(obj->op_region->space);
39
41 "%s (%s) operation region %s: %s",
42 message, space_string, path, uacpi_status_to_string(ret)
43 );
45}
46
47static void trace_region_io(
50)
51{
52 const uacpi_char *path;
53 const uacpi_char *type_str;
54
56 return;
57
58 switch (op) {
60 type_str = "read from";
61 break;
63 type_str = "write to";
64 break;
65 default:
66 type_str = "<INVALID-OP>";
67 }
68
70
71 switch (space) {
76 "write-then-read from [%s] %s[0x%016"UACPI_PRIX64"] = "
77 "<buffer of %zu bytes>", path,
79 UACPI_FMT64(offset), data.buffer.length
80 );
81 break;
85 "%s [%s] %s[0x%016"UACPI_PRIX64"] = "
86 "<buffer of %zu bytes>", type_str, path,
88 UACPI_FMT64(offset), data.buffer.length
89 );
90 break;
93 "%s [%s] %s pins[%u..%u] = 0x%"UACPI_PRIX64,
95 field->pin_offset, (field->pin_offset + field->bit_length) - 1,
96 UACPI_FMT64(*data.integer)
97 );
98 break;
99 default:
101 "%s [%s] (%d bytes) %s[0x%016"UACPI_PRIX64"] = 0x%"UACPI_PRIX64,
102 type_str, path, field->access_width_bytes,
105 );
106 break;
107 }
108
110}
111
113{
117 return UACPI_FALSE;
118
119 return UACPI_TRUE;
120}
121
122// Returns UACPI_STATUS_NOT_FOUND if 'scope' has no _REG
124 uacpi_namespace_node *scope, uacpi_u16 space, uacpi_u8 connection_code
125)
126{
128 uacpi_namespace_node *reg_node;
129 uacpi_object_array method_args;
130 uacpi_object *reg_obj, *args[2];
131
133 scope, "_REG", UACPI_SHOULD_LOCK_NO,
135 );
137 return ret;
138
141 );
142 if (uacpi_unlikely(reg_obj == UACPI_NULL))
143 return UACPI_STATUS_OK;
144
146 if (uacpi_unlikely(args[0] == UACPI_NULL))
148
150 if (uacpi_unlikely(args[1] == UACPI_NULL)) {
153 }
154
155 args[0]->integer = space;
156 args[1]->integer = connection_code;
157 method_args.objects = args;
158 method_args.count = 2;
159
161 reg_node, reg_obj->method, &method_args, UACPI_NULL
162 );
164 const uacpi_char *path;
165
168 "error during _REG execution for %s (%s): %s", path,
170 );
172 }
173
176 return ret;
177}
178
181)
182{
184
185 if (node == uacpi_namespace_root())
186 return g_uacpi_rt_ctx.root_object->address_space_handlers;
187
189 if (uacpi_unlikely(object == UACPI_NULL))
190 return UACPI_NULL;
191
192 switch (object->type) {
196 return object->address_space_handlers;
197 default:
198 return UACPI_NULL;
199 }
200}
201
205)
206{
208
209 while (handler) {
210 if (handler->space == space)
211 return handler;
212
213 handler = handler->next;
214 }
215
216 return UACPI_NULL;
217}
218
221)
222{
225
226 if (parent == region)
227 // This is the last attached region, it has no previous link
228 return region;
229
230 while (parent->next != region) {
231 parent = parent->next;
232
234 return UACPI_NULL;
235 }
236
237 return parent;
238}
239
241{
246 uacpi_region_attach_data attach_data = { 0 };
247
250
253 );
256
257 region = obj->op_region;
258
259 if (region->handler == UACPI_NULL)
261 if (region->state_flags & UACPI_OP_REGION_STATE_ATTACHED)
262 return UACPI_STATUS_OK;
263
264 handler = region->handler;
265 attach_data.region_node = node;
266
267 switch (region->space) {
269 if (region->length) {
270 region->internal_buffer = uacpi_kernel_alloc_zeroed(region->length);
271 if (uacpi_unlikely(region->internal_buffer == UACPI_NULL))
273 }
274
275 attach_data.pcc_info.buffer.bytes = region->internal_buffer;
276 attach_data.pcc_info.buffer.length = region->length;
277 attach_data.pcc_info.subspace_id = region->offset;
278 break;
280 attach_data.gpio_info.num_pins = region->length;
281 break;
282 default:
283 attach_data.generic_info.base = region->offset;
284 attach_data.generic_info.length = region->length;
285 break;
286 }
287
288 attach_data.handler_context = handler->user_context;
289
290 /*
291 * The handler is invoked with the namespace unlocked, and is free to do
292 * whatever it wants in the meantime, which includes evaluating a method
293 * that gets rid of the region, as well as uninstalling itself. Keep both
294 * of them alive until we're done.
295 */
298
300 ret = handler->callback(UACPI_REGION_OP_ATTACH, &attach_data);
302
304 goto out;
305
306 if (uacpi_unlikely(region->handler != handler)) {
307 uacpi_region_detach_data detach_data = { 0 };
308
309 /*
310 * The region was taken away from the handler before it was done
311 * attaching it. This is not something that the handler was told
312 * about, as the region was not attached at the time, so do it now:
313 * a region that was attached is always detached as well.
314 */
315 detach_data.region_node = node;
316 detach_data.region_context = attach_data.out_region_context;
317 detach_data.handler_context = handler->user_context;
318
320 handler->callback(UACPI_REGION_OP_DETACH, &detach_data);
322
324 goto out;
325 }
326
328 uacpi_region_detach_data detach_data = { 0 };
329
330 /*
331 * The region was attached once more in the meantime, which is what
332 * happens if the handler ends up accessing the region that it's still
333 * in the middle of attaching. It only gets to be attached once, and
334 * that one was there first, so this is the one to be undone.
335 */
336 detach_data.region_node = node;
337 detach_data.region_context = attach_data.out_region_context;
338 detach_data.handler_context = handler->user_context;
339
341 handler->callback(UACPI_REGION_OP_DETACH, &detach_data);
343
344 goto out;
345 }
346
348 region->user_context = attach_data.out_region_context;
349
350out:
353 return ret;
354}
355
358)
359{
360 region->handler = handler;
362
363 region->next = handler->regions;
364 handler->regions = region;
365}
366
367enum unreg {
370};
371
374)
375{
380 uacpi_bool was_attached;
381
384 );
386 return;
387
388 region = obj->op_region;
389
390 handler = region->handler;
391 if (handler == UACPI_NULL)
392 return;
393
394 // We're in the middle of doing this already, see below
396 return;
397
400 uacpi_error("operation region @%p not in the handler@%p list(?)",
401 region, handler);
402 goto out;
403 } else if (link == region) {
404 link = link->next;
405 handler->regions = link;
406 } else {
407 link->next = region->next;
408 }
409
410out:
411 /*
412 * Both the _REG method and the handler are free to do whatever they want
413 * to the region once we invoke them, which includes getting rid of it,
414 * e.g. by overwriting it via CopyObject. That leads right back here, so
415 * make sure there's nothing left to do if it happens. It's also up to us
416 * to keep the region alive until we're done.
417 */
419
420 /*
421 * This is done while the region still has its handler, as _REG is what
422 * lets AML know that it's about to lose access to the region, and is
423 * thus its last chance to make use of it.
424 */
425 if ((region->state_flags & UACPI_OP_REGION_STATE_REG_EXECUTED) &&
426 unreg == UNREG_YES) {
427 region->state_flags &= ~UACPI_OP_REGION_STATE_REG_EXECUTED;
429
430 run_reg(node->parent, region->space, ACPI_REG_DISCONNECT);
431
432 region->state_flags &= ~UACPI_OP_REGION_STATE_DISCONNECTING;
433 }
434
435 /*
436 * The region has no handler as far as anyone else is concerned from this
437 * point on, which includes whatever the handler decides to do while it's
438 * detaching it. Note that the region might've only been attached by the
439 * _REG method above, so this is not something to check any earlier.
440 */
441 was_attached = region->state_flags & UACPI_OP_REGION_STATE_ATTACHED;
442
443 region->handler = UACPI_NULL;
444 region->state_flags &= ~UACPI_OP_REGION_STATE_ATTACHED;
445
446 if (was_attached) {
447 uacpi_region_detach_data detach_data = { 0 };
448
449 detach_data.region_node = node;
450 detach_data.region_context = region->user_context;
451 detach_data.handler_context = handler->user_context;
452
455
456 ret = handler->callback(UACPI_REGION_OP_DETACH, &detach_data);
457
460
463 node, "error during handler detach for", ret
464 );
465 }
466 }
467
470}
471
473{
475
476 /*
477 * Drop the namespace lock, and reacquire it after the opregion lock
478 * so we keep the ordering with user API.
479 */
481
484 return ret;
485}
486
488{
490}
491
493{
495 return;
496
498
500}
501
504)
505{
507}
508
512};
513
517
518 // The handlers of the device that the above is installed for
520};
521
523{
524 return find_handler(ctx->handlers, ctx->handler->space) == ctx->handler;
525}
526
529)
530{
531 struct opregion_iter_ctx *ctx = opaque;
534
536
539 uacpi_operation_region *region = object->op_region;
540
541 if (region->space != ctx->handler->space)
543
544 if (ctx->action == OPREGION_ITER_ACTION_INSTALL) {
545 if (region->handler) {
547
548 /*
549 * The previous handler was invoked by the above, and might've
550 * uninstalled the one that we're in the middle of installing.
551 * There's nothing left for us to do in that case.
552 */
555
556 /*
557 * The previous handler was just told that the region is being
558 * detached, and is free to have done whatever it wanted to it
559 * in response, which includes getting rid of it. Make sure
560 * that there's still something to install the handler for.
561 */
564 );
565 if (uacpi_unlikely(object == UACPI_NULL))
567
568 region = object->op_region;
569 if (uacpi_unlikely(region->space != ctx->handler->space ||
570 region->handler != UACPI_NULL))
572 }
573
575 } else {
576 /*
577 * A region that has no handler is not ours to uninstall, and is
578 * nothing to complain about either: it's one that was left this
579 * way by a closer handler that is gone by now, or one that is in
580 * the middle of being detached by whoever has called us.
581 */
582 if (region->handler == UACPI_NULL)
584
585 if (uacpi_unlikely(region->handler != ctx->handler)) {
587 node, "handler mismatch for",
589 );
591 }
592
594 }
595
597 }
598
600 if (handlers == UACPI_NULL)
602
603 // Device already has a handler for this space installed
604 if (find_handler(handlers, ctx->handler->space) != UACPI_NULL)
606
608}
609
614};
615
618)
619{
620 struct reg_run_ctx *ctx = opaque;
624
626
628 region = obj->op_region;
629
630 if (region->space != ctx->space)
632
635
636 /*
637 * A region that has no handler is not accessible, so there's nothing for
638 * it to be connected to. The same goes for one that is in the middle of
639 * being disconnected, as its handler is about to be gone.
640 */
641 if (region->handler == UACPI_NULL ||
644
645 /*
646 * The _REG method is free to do whatever it wants to the region, which
647 * includes getting rid of it, e.g. by overwriting it via CopyObject. Keep
648 * it alive until we're done with it.
649 */
651
652 ret = run_reg(node->parent, region->space, ACPI_REG_CONNECT);
654 goto out;
655
657 ctx->reg_executed++;
658
660 ctx->reg_errors++;
661
662out:
665}
666
667/*
668 * Firmware might expect _REG to be executed for an address space that it has
669 * no regions of, e.g. for an EC that it only ever accesses via SystemMemory.
670 */
671static void run_orphan_reg(
673)
674{
676
677 for (;;) {
679
682 );
683 if (ret != UACPI_STATUS_OK)
684 /*
685 * No opregion child of this device is of this address space, so
686 * this _REG is indeed orphan as far as we're concerned.
687 */
688 break;
689
690 if (uacpi_namespace_node_get_object(child)->op_region->space == space)
691 return;
692 }
693
695}
696
699)
700{
702
704 if (handlers == UACPI_NULL)
705 return UACPI_FALSE;
706
708}
709
712)
713{
714 static const uacpi_char *const ec_ids[] = { "PNP0C09", UACPI_NULL };
715 uacpi_namespace_node *device_node = opaque;
716 uacpi_bool has_own_handler = UACPI_FALSE;
717
719
722
723 if (node != device_node) {
724 has_own_handler = node_has_handler(
726 );
727 }
729
730 // That handler takes care of everything underneath it
731 if (has_own_handler)
733
734 // This might execute AML, so it's done with the namespace unlocked
735 if (!uacpi_device_matches_pnp_id(node, ec_ids))
737
740
741 // The handler might've been uninstalled while the namespace was unlocked
742 has_own_handler = node_has_handler(
744 );
745
746 if (has_own_handler)
748
751}
752
753/*
754 * An embedded controller is looked for by its PNP id, as the handler that it
755 * uses is not necessarily installed to the EC device itself, e.g. it might be
756 * installed to the root instead, so that the regions outside of the EC device
757 * are covered as well.
758 *
759 * Must be called with the namespace write-locked. The lock is dropped while
760 * the devices are looked at, and is held again by the time this returns.
761 */
763{
765
767
768 decision = do_run_orphan_ec_reg(device_node, device_node, 0);
769 if (decision == UACPI_ITERATION_DECISION_CONTINUE) {
771 device_node, do_run_orphan_ec_reg, UACPI_NULL,
774 );
775 }
776
778}
779
782)
783{
785 struct reg_run_ctx ctx = { 0 };
786
787 ctx.space = space;
788
792
795
796 /*
797 * Registering non-permanent opregions is handled separately and should
798 * not be done by us.
799 */
801 device_node, do_run_reg, UACPI_NULL,
804 );
805
807 "activated all '%s' opregions controlled by '%.4s', "
808 "%zu _REG() calls (%zu errors)",
810 device_node->name.text, ctx.reg_executed, ctx.reg_errors
811 );
812
814 run_orphan_ec_regs(device_node);
815
816 /*
817 * Unlike an EC, a GPIO controller has no common PNP id to be looked for
818 * by. Its handler is normally installed to the controller itself though,
819 * so that is the only one that is checked.
820 */
822 run_orphan_reg(device_node, space);
823
824 return UACPI_STATUS_OK;
825}
826
829)
830{
831 uacpi_object *handlers_obj;
832
833 if (node == uacpi_namespace_root())
834 return g_uacpi_rt_ctx.root_object->address_space_handlers;
835
837 node,
840 );
841 if (uacpi_unlikely(handlers_obj == UACPI_NULL))
842 return UACPI_NULL;
843
844 return handlers_obj->address_space_handlers;
845}
846
848 uacpi_namespace_node *device_node,
850)
851{
853
855
857 return UACPI_STATUS_OK;
858
861 return ret;
862
866 return ret;
867 }
868
869 if (uacpi_unlikely(extract_handlers(device_node) == UACPI_NULL)) {
871 goto out;
872 }
873
874 ret = reg_all_opregions(device_node, space);
875
876out:
879 return ret;
880}
881
886)
887{
890 uacpi_address_space_handler *this_handler, *new_handler;
891 struct opregion_iter_ctx iter_ctx;
892
895 return ret;
896
900 return ret;
901 }
902
903 handlers = extract_handlers(device_node);
906 goto out;
907 }
908
909 this_handler = find_handler(handlers, space);
910 if (this_handler != UACPI_NULL) {
912 goto out;
913 }
914
915 new_handler = uacpi_kernel_alloc(sizeof(*new_handler));
916 if (new_handler == UACPI_NULL) {
918 goto out;
919 }
920 uacpi_shareable_init(new_handler);
921
922 new_handler->next = handlers->head;
923 new_handler->space = space;
924 new_handler->user_context = handler_context;
925 new_handler->callback = handler;
926 new_handler->regions = UACPI_NULL;
927 new_handler->flags = flags;
928 handlers->head = new_handler;
929
930 /*
931 * The handlers that some of the regions already have are invoked as the
932 * regions are taken away from them below, and are free to do whatever they
933 * want in response, which includes uninstalling the handler that we have
934 * just put on the list. Keep it alive until we're done.
935 */
936 uacpi_shareable_ref(new_handler);
937
938 iter_ctx.handler = new_handler;
939 iter_ctx.handlers = handlers;
941
945 UACPI_PERMANENT_ONLY_YES, &iter_ctx
946 );
947
948 if (uacpi_unlikely(!handler_is_installed(&iter_ctx))) {
950 goto out_unref;
951 }
952
954 goto out_unref;
955
956 /*
957 * Installing an early address space handler, obviously not possible to
958 * execute any _REG methods here. Just return and hope that it is either
959 * a global address space handler, or a handler installed by a user who
960 * will run uacpi_reg_all_opregions manually after loading/initializing
961 * the namespace.
962 */
964 goto out_unref;
965
966 // Init level is NAMESPACE_INITIALIZED, so we can safely run _REG now
967 ret = reg_all_opregions(device_node, space);
968
969out_unref:
971out:
974 return ret;
975}
976
980)
981{
983 device_node, space, handler, handler_context, 0
984 );
985}
986
990)
991{
994 uacpi_address_space_handler *this_handler, *prev_handler;
995 struct opregion_iter_ctx iter_ctx;
996
999 return ret;
1000
1004 return ret;
1005 }
1006
1007 handlers = extract_handlers(device_node);
1010 goto out;
1011 }
1012
1013 this_handler = find_handler(handlers, space);
1014 if (uacpi_unlikely(this_handler == UACPI_NULL)) {
1016 goto out;
1017 }
1018
1019 // This is somebody else's handler, and is thus not ours to uninstall
1020 if (uacpi_unlikely(this_handler->callback != handler)) {
1022 goto out;
1023 }
1024
1025 /*
1026 * Both the handler and the _REG methods are invoked as the regions are
1027 * taken away below, and are free to do whatever they want in response.
1028 * Make sure that the handler is no longer there to be found by then, be
1029 * it by a region that is created in the meantime, or by the handler
1030 * itself in case it decides to uninstall itself as it's told to detach
1031 * a region. The reference that the device had is now ours, which is what
1032 * keeps the handler alive until we're done.
1033 */
1034 prev_handler = handlers->head;
1035
1036 // Are we the last linked handler?
1037 if (prev_handler == this_handler) {
1038 handlers->head = this_handler->next;
1039 } else {
1040 // Nope, we're somewhere in the middle. Do a search.
1041 while (prev_handler->next != this_handler)
1042 prev_handler = prev_handler->next;
1043
1044 prev_handler->next = this_handler->next;
1045 }
1046
1047 iter_ctx.handler = this_handler;
1048 iter_ctx.handlers = handlers;
1050
1054 UACPI_PERMANENT_ONLY_NO, &iter_ctx
1055 );
1056
1058
1059out:
1062 return ret;
1063}
1064
1066{
1068 uacpi_namespace_node *parent = node->parent;
1072
1075 return ret;
1076
1079
1080 while (parent) {
1082 if (handlers != UACPI_NULL) {
1084
1085 if (handler != UACPI_NULL) {
1088 break;
1089 }
1090 }
1091
1092 parent = parent->parent;
1093 }
1094
1095 if (ret != UACPI_STATUS_OK)
1096 goto out;
1097 if (!space_needs_reg(region->space))
1098 goto out;
1100 goto out;
1101
1102 if (run_reg(node->parent, region->space, ACPI_REG_CONNECT) !=
1105
1106out:
1108 return ret;
1109}
1110
1112{
1113 switch (space) {
1119 return UACPI_TRUE;
1120 default:
1121 return UACPI_FALSE;
1122 }
1123}
1124
1126{
1129}
1130
1131/*
1132 * A command is sent over a PCC subspace as soon as its command field is
1133 * written, which is any field that starts where the command does: it doesn't
1134 * have to be as wide, nor is it limited to it.
1135 *
1136 * A field is written one access at a time though, and a PCC one is only
1137 * supposed to be accessed byte by byte, so what was written is not all there
1138 * until the last access of the field. That's the only one to send it for.
1139 */
1140#define PCC_COMMAND_OFFSET 8
1141#define PCC_COMMAND_SIZE 4
1142
1145)
1146{
1147 uacpi_u32 access_bits, last_bit, last_offset;
1148
1149 if (field->byte_offset < PCC_COMMAND_OFFSET ||
1150 field->byte_offset >= PCC_COMMAND_OFFSET + PCC_COMMAND_SIZE)
1151 return UACPI_FALSE;
1152
1153 access_bits = field->access_width_bytes * 8;
1154 last_bit = field->bit_offset_within_first_byte + field->bit_length - 1;
1155
1156 last_offset = field->byte_offset;
1157 last_offset += (last_bit / access_bits) * field->access_width_bytes;
1158
1159 return offset == last_offset;
1160}
1161
1165)
1166{
1172 uacpi_u64 abs_offset, offset_end = offset;
1173 uacpi_bool is_oob = UACPI_FALSE;
1174 uacpi_region_op orig_op = op;
1175
1176 union {
1184 } handler_data;
1185
1186 ret = uacpi_opregion_attach(field->region);
1189 field->region, "unable to attach", ret
1190 );
1191 return ret;
1192 }
1193
1196 );
1199
1200 region = obj->op_region;
1201 space = region->space;
1202 handler = region->handler;
1203
1204 abs_offset = region->offset + offset;
1205 offset_end += field->access_width_bytes;
1206
1208 is_oob = region->length < offset_end || abs_offset < offset;
1209 if (uacpi_unlikely(is_oob)) {
1210 const uacpi_char *path;
1211
1214 "out-of-bounds access to opregion %s[0x%"UACPI_PRIX64"->"
1215 "0x%"UACPI_PRIX64"] at 0x%"UACPI_PRIX64" (idx=%u, width=%d)",
1216 path, UACPI_FMT64(region->offset),
1217 UACPI_FMT64(region->offset + region->length),
1218 UACPI_FMT64(abs_offset), offset, field->access_width_bytes
1219 );
1222 }
1223
1224 handler_data.rw.region_context = region->user_context;
1225 handler_data.rw.handler_context = handler->user_context;
1226
1227 switch (region->space) {
1230
1231 cursor = region->internal_buffer + offset;
1232
1233 /*
1234 * Reads from PCC just return the current contents of the internal
1235 * buffer.
1236 */
1237 if (op == UACPI_REGION_OP_READ) {
1239 data.integer, cursor, sizeof(*data.integer),
1240 field->access_width_bytes
1241 );
1242 goto io_done;
1243 }
1244
1245 uacpi_memcpy(cursor, data.integer, field->access_width_bytes);
1246
1247 /*
1248 * Dispatch a PCC send command if this was a write to the command field
1249 *
1250 * ACPI 6.5: 14.3. Extended PCC Subspace Shared Memory Region
1251 *
1252 * Note that a PCC region covers whatever follows the signature that
1253 * the shared memory region starts with, so the offset of every field
1254 * is 4 bytes less than what it is there.
1255 */
1257 uacpi_memzero(&handler_data.pcc.buffer, sizeof(handler_data.pcc.buffer));
1258 handler_data.pcc.buffer.bytes = region->internal_buffer;
1259 handler_data.pcc.buffer.length = region->length;
1260
1262 break;
1263 }
1264
1265 // No dispatch needed, IO is done
1266 goto io_done;
1267 }
1269 handler_data.gpio.pin_offset = field->pin_offset;
1270 handler_data.gpio.num_pins = field->bit_length;
1271 handler_data.gpio.value = *data.integer;
1272
1274 field->connection, &handler_data.gpio.connection
1275 );
1277 goto io_done;
1278
1281 break;
1283 handler_data.ipmi.in_out_message = data.buffer;
1284 handler_data.ipmi.command = abs_offset;
1286 break;
1288 handler_data.ffixedhw.in_out_message = data.buffer;
1289 handler_data.ffixedhw.command = abs_offset;
1291 break;
1293 handler_data.prm.in_out_message = data.buffer;
1295 break;
1299 field->connection, &handler_data.serial.connection
1300 );
1302 goto io_done;
1303
1304 handler_data.serial.command = abs_offset;
1305 handler_data.serial.in_out_buffer = data.buffer;
1306 handler_data.serial.access_attribute = field->attributes;
1307
1308 switch (field->attributes) {
1312 handler_data.serial.access_length = field->access_length;
1313 break;
1314 default:
1315 handler_data.serial.access_length = 0;
1316 }
1317
1320 break;
1321 default:
1322 handler_data.rw.byte_width = field->access_width_bytes;
1323 handler_data.rw.offset = abs_offset;
1324 handler_data.rw.value = *data.integer;
1325 break;
1326 }
1327
1330
1331 ret = handler->callback(op, &handler_data);
1332
1335
1336io_done:
1338 uacpi_trace_region_error(field->region, "unable to perform IO", ret);
1339 return ret;
1340 }
1341
1342 if (orig_op == UACPI_REGION_OP_READ) {
1343 switch (space) {
1350 break;
1352 *data.integer = handler_data.gpio.value;
1353 break;
1354 default:
1355 *data.integer = handler_data.rw.value;
1356 break;
1357 }
1358 }
1359
1360 trace_region_io(field, space, abs_offset, orig_op, data);
1361 return ret;
1362}
1363
1364#endif // !UACPI_BAREBONES_MODE
#define ACPI_REG_CONNECT
Definition: actypes.h:890
#define ACPI_REG_DISCONNECT
Definition: actypes.h:889
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:265
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:253
uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
Definition: mutex.c:285
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:305
const WCHAR * link
Definition: db.cpp:998
UINT op
Definition: effect.c:235
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7708
#define UACPI_ENSURE_INIT_LEVEL_AT_LEAST(lvl)
Definition: context.h:127
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:18
static uacpi_bool uacpi_should_log(enum uacpi_log_level lvl)
Definition: context.h:95
#define UACPI_UNUSED(x)
Definition: helpers.h:7
#define uacpi_trace(...)
Definition: log.h:33
#define uacpi_error(...)
Definition: log.h:36
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:294
uacpi_status uacpi_namespace_do_for_each_child(uacpi_namespace_node *parent, uacpi_iteration_callback descending_callback, uacpi_iteration_callback ascending_callback, uacpi_object_type_bits, uacpi_u32 max_depth, enum uacpi_should_lock, enum uacpi_permanent_only, void *user)
Definition: namespace.c:841
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:51
uacpi_object * uacpi_namespace_node_get_object_typed(const uacpi_namespace_node *node, uacpi_object_type_bits type_mask)
Definition: namespace.c:661
@ UACPI_PERMANENT_ONLY_YES
Definition: namespace.h:94
@ UACPI_PERMANENT_ONLY_NO
Definition: namespace.h:93
uacpi_status uacpi_namespace_node_next_typed_unlocked(uacpi_namespace_node *parent, uacpi_namespace_node **iter, uacpi_object_type_bits type_mask)
Definition: namespace.c:967
uacpi_bool uacpi_namespace_node_is_dangling(uacpi_namespace_node *node)
Definition: namespace.c:340
uacpi_object * uacpi_namespace_node_get_object(const uacpi_namespace_node *node)
Definition: namespace.c:653
@ UACPI_SHOULD_LOCK_YES
Definition: namespace.h:99
@ UACPI_SHOULD_LOCK_NO
Definition: namespace.h:98
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
@ UACPI_MAY_SEARCH_ABOVE_PARENT_NO
Definition: namespace.h:88
uacpi_status uacpi_namespace_node_resolve(uacpi_namespace_node *scope, const uacpi_char *path, enum uacpi_should_lock, enum uacpi_may_search_above_parent, enum uacpi_permanent_only, uacpi_namespace_node **out_node)
Definition: namespace.c:498
#define uacpi_memzero(ptr, size)
Definition: stdlib.h:99
#define uacpi_kernel_alloc_zeroed
Definition: stdlib.h:127
#define uacpi_memcpy
Definition: stdlib.h:34
void uacpi_memcpy_zerout(void *dst, const void *src, uacpi_size dst_size, uacpi_size src_size)
Definition: stdlib.c:112
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:328
#define UACPI_OP_REGION_STATE_REG_EXECUTED
Definition: types.h:111
void uacpi_address_space_handler_unref(uacpi_address_space_handler *handler)
Definition: types.c:552
#define UACPI_ADDRESS_SPACE_HANDLER_DEFAULT
Definition: types.h:73
#define UACPI_OP_REGION_STATE_ATTACHED
Definition: types.h:114
#define UACPI_OP_REGION_STATE_DISCONNECTING
Definition: types.h:117
@ UACPI_LOG_TRACE
Definition: log.h:18
#define UACPI_MAX_DEPTH_ANY
Definition: namespace.h:102
const uacpi_char * uacpi_namespace_node_generate_absolute_path(const uacpi_namespace_node *node)
Definition: namespace.c:1053
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
#define uacpi_likely(expr)
Definition: compiler.h:89
#define uacpi_unlikely(expr)
Definition: compiler.h:88
#define UACPI_PRIX64
Definition: types.h:61
size_t uacpi_size
Definition: types.h:37
uint32_t uacpi_u32
Definition: types.h:21
bool uacpi_bool
Definition: types.h:31
#define UACPI_FALSE
Definition: types.h:30
uint64_t uacpi_u64
Definition: types.h:22
char uacpi_char
Definition: types.h:44
uint16_t uacpi_u16
Definition: types.h:20
#define UACPI_NULL
Definition: types.h:33
uint8_t uacpi_u8
Definition: types.h:19
#define UACPI_FMT64(val)
Definition: types.h:62
#define UACPI_TRUE
Definition: types.h:29
#define uacpi_unlikely_error(expr)
Definition: status.h:50
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX
Definition: status.h:40
@ UACPI_STATUS_INTERNAL_ERROR
Definition: status.h:21
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
@ UACPI_STATUS_NAMESPACE_NODE_DANGLING
Definition: status.h:24
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_ALREADY_EXISTS
Definition: status.h:20
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:61
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:733
const uacpi_char * uacpi_address_space_to_string(uacpi_address_space space)
Definition: types.c:12
uacpi_iteration_decision
Definition: types.h:28
@ UACPI_ITERATION_DECISION_BREAK
Definition: types.h:30
@ UACPI_ITERATION_DECISION_NEXT_PEER
Definition: types.h:39
@ UACPI_ITERATION_DECISION_CONTINUE
Definition: types.h:29
@ UACPI_OBJECT_METHOD_BIT
Definition: types.h:142
@ UACPI_OBJECT_PROCESSOR_BIT
Definition: types.h:146
@ UACPI_OBJECT_OPERATION_REGION_BIT
Definition: types.h:144
@ UACPI_OBJECT_THERMAL_ZONE_BIT
Definition: types.h:147
@ UACPI_OBJECT_ANY_BIT
Definition: types.h:152
@ UACPI_OBJECT_DEVICE_BIT
Definition: types.h:140
@ UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
Definition: types.h:493
@ UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
Definition: types.h:494
@ UACPI_ACCESS_ATTRIBUTE_BYTES
Definition: types.h:490
@ UACPI_INIT_LEVEL_NAMESPACE_LOADED
Definition: types.h:78
uacpi_status(* uacpi_region_handler)(uacpi_region_op op, uacpi_handle op_data)
Definition: types.h:521
@ UACPI_OBJECT_PROCESSOR
Definition: types.h:123
@ UACPI_OBJECT_DEVICE
Definition: types.h:117
@ UACPI_OBJECT_INTEGER
Definition: types.h:112
@ UACPI_OBJECT_OPERATION_REGION
Definition: types.h:121
@ UACPI_OBJECT_THERMAL_ZONE
Definition: types.h:124
uacpi_region_op
Definition: types.h:373
@ UACPI_REGION_OP_FFIXEDHW_COMMAND
Definition: types.h:394
@ UACPI_REGION_OP_PCC_SEND
Definition: types.h:384
@ UACPI_REGION_OP_GPIO_READ
Definition: types.h:387
@ UACPI_REGION_OP_SERIAL_WRITE
Definition: types.h:401
@ UACPI_REGION_OP_PRM_COMMAND
Definition: types.h:397
@ UACPI_REGION_OP_DETACH
Definition: types.h:377
@ UACPI_REGION_OP_GPIO_WRITE
Definition: types.h:388
@ UACPI_REGION_OP_SERIAL_READ
Definition: types.h:400
@ UACPI_REGION_OP_WRITE
Definition: types.h:381
@ UACPI_REGION_OP_READ
Definition: types.h:380
@ UACPI_REGION_OP_IPMI_COMMAND
Definition: types.h:391
@ UACPI_REGION_OP_ATTACH
Definition: types.h:375
uacpi_address_space
Definition: types.h:42
@ UACPI_ADDRESS_SPACE_IPMI
Definition: types.h:50
@ UACPI_ADDRESS_SPACE_PRM
Definition: types.h:54
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:43
@ UACPI_ADDRESS_SPACE_GENERAL_PURPOSE_IO
Definition: types.h:51
@ UACPI_ADDRESS_SPACE_FFIXEDHW
Definition: types.h:55
@ UACPI_ADDRESS_SPACE_TABLE_DATA
Definition: types.h:58
@ UACPI_ADDRESS_SPACE_EMBEDDED_CONTROLLER
Definition: types.h:46
@ UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS
Definition: types.h:52
@ UACPI_ADDRESS_SPACE_SYSTEM_IO
Definition: types.h:44
@ UACPI_ADDRESS_SPACE_SMBUS
Definition: types.h:47
@ UACPI_ADDRESS_SPACE_PCC
Definition: types.h:53
uacpi_status uacpi_object_get_string_or_buffer(uacpi_object *, uacpi_data_view *out)
Definition: types.c:1058
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:761
return ret
Definition: mutex.c:147
r parent
Definition: btrfs.c:3010
static xmlCharEncodingHandlerPtr * handlers
Definition: encoding.c:1380
uint32_t serial
Definition: fsck.fat.h:29
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
GLbitfield flags
Definition: glext.h:7161
const char cursor[]
Definition: icontest.c:13
void uacpi_free_dynamic_string(const uacpi_char *str)
Definition: utilities.c:1148
uacpi_status uacpi_execute_control_method(uacpi_namespace_node *scope, uacpi_control_method *method, const uacpi_object_array *args, uacpi_object **ret)
Definition: interpreter.c:6479
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
static HWND child
Definition: cursoricon.c:298
static uacpi_operation_region * find_previous_region_link(uacpi_operation_region *region)
Definition: opregion.c:219
uacpi_status uacpi_install_address_space_handler_with_flags(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler, uacpi_handle handler_context, uacpi_u16 flags)
Definition: opregion.c:882
void uacpi_release_opregion_lock(void)
Definition: opregion.c:487
uacpi_status uacpi_install_address_space_handler(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler, uacpi_handle handler_context)
Definition: opregion.c:977
#define PCC_COMMAND_OFFSET
Definition: opregion.c:1140
static uacpi_status reg_all_opregions(uacpi_namespace_node *device_node, enum uacpi_address_space space)
Definition: opregion.c:780
#define PCC_COMMAND_SIZE
Definition: opregion.c:1141
static void trace_region_io(uacpi_field_unit *field, uacpi_address_space space, uacpi_u64 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
Definition: opregion.c:47
static uacpi_address_space_handler * find_handler(uacpi_address_space_handlers *handlers, enum uacpi_address_space space)
Definition: opregion.c:202
void uacpi_trace_region_error(uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret)
Definition: opregion.c:25
uacpi_status uacpi_upgrade_to_opregion_lock(void)
Definition: opregion.c:472
uacpi_status uacpi_initialize_opregion(void)
Definition: opregion.c:15
static void region_uninstall_handler(uacpi_namespace_node *node, enum unreg unreg)
Definition: opregion.c:372
static uacpi_iteration_decision do_install_or_uninstall_handler(uacpi_handle opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:527
static uacpi_bool space_needs_reg(enum uacpi_address_space space)
Definition: opregion.c:112
static uacpi_bool handler_is_installed(struct opregion_iter_ctx *ctx)
Definition: opregion.c:522
static void run_orphan_reg(uacpi_namespace_node *node, enum uacpi_address_space space)
Definition: opregion.c:671
static uacpi_bool space_needs_bounds_checking(uacpi_address_space space)
Definition: opregion.c:1125
static uacpi_address_space_handlers * extract_handlers(uacpi_namespace_node *node)
Definition: opregion.c:827
static void region_install_handler(uacpi_operation_region *region, uacpi_address_space_handler *handler)
Definition: opregion.c:356
void uacpi_opregion_uninstall_handler(uacpi_namespace_node *node)
Definition: opregion.c:492
uacpi_status uacpi_reg_all_opregions(uacpi_namespace_node *device_node, enum uacpi_address_space space)
Definition: opregion.c:847
uacpi_status uacpi_opregion_attach(uacpi_namespace_node *node)
Definition: opregion.c:240
static uacpi_bool pcc_write_completes_command(uacpi_field_unit *field, uacpi_u32 offset)
Definition: opregion.c:1143
unreg
Definition: opregion.c:367
@ UNREG_YES
Definition: opregion.c:369
@ UNREG_NO
Definition: opregion.c:368
uacpi_address_space_handlers * uacpi_node_get_address_space_handlers(uacpi_namespace_node *node)
Definition: opregion.c:179
uacpi_status uacpi_uninstall_address_space_handler(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler)
Definition: opregion.c:987
opregion_iter_action
Definition: opregion.c:509
@ OPREGION_ITER_ACTION_UNINSTALL
Definition: opregion.c:510
@ OPREGION_ITER_ACTION_INSTALL
Definition: opregion.c:511
static uacpi_iteration_decision do_run_reg(void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:616
uacpi_bool uacpi_address_space_handler_is_default(uacpi_address_space_handler *handler)
Definition: opregion.c:502
struct uacpi_recursive_lock g_opregion_lock
Definition: opregion.c:13
uacpi_bool uacpi_is_buffer_access_address_space(uacpi_address_space space)
Definition: opregion.c:1111
static void run_orphan_ec_regs(uacpi_namespace_node *device_node)
Definition: opregion.c:762
void uacpi_deinitialize_opregion(void)
Definition: opregion.c:20
uacpi_status uacpi_dispatch_opregion_io(uacpi_field_unit *field, uacpi_u32 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
Definition: opregion.c:1162
static uacpi_iteration_decision do_run_orphan_ec_reg(void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:710
static uacpi_bool node_has_handler(uacpi_namespace_node *node, enum uacpi_address_space space)
Definition: opregion.c:697
static uacpi_status run_reg(uacpi_namespace_node *scope, uacpi_u16 space, uacpi_u8 connection_code)
Definition: opregion.c:123
uacpi_status uacpi_initialize_opregion_node(uacpi_namespace_node *node)
Definition: opregion.c:1065
#define rw
Definition: rosglue.h:38
#define args
Definition: format.c:66
static uacpi_u32 uacpi_shareable_ref(uacpi_handle handle)
Definition: shareable.h:40
static void uacpi_shareable_init(uacpi_handle handle)
Definition: shareable.h:14
Definition: match.c:390
Definition: parser.c:44
Definition: tftpd.h:60
enum object_type type
enum opregion_iter_action action
Definition: opregion.c:515
uacpi_address_space_handlers * handlers
Definition: opregion.c:519
uacpi_address_space_handler * handler
Definition: opregion.c:516
uacpi_u8 space
Definition: opregion.c:611
uacpi_size reg_errors
Definition: opregion.c:613
uacpi_size reg_executed
Definition: opregion.c:612
uacpi_region_handler callback
Definition: types.h:67
uacpi_handle user_context
Definition: types.h:68
struct uacpi_address_space_handler * next
Definition: types.h:69
struct uacpi_operation_region * regions
Definition: types.h:70
uacpi_size length
Definition: types.h:105
uacpi_u8 * bytes
Definition: types.h:96
uacpi_u64 num_pins
Definition: types.h:426
uacpi_object_name name
Definition: namespace.h:29
uacpi_object ** objects
Definition: types.h:290
uacpi_size count
Definition: types.h:291
uacpi_address_space_handlers * address_space_handlers
Definition: types.h:276
uacpi_control_method * method
Definition: types.h:267
uacpi_operation_region * op_region
Definition: types.h:272
uacpi_data_view buffer
Definition: types.h:420
uacpi_u8 subspace_id
Definition: types.h:421
void * out_region_context
Definition: types.h:437
uacpi_gpio_region_info gpio_info
Definition: types.h:435
uacpi_pcc_region_info pcc_info
Definition: types.h:434
uacpi_namespace_node * region_node
Definition: types.h:431
uacpi_generic_region_info generic_info
Definition: types.h:433
uacpi_namespace_node * region_node
Definition: types.h:517
uacpi_init_level uacpi_get_current_init_level(void)
Definition: uacpi.c:322
Definition: dlist.c:348
uacpi_char text[4]
Definition: types.h:24
uacpi_bool uacpi_device_matches_pnp_id(uacpi_namespace_node *node, const uacpi_char *const *list)
Definition: utilities.c:905
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383