ReactOS 0.4.17-dev-683-g0dafdc5
opregion.c File Reference
Include dependency graph for opregion.c:

Go to the source code of this file.

Classes

struct  opregion_iter_ctx
 
struct  reg_run_ctx
 

Enumerations

enum  unreg { UNREG_NO = 0 , UNREG_YES }
 
enum  opregion_iter_action { OPREGION_ITER_ACTION_UNINSTALL , OPREGION_ITER_ACTION_INSTALL }
 

Functions

uacpi_status uacpi_initialize_opregion (void)
 
void uacpi_deinitialize_opregion (void)
 
void uacpi_trace_region_error (uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret)
 
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)
 
static uacpi_bool space_needs_reg (enum uacpi_address_space space)
 
static uacpi_status region_run_reg (uacpi_namespace_node *node, uacpi_u8 connection_code)
 
uacpi_address_space_handlersuacpi_node_get_address_space_handlers (uacpi_namespace_node *node)
 
static uacpi_address_space_handlerfind_handler (uacpi_address_space_handlers *handlers, enum uacpi_address_space space)
 
static uacpi_operation_regionfind_previous_region_link (uacpi_operation_region *region)
 
uacpi_status uacpi_opregion_attach (uacpi_namespace_node *node)
 
static void region_install_handler (uacpi_namespace_node *node, uacpi_address_space_handler *handler)
 
static void region_uninstall_handler (uacpi_namespace_node *node, enum unreg unreg)
 
uacpi_status uacpi_upgrade_to_opregion_lock (void)
 
void uacpi_release_opregion_lock (void)
 
void uacpi_opregion_uninstall_handler (uacpi_namespace_node *node)
 
uacpi_bool uacpi_address_space_handler_is_default (uacpi_address_space_handler *handler)
 
static uacpi_iteration_decision do_install_or_uninstall_handler (uacpi_handle opaque, uacpi_namespace_node *node, uacpi_u32 depth)
 
static uacpi_iteration_decision do_run_reg (void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
 
static uacpi_status reg_or_unreg_all_opregions (uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_u8 connection_code)
 
static uacpi_address_space_handlersextract_handlers (uacpi_namespace_node *node)
 
uacpi_status uacpi_reg_all_opregions (uacpi_namespace_node *device_node, enum uacpi_address_space space)
 
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)
 
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)
 
uacpi_status uacpi_uninstall_address_space_handler (uacpi_namespace_node *device_node, enum uacpi_address_space space)
 
uacpi_status uacpi_initialize_opregion_node (uacpi_namespace_node *node)
 
uacpi_bool uacpi_is_buffer_access_address_space (uacpi_address_space space)
 
static uacpi_bool space_needs_bounds_checking (uacpi_address_space space)
 
uacpi_status uacpi_dispatch_opregion_io (uacpi_field_unit *field, uacpi_u32 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
 

Variables

struct uacpi_recursive_lock g_opregion_lock
 

Enumeration Type Documentation

◆ opregion_iter_action

Enumerator
OPREGION_ITER_ACTION_UNINSTALL 
OPREGION_ITER_ACTION_INSTALL 

Definition at line 420 of file opregion.c.

420 {
423};
@ OPREGION_ITER_ACTION_UNINSTALL
Definition: opregion.c:421
@ OPREGION_ITER_ACTION_INSTALL
Definition: opregion.c:422

◆ unreg

Enumerator
UNREG_NO 
UNREG_YES 

Definition at line 311 of file opregion.c.

311 {
312 UNREG_NO = 0,
313 UNREG_YES,
314};
@ UNREG_YES
Definition: opregion.c:313
@ UNREG_NO
Definition: opregion.c:312

Function Documentation

◆ do_install_or_uninstall_handler()

static uacpi_iteration_decision do_install_or_uninstall_handler ( uacpi_handle  opaque,
uacpi_namespace_node node,
uacpi_u32  depth 
)
static

Definition at line 430 of file opregion.c.

433{
434 struct opregion_iter_ctx *ctx = opaque;
437
439
442 uacpi_operation_region *region = object->op_region;
443
444 if (region->space != ctx->handler->space)
446
447 if (ctx->action == OPREGION_ITER_ACTION_INSTALL) {
448 if (region->handler)
450
452 } else {
453 if (uacpi_unlikely(region->handler != ctx->handler)) {
455 node, "handler mismatch for",
457 );
459 }
460
462 }
463
465 }
466
468 if (handlers == UACPI_NULL)
470
471 // Device already has a handler for this space installed
472 if (find_handler(handlers, ctx->handler->space) != UACPI_NULL)
474
476}
#define UACPI_UNUSED(x)
Definition: helpers.h:7
uacpi_object * uacpi_namespace_node_get_object(const uacpi_namespace_node *node)
Definition: namespace.c:646
#define uacpi_unlikely(expr)
Definition: compiler.h:88
#define UACPI_NULL
Definition: types.h:33
@ UACPI_STATUS_INTERNAL_ERROR
Definition: status.h:21
@ UACPI_ITERATION_DECISION_NEXT_PEER
Definition: types.h:39
@ UACPI_ITERATION_DECISION_CONTINUE
Definition: types.h:29
@ UACPI_OBJECT_OPERATION_REGION
Definition: types.h:121
static xmlCharEncodingHandlerPtr * handlers
Definition: encoding.c:1380
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
static uacpi_address_space_handler * find_handler(uacpi_address_space_handlers *handlers, enum uacpi_address_space space)
Definition: opregion.c:193
void uacpi_trace_region_error(uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret)
Definition: opregion.c:25
static void region_uninstall_handler(uacpi_namespace_node *node, enum unreg unreg)
Definition: opregion.c:316
static void region_install_handler(uacpi_namespace_node *node, uacpi_address_space_handler *handler)
Definition: opregion.c:297
uacpi_address_space_handlers * uacpi_node_get_address_space_handlers(uacpi_namespace_node *node)
Definition: opregion.c:170
uacpi_u16 space
Definition: types.h:120
uacpi_address_space_handler * handler
Definition: types.h:118
Definition: dlist.c:348

Referenced by uacpi_install_address_space_handler_with_flags(), and uacpi_uninstall_address_space_handler().

◆ do_run_reg()

static uacpi_iteration_decision do_run_reg ( void opaque,
uacpi_namespace_node node,
uacpi_u32  depth 
)
static

Definition at line 485 of file opregion.c.

488{
489 struct reg_run_ctx *ctx = opaque;
492 uacpi_bool was_regged;
493
495
497
498 if (region->space != ctx->space)
500
501 was_regged = region->state_flags & UACPI_OP_REGION_STATE_REG_EXECUTED;
502 if (was_regged == (ctx->connection_code == ACPI_REG_CONNECT))
504
505 ret = region_run_reg(node, ctx->connection_code);
506 if (ctx->connection_code == ACPI_REG_DISCONNECT)
507 region->state_flags &= ~UACPI_OP_REGION_STATE_REG_EXECUTED;
508
511
512 if (ctx->connection_code == ACPI_REG_CONNECT)
514
515 ctx->reg_executed++;
516
518 ctx->reg_errors++;
520 }
521
523}
#define ACPI_REG_CONNECT
Definition: actypes.h:890
#define ACPI_REG_DISCONNECT
Definition: actypes.h:889
#define UACPI_OP_REGION_STATE_REG_EXECUTED
Definition: types.h:111
bool uacpi_bool
Definition: types.h:31
#define uacpi_unlikely_error(expr)
Definition: status.h:49
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
return ret
Definition: mutex.c:147
static uacpi_status region_run_reg(uacpi_namespace_node *node, uacpi_u8 connection_code)
Definition: opregion.c:122
uacpi_operation_region * op_region
Definition: types.h:262
uacpi_u8 state_flags
Definition: types.h:121

Referenced by reg_or_unreg_all_opregions().

◆ extract_handlers()

static uacpi_address_space_handlers * extract_handlers ( uacpi_namespace_node node)
static

Definition at line 570 of file opregion.c.

573{
574 uacpi_object *handlers_obj;
575
576 if (node == uacpi_namespace_root())
577 return g_uacpi_rt_ctx.root_object->address_space_handlers;
578
580 node,
583 );
584 if (uacpi_unlikely(handlers_obj == UACPI_NULL))
585 return UACPI_NULL;
586
587 return handlers_obj->address_space_handlers;
588}
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:17
uacpi_object * uacpi_namespace_node_get_object_typed(const uacpi_namespace_node *node, uacpi_object_type_bits type_mask)
Definition: namespace.c:654
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
@ UACPI_OBJECT_PROCESSOR_BIT
Definition: types.h:146
@ UACPI_OBJECT_THERMAL_ZONE_BIT
Definition: types.h:147
@ UACPI_OBJECT_DEVICE_BIT
Definition: types.h:140
uacpi_address_space_handlers * address_space_handlers
Definition: types.h:266

Referenced by uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ find_handler()

static uacpi_address_space_handler * find_handler ( uacpi_address_space_handlers handlers,
enum uacpi_address_space  space 
)
static

Definition at line 193 of file opregion.c.

197{
199
200 while (handler) {
201 if (handler->space == space)
202 return handler;
203
204 handler = handler->next;
205 }
206
207 return UACPI_NULL;
208}
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512

Referenced by do_install_or_uninstall_handler(), reg_or_unreg_all_opregions(), uacpi_initialize_opregion_node(), uacpi_install_address_space_handler_with_flags(), and uacpi_uninstall_address_space_handler().

◆ find_previous_region_link()

static uacpi_operation_region * find_previous_region_link ( uacpi_operation_region region)
static

Definition at line 210 of file opregion.c.

213{
216
217 if (parent == region)
218 // This is the last attached region, it has no previous link
219 return region;
220
221 while (parent->next != region) {
222 parent = parent->next;
223
225 return UACPI_NULL;
226 }
227
228 return parent;
229}
r parent
Definition: btrfs.c:3010

Referenced by region_uninstall_handler().

◆ reg_or_unreg_all_opregions()

static uacpi_status reg_or_unreg_all_opregions ( uacpi_namespace_node device_node,
enum uacpi_address_space  space,
uacpi_u8  connection_code 
)
static

Definition at line 525 of file opregion.c.

529{
531 uacpi_bool is_connect;
532 enum uacpi_permanent_only perm_only;
533 struct reg_run_ctx ctx = { 0 };
534
535 ctx.space = space;
536 ctx.connection_code = connection_code;
537
541
542 is_connect = connection_code == ACPI_REG_CONNECT;
543 if (uacpi_unlikely(is_connect &&
546
547 /*
548 * We want to unreg non-permanent opregions as well, however,
549 * registering them is handled separately and should not be
550 * done by us.
551 */
552 perm_only = is_connect ? UACPI_PERMANENT_ONLY_YES : UACPI_PERMANENT_ONLY_NO;
553
555 device_node, do_run_reg, UACPI_NULL,
557 UACPI_SHOULD_LOCK_NO, perm_only, &ctx
558 );
559
561 "%sactivated all '%s' opregions controlled by '%.4s', "
562 "%zu _REG() calls (%zu errors)",
563 connection_code == ACPI_REG_CONNECT ? "" : "de",
565 device_node->name.text, ctx.reg_executed, ctx.reg_errors
566 );
567 return UACPI_STATUS_OK;
568}
#define uacpi_trace(...)
Definition: log.h:33
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:834
uacpi_permanent_only
Definition: namespace.h:88
@ UACPI_PERMANENT_ONLY_YES
Definition: namespace.h:90
@ UACPI_PERMANENT_ONLY_NO
Definition: namespace.h:89
@ UACPI_SHOULD_LOCK_NO
Definition: namespace.h:94
#define UACPI_MAX_DEPTH_ANY
Definition: namespace.h:102
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
const uacpi_char * uacpi_address_space_to_string(uacpi_address_space space)
Definition: types.c:11
@ UACPI_OBJECT_OPERATION_REGION_BIT
Definition: types.h:144
static uacpi_iteration_decision do_run_reg(void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:485
uacpi_u8 space
Definition: opregion.c:479
uacpi_u8 connection_code
Definition: opregion.c:480
uacpi_object_name name
Definition: namespace.h:29
uacpi_char text[4]
Definition: types.h:24

Referenced by uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ region_install_handler()

static void region_install_handler ( uacpi_namespace_node node,
uacpi_address_space_handler handler 
)
static

Definition at line 297 of file opregion.c.

300{
302
304 region->handler = handler;
306
307 region->next = handler->regions;
308 handler->regions = region;
309}
uacpi_u32 uacpi_shareable_ref(uacpi_handle)
Definition: shareable.c:31
struct uacpi_operation_region * next
Definition: types.h:134

Referenced by do_install_or_uninstall_handler(), and uacpi_initialize_opregion_node().

◆ region_run_reg()

static uacpi_status region_run_reg ( uacpi_namespace_node node,
uacpi_u8  connection_code 
)
static

Definition at line 122 of file opregion.c.

125{
127 uacpi_namespace_node *reg_node;
128 uacpi_object_array method_args;
129 uacpi_object *reg_obj, *args[2];
130
132 node->parent, "_REG", UACPI_SHOULD_LOCK_NO,
134 );
136 return ret;
137
140 );
141 if (uacpi_unlikely(reg_obj == UACPI_NULL))
142 return UACPI_STATUS_OK;
143
145 if (uacpi_unlikely(args[0] == UACPI_NULL))
147
149 if (uacpi_unlikely(args[1] == UACPI_NULL)) {
152 }
153
155 args[1]->integer = connection_code;
156 method_args.objects = args;
157 method_args.count = 2;
158
160 reg_node, reg_obj->method, &method_args, UACPI_NULL
161 );
163 uacpi_trace_region_error(node, "error during _REG execution for", ret);
164
167 return ret;
168}
@ UACPI_MAY_SEARCH_ABOVE_PARENT_NO
Definition: namespace.h:84
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:491
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:327
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_OBJECT_METHOD_BIT
Definition: types.h:142
@ UACPI_OBJECT_INTEGER
Definition: types.h:112
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:762
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:6150
#define args
Definition: format.c:66
Definition: match.c:390
uacpi_object ** objects
Definition: types.h:290
uacpi_size count
Definition: types.h:291
uacpi_control_method * method
Definition: types.h:257

Referenced by do_run_reg(), region_uninstall_handler(), and uacpi_initialize_opregion_node().

◆ region_uninstall_handler()

static void region_uninstall_handler ( uacpi_namespace_node node,
enum unreg  unreg 
)
static

Definition at line 316 of file opregion.c.

319{
324
327 );
329 return;
330
331 region = obj->op_region;
332
333 handler = region->handler;
334 if (handler == UACPI_NULL)
335 return;
336
339 uacpi_error("operation region @%p not in the handler@%p list(?)",
340 region, handler);
341 goto out;
342 } else if (link == region) {
343 link = link->next;
344 handler->regions = link;
345 } else {
346 link->next = region->next;
347 }
348
349out:
351 uacpi_region_detach_data detach_data = { 0 };
352
353 detach_data.region_node = node;
354 detach_data.region_context = region->user_context;
355 detach_data.handler_context = handler->user_context;
356
359
360 ret = handler->callback(UACPI_REGION_OP_DETACH, &detach_data);
361
364
367 node, "error during handler detach for", ret
368 );
369 }
370 }
371
373 unreg == UNREG_YES) {
375 region->state_flags &= ~UACPI_OP_REGION_STATE_REG_EXECUTED;
376 }
377
379 region->handler = UACPI_NULL;
380 region->state_flags &= ~UACPI_OP_REGION_STATE_ATTACHED;
381}
const WCHAR * link
Definition: db.cpp:998
#define uacpi_error(...)
Definition: log.h:36
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:294
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:51
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
void uacpi_address_space_handler_unref(uacpi_address_space_handler *handler)
Definition: types.c:551
#define UACPI_OP_REGION_STATE_ATTACHED
Definition: types.h:114
@ UACPI_REGION_OP_DETACH
Definition: types.h:377
static uacpi_operation_region * find_previous_region_link(uacpi_operation_region *region)
Definition: opregion.c:210
unreg
Definition: opregion.c:311
uacpi_handle user_context
Definition: types.h:119
uacpi_namespace_node * region_node
Definition: types.h:507
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383

Referenced by do_install_or_uninstall_handler(), and uacpi_opregion_uninstall_handler().

◆ space_needs_bounds_checking()

static uacpi_bool space_needs_bounds_checking ( uacpi_address_space  space)
static

Definition at line 847 of file opregion.c.

848{
851}
@ UACPI_ADDRESS_SPACE_GENERAL_PURPOSE_IO
Definition: types.h:51
uacpi_bool uacpi_is_buffer_access_address_space(uacpi_address_space space)
Definition: opregion.c:833

Referenced by uacpi_dispatch_opregion_io().

◆ space_needs_reg()

static uacpi_bool space_needs_reg ( enum uacpi_address_space  space)
static

Definition at line 112 of file opregion.c.

113{
117 return UACPI_FALSE;
118
119 return UACPI_TRUE;
120}
#define UACPI_FALSE
Definition: types.h:30
#define UACPI_TRUE
Definition: types.h:29
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:43
@ UACPI_ADDRESS_SPACE_TABLE_DATA
Definition: types.h:58
@ UACPI_ADDRESS_SPACE_SYSTEM_IO
Definition: types.h:44

Referenced by uacpi_initialize_opregion_node(), uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ trace_region_io()

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 
)
static

Definition at line 47 of file opregion.c.

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}
UINT op
Definition: effect.c:236
static uacpi_bool uacpi_should_log(enum uacpi_log_level lvl)
Definition: context.h:95
@ UACPI_LOG_TRACE
Definition: log.h:18
const uacpi_char * uacpi_namespace_node_generate_absolute_path(const uacpi_namespace_node *node)
Definition: namespace.c:1034
#define UACPI_PRIX64
Definition: types.h:61
char uacpi_char
Definition: types.h:44
#define UACPI_FMT64(val)
Definition: types.h:62
@ UACPI_REGION_OP_WRITE
Definition: types.h:381
@ UACPI_REGION_OP_READ
Definition: types.h:380
@ UACPI_ADDRESS_SPACE_IPMI
Definition: types.h:50
@ UACPI_ADDRESS_SPACE_PRM
Definition: types.h:54
@ UACPI_ADDRESS_SPACE_FFIXEDHW
Definition: types.h:55
@ UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS
Definition: types.h:52
@ UACPI_ADDRESS_SPACE_SMBUS
Definition: types.h:47
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
void uacpi_free_dynamic_string(const uacpi_char *str)
Definition: utilities.c:1148
Definition: parser.c:44

Referenced by uacpi_dispatch_opregion_io().

◆ uacpi_address_space_handler_is_default()

uacpi_bool uacpi_address_space_handler_is_default ( uacpi_address_space_handler handler)

Definition at line 413 of file opregion.c.

416{
418}
#define UACPI_ADDRESS_SPACE_HANDLER_DEFAULT
Definition: types.h:73

Referenced by uacpi_namespace_initialize().

◆ uacpi_deinitialize_opregion()

void uacpi_deinitialize_opregion ( void  )

Definition at line 20 of file opregion.c.

21{
23}
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:268
struct uacpi_recursive_lock g_opregion_lock
Definition: opregion.c:13

Referenced by uacpi_state_reset().

◆ uacpi_dispatch_opregion_io()

uacpi_status uacpi_dispatch_opregion_io ( uacpi_field_unit field,
uacpi_u32  offset,
uacpi_region_op  op,
union uacpi_opregion_io_data  data 
)

Definition at line 853 of file opregion.c.

857{
863 uacpi_u64 abs_offset, offset_end = offset;
864 uacpi_bool is_oob = UACPI_FALSE;
865 uacpi_region_op orig_op = op;
866
867 union {
875 } handler_data;
876
880 field->region, "unable to attach", ret
881 );
882 return ret;
883 }
884
887 );
890
891 region = obj->op_region;
892 space = region->space;
893 handler = region->handler;
894
895 abs_offset = region->offset + offset;
896 offset_end += field->access_width_bytes;
897
899 is_oob = region->length < offset_end || abs_offset < offset;
900 if (uacpi_unlikely(is_oob)) {
901 const uacpi_char *path;
902
905 "out-of-bounds access to opregion %s[0x%"UACPI_PRIX64"->"
906 "0x%"UACPI_PRIX64"] at 0x%"UACPI_PRIX64" (idx=%u, width=%d)",
907 path, UACPI_FMT64(region->offset),
908 UACPI_FMT64(region->offset + region->length),
909 UACPI_FMT64(abs_offset), offset, field->access_width_bytes
910 );
913 }
914
915 handler_data.rw.region_context = region->user_context;
916 handler_data.rw.handler_context = handler->user_context;
917
918 switch (region->space) {
921
922 cursor = region->internal_buffer + offset;
923
924 /*
925 * Reads from PCC just return the current contents of the internal
926 * buffer.
927 */
928 if (op == UACPI_REGION_OP_READ) {
930 data.integer, cursor, sizeof(*data.integer),
931 field->access_width_bytes
932 );
933 goto io_done;
934 }
935
936 uacpi_memcpy(cursor, data.integer, field->access_width_bytes);
937
938 /*
939 * Dispatch a PCC send command if this was a write to the command field
940 *
941 * ACPI 6.5: 14.3. Extended PCC Subspace Shared Memory Region
942 */
943 if (offset >= 12 && offset < 16) {
944 uacpi_memzero(&handler_data.pcc.buffer, sizeof(handler_data.pcc.buffer));
945 handler_data.pcc.buffer.bytes = region->internal_buffer;
946 handler_data.pcc.buffer.length = region->length;
947
949 break;
950 }
951
952 // No dispatch needed, IO is done
953 goto io_done;
954 }
956 handler_data.gpio.pin_offset = field->pin_offset;
957 handler_data.gpio.num_pins = field->bit_length;
958 handler_data.gpio.value = *data.integer;
959
961 field->connection, &handler_data.gpio.connection
962 );
964 goto io_done;
965
968 break;
970 handler_data.ipmi.in_out_message = data.buffer;
971 handler_data.ipmi.command = abs_offset;
973 break;
975 handler_data.ffixedhw.in_out_message = data.buffer;
976 handler_data.ffixedhw.command = abs_offset;
978 break;
980 handler_data.prm.in_out_message = data.buffer;
982 break;
986 field->connection, &handler_data.serial.connection
987 );
989 goto io_done;
990
991 handler_data.serial.command = abs_offset;
992 handler_data.serial.in_out_buffer = data.buffer;
993 handler_data.serial.access_attribute = field->attributes;
994
995 switch (field->attributes) {
999 handler_data.serial.access_length = field->access_length;
1000 break;
1001 default:
1002 handler_data.serial.access_length = 0;
1003 }
1004
1007 break;
1008 default:
1009 handler_data.rw.byte_width = field->access_width_bytes;
1010 handler_data.rw.offset = abs_offset;
1011 handler_data.rw.value = *data.integer;
1012 break;
1013 }
1014
1017
1018 ret = handler->callback(op, &handler_data);
1019
1022
1023io_done:
1025 uacpi_trace_region_error(field->region, "unable to perform IO", ret);
1026 return ret;
1027 }
1028
1029 if (orig_op == UACPI_REGION_OP_READ) {
1030 switch (region->space) {
1037 break;
1039 *data.integer = handler_data.gpio.value;
1040 break;
1041 default:
1042 *data.integer = handler_data.rw.value;
1043 break;
1044 }
1045 }
1046
1047 trace_region_io(field, space, abs_offset, orig_op, data);
1048 return ret;
1049}
#define uacpi_memzero(ptr, size)
Definition: stdlib.h:99
#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
#define uacpi_likely(expr)
Definition: compiler.h:89
uint64_t uacpi_u64
Definition: types.h:22
uint8_t uacpi_u8
Definition: types.h:19
@ UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX
Definition: status.h:40
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:734
@ UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
Definition: types.h:483
@ UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
Definition: types.h:484
@ UACPI_ACCESS_ATTRIBUTE_BYTES
Definition: types.h:480
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_GPIO_WRITE
Definition: types.h:388
@ UACPI_REGION_OP_SERIAL_READ
Definition: types.h:400
@ UACPI_REGION_OP_IPMI_COMMAND
Definition: types.h:391
uacpi_address_space
Definition: types.h:42
@ 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:1059
uint32_t serial
Definition: fsck.fat.h:29
const char cursor[]
Definition: icontest.c:13
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_bool space_needs_bounds_checking(uacpi_address_space space)
Definition: opregion.c:847
uacpi_status uacpi_opregion_attach(uacpi_namespace_node *node)
Definition: opregion.c:231
#define rw
Definition: rosglue.h:38
uacpi_u64 offset
Definition: types.h:122
uacpi_u8 * internal_buffer
Definition: types.h:130
uacpi_u64 length
Definition: types.h:123

Referenced by access_field_unit().

◆ uacpi_initialize_opregion()

uacpi_status uacpi_initialize_opregion ( void  )

Definition at line 15 of file opregion.c.

16{
18}
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:256

Referenced by uacpi_initialize().

◆ uacpi_initialize_opregion_node()

uacpi_status uacpi_initialize_opregion_node ( uacpi_namespace_node node)

Definition at line 788 of file opregion.c.

789{
795
798 return ret;
799
802
803 while (parent) {
805 if (handlers != UACPI_NULL) {
807
808 if (handler != UACPI_NULL) {
811 break;
812 }
813 }
814
815 parent = parent->parent;
816 }
817
818 if (ret != UACPI_STATUS_OK)
819 goto out;
820 if (!space_needs_reg(region->space))
821 goto out;
823 goto out;
824
827
828out:
830 return ret;
831}
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:308
@ UACPI_INIT_LEVEL_NAMESPACE_LOADED
Definition: types.h:78
uacpi_status uacpi_upgrade_to_opregion_lock(void)
Definition: opregion.c:383
static uacpi_bool space_needs_reg(enum uacpi_address_space space)
Definition: opregion.c:112
uacpi_init_level uacpi_get_current_init_level(void)
Definition: uacpi.c:310

Referenced by handle_create_data_region(), and handle_create_op_region().

◆ uacpi_install_address_space_handler()

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 
)

Install an address space handler to a device node. The handler is recursively connected to all of the operation regions of type 'space' underneath 'device_node'. Note that this recursion stops as soon as another device node that already has an address space handler of this type installed is encountered.

Definition at line 706 of file opregion.c.

710{
712 device_node, space, handler, handler_context, 0
713 );
714}
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:625

◆ uacpi_install_address_space_handler_with_flags()

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 at line 625 of file opregion.c.

630{
633 uacpi_address_space_handler *this_handler, *new_handler;
634 struct opregion_iter_ctx iter_ctx;
635
638 return ret;
639
643 return ret;
644 }
645
646 handlers = extract_handlers(device_node);
649 goto out;
650 }
651
652 this_handler = find_handler(handlers, space);
653 if (this_handler != UACPI_NULL) {
655 goto out;
656 }
657
658 new_handler = uacpi_kernel_alloc(sizeof(*new_handler));
659 if (new_handler == UACPI_NULL) {
661 goto out;
662 }
663 uacpi_shareable_init(new_handler);
664
665 new_handler->next = handlers->head;
666 new_handler->space = space;
667 new_handler->user_context = handler_context;
668 new_handler->callback = handler;
669 new_handler->regions = UACPI_NULL;
670 new_handler->flags = flags;
671 handlers->head = new_handler;
672
673 iter_ctx.handler = new_handler;
674 iter_ctx.action = OPREGION_ITER_ACTION_INSTALL;
675
679 UACPI_PERMANENT_ONLY_YES, &iter_ctx
680 );
681
683 goto out;
684
685 /*
686 * Installing an early address space handler, obviously not possible to
687 * execute any _REG methods here. Just return and hope that it is either
688 * a global address space handler, or a handler installed by a user who
689 * will run uacpi_reg_all_opregions manually after loading/initializing
690 * the namespace.
691 */
693 goto out;
694
695 // Init level is NAMESPACE_INITIALIZED, so we can safely run _REG now
697 device_node, space, ACPI_REG_CONNECT
698 );
699
700out:
703 return ret;
704}
uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
Definition: mutex.c:288
@ UACPI_STATUS_ALREADY_EXISTS
Definition: status.h:20
@ UACPI_OBJECT_ANY_BIT
Definition: types.h:152
GLbitfield flags
Definition: glext.h:7161
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
static uacpi_status reg_or_unreg_all_opregions(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_u8 connection_code)
Definition: opregion.c:525
static uacpi_iteration_decision do_install_or_uninstall_handler(uacpi_handle opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:430
static uacpi_address_space_handlers * extract_handlers(uacpi_namespace_node *node)
Definition: opregion.c:570
void uacpi_shareable_init(uacpi_handle)
Definition: shareable.c:9
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

Referenced by uacpi_install_address_space_handler(), and uacpi_install_default_address_space_handlers().

◆ uacpi_is_buffer_access_address_space()

uacpi_bool uacpi_is_buffer_access_address_space ( uacpi_address_space  space)

Definition at line 833 of file opregion.c.

834{
835 switch (space) {
841 return UACPI_TRUE;
842 default:
843 return UACPI_FALSE;
844 }
845}

Referenced by space_needs_bounds_checking(), uacpi_field_unit_get_bit_length(), and uacpi_field_unit_get_read_type().

◆ uacpi_node_get_address_space_handlers()

uacpi_address_space_handlers * uacpi_node_get_address_space_handlers ( uacpi_namespace_node node)

Definition at line 170 of file opregion.c.

173{
175
176 if (node == uacpi_namespace_root())
177 return g_uacpi_rt_ctx.root_object->address_space_handlers;
178
180 if (uacpi_unlikely(object == UACPI_NULL))
181 return UACPI_NULL;
182
183 switch (object->type) {
187 return object->address_space_handlers;
188 default:
189 return UACPI_NULL;
190 }
191}
@ UACPI_OBJECT_PROCESSOR
Definition: types.h:123
@ UACPI_OBJECT_DEVICE
Definition: types.h:117
@ UACPI_OBJECT_THERMAL_ZONE
Definition: types.h:124

Referenced by do_install_or_uninstall_handler(), reg_or_unreg_all_opregions(), uacpi_initialize_opregion_node(), and uacpi_namespace_initialize().

◆ uacpi_opregion_attach()

uacpi_status uacpi_opregion_attach ( uacpi_namespace_node node)

Definition at line 231 of file opregion.c.

232{
237 uacpi_region_attach_data attach_data = { 0 };
238
241
244 );
247
248 region = obj->op_region;
249
250 if (region->handler == UACPI_NULL)
253 return UACPI_STATUS_OK;
254
255 handler = region->handler;
256 attach_data.region_node = node;
257
258 switch (region->space) {
260 if (region->length) {
264 }
265
266 attach_data.pcc_info.buffer.bytes = region->internal_buffer;
267 attach_data.pcc_info.buffer.length = region->length;
268 attach_data.pcc_info.subspace_id = region->offset;
269 break;
271 attach_data.gpio_info.num_pins = region->length;
272 break;
273 default:
274 attach_data.generic_info.base = region->offset;
275 attach_data.generic_info.length = region->length;
276 break;
277 }
278
279 attach_data.handler_context = handler->user_context;
280
283 ret = handler->callback(UACPI_REGION_OP_ATTACH, &attach_data);
285
288 return ret;
289 }
290
292 region->user_context = attach_data.out_region_context;
294 return ret;
295}
uacpi_bool uacpi_namespace_node_is_dangling(uacpi_namespace_node *node)
Definition: namespace.c:333
#define uacpi_kernel_alloc_zeroed
Definition: stdlib.h:127
@ UACPI_STATUS_NAMESPACE_NODE_DANGLING
Definition: status.h:24
@ UACPI_REGION_OP_ATTACH
Definition: types.h:375
uacpi_size length
Definition: types.h:105
uacpi_u8 * bytes
Definition: types.h:96
uacpi_u64 num_pins
Definition: types.h:416
uacpi_data_view buffer
Definition: types.h:410
uacpi_u8 subspace_id
Definition: types.h:411
void * out_region_context
Definition: types.h:427
uacpi_gpio_region_info gpio_info
Definition: types.h:425
uacpi_pcc_region_info pcc_info
Definition: types.h:424
uacpi_namespace_node * region_node
Definition: types.h:421
uacpi_generic_region_info generic_info
Definition: types.h:423

Referenced by uacpi_dispatch_opregion_io().

◆ uacpi_opregion_uninstall_handler()

void uacpi_opregion_uninstall_handler ( uacpi_namespace_node node)

◆ uacpi_reg_all_opregions()

uacpi_status uacpi_reg_all_opregions ( uacpi_namespace_node device_node,
enum uacpi_address_space  space 
)

Execute _REG(space, ACPI_REG_CONNECT) for all of the opregions with this address space underneath this device. This should only be called manually if you want to register an early handler that must be available before the call to uacpi_namespace_initialize().

Definition at line 590 of file opregion.c.

Referenced by uacpi_namespace_initialize().

◆ uacpi_release_opregion_lock()

void uacpi_release_opregion_lock ( void  )

Definition at line 398 of file opregion.c.

Referenced by unlock_field_unit_transaction().

◆ uacpi_trace_region_error()

void uacpi_trace_region_error ( uacpi_namespace_node node,
uacpi_char message,
uacpi_status  ret 
)

Definition at line 25 of file opregion.c.

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}
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:60
Definition: tftpd.h:60

Referenced by do_install_or_uninstall_handler(), find_pci_root(), handle_special_field(), io_region_attach(), memory_region_attach(), pci_region_attach(), region_run_reg(), region_uninstall_handler(), and uacpi_dispatch_opregion_io().

◆ uacpi_uninstall_address_space_handler()

uacpi_status uacpi_uninstall_address_space_handler ( uacpi_namespace_node device_node,
enum uacpi_address_space  space 
)

Uninstall the handler of type 'space' from a given device node.

Definition at line 716 of file opregion.c.

720{
724 struct opregion_iter_ctx iter_ctx;
725
728 return ret;
729
733 return ret;
734 }
735
736 handlers = extract_handlers(device_node);
739 goto out;
740 }
741
745 goto out;
746 }
747
748 iter_ctx.handler = handler;
749 iter_ctx.action = OPREGION_ITER_ACTION_UNINSTALL;
750
754 UACPI_PERMANENT_ONLY_NO, &iter_ctx
755 );
756
757 prev_handler = handlers->head;
758
759 // Are we the last linked handler?
760 if (prev_handler == handler) {
761 handlers->head = handler->next;
762 goto out_unreg;
763 }
764
765 // Nope, we're somewhere in the middle. Do a search.
766 while (prev_handler) {
767 if (prev_handler->next == handler) {
768 prev_handler->next = handler->next;
769 goto out;
770 }
771
772 prev_handler = prev_handler->next;
773 }
774
775out_unreg:
778
779out:
780 if (handler != UACPI_NULL)
782
785 return ret;
786}

◆ uacpi_upgrade_to_opregion_lock()

uacpi_status uacpi_upgrade_to_opregion_lock ( void  )

Definition at line 383 of file opregion.c.

384{
386
387 /*
388 * Drop the namespace lock, and reacquire it after the opregion lock
389 * so we keep the ordering with user API.
390 */
392
395 return ret;
396}

Referenced by lock_field_unit_transaction(), uacpi_initialize_opregion_node(), and uacpi_opregion_uninstall_handler().

Variable Documentation

◆ g_opregion_lock