Skip to content

Commit

Permalink
Introduce support for SMBus and GenericSerialBus opregions
Browse files Browse the repository at this point in the history
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
  • Loading branch information
d-tatianin committed Jan 8, 2025
1 parent 9863968 commit 17e9439
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 22 deletions.
13 changes: 0 additions & 13 deletions include/uacpi/internal/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,19 +187,6 @@ typedef enum uacpi_access_type {
UACPI_ACCESS_TYPE_BUFFER = 5,
} uacpi_access_type;

typedef enum uacpi_access_attributes {
UACPI_ACCESS_ATTRIBUTE_QUICK = 0x02,
UACPI_ACCESS_ATTRIBUTE_SEND_RECEIVE = 0x04,
UACPI_ACCESS_ATTRIBUTE_BYTE = 0x06,
UACPI_ACCESS_ATTRIBUTE_WORD = 0x08,
UACPI_ACCESS_ATTRIBUTE_BLOCK = 0x0A,
UACPI_ACCESS_ATTRIBUTE_BYTES = 0x0B,
UACPI_ACCESS_ATTRIBUTE_PROCESS_CALL = 0x0C,
UACPI_ACCESS_ATTRIBUTE_BLOCK_PROCESS_CALL = 0x0D,
UACPI_ACCESS_ATTRIBUTE_RAW_BYTES = 0x0E,
UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES = 0x0F,
} uacpi_access_attributes;

typedef enum uacpi_lock_rule {
UACPI_LOCK_RULE_NO_LOCK = 0,
UACPI_LOCK_RULE_LOCK = 1,
Expand Down
36 changes: 36 additions & 0 deletions include/uacpi/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ typedef enum uacpi_region_op {

// data => uacpi_region_prm_rw_data
UACPI_REGION_OP_PRM_COMMAND,

// data => uacpi_region_serial_rw_data
UACPI_REGION_OP_SERIAL_READ,
UACPI_REGION_OP_SERIAL_WRITE,
} uacpi_region_op;

typedef struct uacpi_generic_region_info {
Expand Down Expand Up @@ -458,6 +462,38 @@ typedef struct uacpi_region_prm_rw_data
uacpi_data_view in_out_message;
} uacpi_region_prm_rw_data;

typedef enum uacpi_access_attribute
{
UACPI_ACCESS_ATTRIBUTE_QUICK = 0x02,
UACPI_ACCESS_ATTRIBUTE_SEND_RECEIVE = 0x04,
UACPI_ACCESS_ATTRIBUTE_BYTE = 0x06,
UACPI_ACCESS_ATTRIBUTE_WORD = 0x08,
UACPI_ACCESS_ATTRIBUTE_BLOCK = 0x0A,
UACPI_ACCESS_ATTRIBUTE_BYTES = 0x0B,
UACPI_ACCESS_ATTRIBUTE_PROCESS_CALL = 0x0C,
UACPI_ACCESS_ATTRIBUTE_BLOCK_PROCESS_CALL = 0x0D,
UACPI_ACCESS_ATTRIBUTE_RAW_BYTES = 0x0E,
UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES = 0x0F,
} uacpi_access_attribute;

typedef struct uacpi_region_serial_rw_data
{
void *handler_context;
void *region_context;
uacpi_u64 command;
uacpi_data_view connection;
uacpi_data_view in_out_buffer;
uacpi_access_attribute access_attribute;

/*
* Applicable if access_attribute is one of:
* - UACPI_ACCESS_ATTRIBUTE_BYTES
* - UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
* - UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
*/
uacpi_u8 access_length;
} uacpi_region_serial_rw_data;

typedef struct uacpi_region_detach_data {
void *handler_context;
void *region_context;
Expand Down
65 changes: 56 additions & 9 deletions source/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,22 +247,65 @@ static uacpi_status access_field_unit(
#define SERIAL_HEADER_SIZE 2
#define IPMI_DATA_SIZE 64

static uacpi_size wtr_buffer_size(
uacpi_field_unit *field, uacpi_address_space space
static uacpi_status wtr_buffer_size(
uacpi_field_unit *field, uacpi_address_space space,
uacpi_size *out_size
)
{
UACPI_UNUSED(field);

switch (space) {
case UACPI_ADDRESS_SPACE_IPMI:
return SERIAL_HEADER_SIZE + IPMI_DATA_SIZE;
*out_size = SERIAL_HEADER_SIZE + IPMI_DATA_SIZE;
break;
case UACPI_ADDRESS_SPACE_PRM:
return 26;
*out_size = 26;
break;
case UACPI_ADDRESS_SPACE_FFIXEDHW:
return 256;
*out_size = 256;
break;
case UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS:
case UACPI_ADDRESS_SPACE_SMBUS: {
uacpi_size size_for_protocol = SERIAL_HEADER_SIZE;

switch (field->attributes) {
case UACPI_ACCESS_ATTRIBUTE_QUICK:
break; // + 0
case UACPI_ACCESS_ATTRIBUTE_SEND_RECEIVE:
case UACPI_ACCESS_ATTRIBUTE_BYTE:
size_for_protocol += 1;
break;

case UACPI_ACCESS_ATTRIBUTE_WORD:
case UACPI_ACCESS_ATTRIBUTE_PROCESS_CALL:
size_for_protocol += 2;
break;

case UACPI_ACCESS_ATTRIBUTE_BYTES:
size_for_protocol += field->access_length;
break;

case UACPI_ACCESS_ATTRIBUTE_BLOCK:
case UACPI_ACCESS_ATTRIBUTE_BLOCK_PROCESS_CALL:
case UACPI_ACCESS_ATTRIBUTE_RAW_BYTES:
case UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES:
size_for_protocol += 255;
break;

default:
uacpi_error(
"unsupported field@%p access attribute %d\n",
field, field->attributes
);
return UACPI_STATUS_UNIMPLEMENTED;
}

*out_size = size_for_protocol;
break;
}
default:
return 0;
return UACPI_STATUS_INVALID_ARGUMENT;
}

return UACPI_STATUS_OK;
}

static uacpi_status handle_special_field(
Expand Down Expand Up @@ -321,13 +364,17 @@ static uacpi_status handle_special_field(
}
UACPI_FALLTHROUGH;
case UACPI_ADDRESS_SPACE_FFIXEDHW:
case UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS:
case UACPI_ADDRESS_SPACE_SMBUS:
goto do_wtr;
default:
return ret;
}

do_wtr:
wtr_buffer.length = wtr_buffer_size(field, region->space);
ret = wtr_buffer_size(field, region->space, &wtr_buffer.length);
if (uacpi_unlikely_error(ret))
goto out_handled;

wtr_buffer.data = uacpi_kernel_alloc(wtr_buffer.length);
if (uacpi_unlikely(wtr_buffer.data == UACPI_NULL)) {
Expand Down
26 changes: 26 additions & 0 deletions source/opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,7 @@ uacpi_status uacpi_dispatch_opregion_io(
uacpi_region_ipmi_rw_data ipmi;
uacpi_region_ffixedhw_rw_data ffixedhw;
uacpi_region_prm_rw_data prm;
uacpi_region_serial_rw_data serial;
} handler_data;

ret = upgrade_to_opregion_lock();
Expand Down Expand Up @@ -968,6 +969,31 @@ uacpi_status uacpi_dispatch_opregion_io(
handler_data.prm.in_out_message = data.buffer;
op = UACPI_REGION_OP_PRM_COMMAND;
break;
case UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS:
case UACPI_ADDRESS_SPACE_SMBUS:
ret = uacpi_object_get_string_or_buffer(
field->connection, &handler_data.serial.connection
);
if (uacpi_unlikely_error(ret))
goto io_done;

handler_data.serial.command = abs_offset;
handler_data.serial.in_out_buffer = data.buffer;
handler_data.serial.access_attribute = field->attributes;

switch (field->attributes) {
case UACPI_ACCESS_ATTRIBUTE_BYTES:
case UACPI_ACCESS_ATTRIBUTE_RAW_BYTES:
case UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES:
handler_data.serial.access_length = field->access_length;
break;
default:
handler_data.serial.access_length = 0;
}

op = op == UACPI_REGION_OP_READ ?
UACPI_REGION_OP_SERIAL_READ : UACPI_REGION_OP_SERIAL_WRITE;
break;
default:
handler_data.rw.byte_width = field->access_width_bytes;
handler_data.rw.offset = abs_offset;
Expand Down

0 comments on commit 17e9439

Please sign in to comment.