acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) { u64 address; acpi_status status; ACPI_FUNCTION_NAME(hw_read); status = acpi_hw_validate_register(reg, 32, &address); if (ACPI_FAILURE(status)) { return (status); } *value = 0; if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_read_memory((acpi_physical_address) address, value, reg->bit_width); } else { status = acpi_hw_read_port((acpi_io_address) address, value, reg->bit_width); } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", *value, reg->bit_width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); }
acpi_status acpi_ex_system_io_space_handler(u32 function, acpi_physical_address address, u32 bit_width, u64 *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; u32 value32; ACPI_FUNCTION_TRACE(ex_system_io_space_handler); ACPI_DEBUG_PRINT((ACPI_DB_INFO, <<<<<<< HEAD "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", ======= "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a bit_width, function, ACPI_FORMAT_NATIVE_UINT(address))); /* Decode the function parameter */ switch (function) { case ACPI_READ: status = acpi_hw_read_port((acpi_io_address) address, &value32, bit_width); *value = value32; break; case ACPI_WRITE: status = acpi_hw_write_port((acpi_io_address) address, (u32) * value, bit_width); break; default: status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS(status); }
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) { u64 address; u64 value64; acpi_status status; ACPI_FUNCTION_NAME(hw_read); /* Validate contents of the GAS register */ status = acpi_hw_validate_register(reg, 32, &address); if (ACPI_FAILURE(status)) { return (status); } /* Initialize entire 32-bit return value to zero */ *value = 0; /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_read_memory((acpi_physical_address) address, &value64, reg->bit_width); *value = (u32)value64; } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_read_port((acpi_io_address) address, value, reg->bit_width); } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", *value, reg->bit_width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); }
/****************************************************************************** * * FUNCTION: acpi_hw_register_read * * PARAMETERS: register_id - ACPI Register ID * return_value - Where the register value is returned * * RETURN: Status and the value read. * * DESCRIPTION: Read from the specified ACPI register * ******************************************************************************/ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) { u32 value = 0; acpi_status status; struct acpi_generic_address reg; ACPI_FUNCTION_TRACE(hw_register_read); switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ status = acpi_hw_read_multiple(&value, &acpi_gbl_xpm1a_status, &acpi_gbl_xpm1b_status); break; case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ status = acpi_hw_read_multiple(&value, &acpi_gbl_xpm1a_enable, &acpi_gbl_xpm1b_enable); break; case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ status = acpi_hw_read_multiple(&value, &acpi_gbl_FADT. xpm1a_control_block, &acpi_gbl_FADT. xpm1b_control_block); /* * Zero the write-only bits. From the ACPI specification, "Hardware * Write-Only Bits": "Upon reads to registers with write-only bits, * software masks out all write-only bits." */ value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ status = acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); break; /* Get reg info from FADT, overwrite correct width and addr */ case ACPI_REGISTER_GPE0_STATUS: reg = acpi_gbl_FADT.xgpe0_block; reg.bit_width = 32; reg.address = 0x420; status = acpi_hw_read(&value, ®); break; case ACPI_REGISTER_GPE0_ENABLE: reg = acpi_gbl_FADT.xgpe0_block; reg.bit_width = 32; reg.address = 0x428; status = acpi_hw_read(&value, ®); break; default: ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id)); status = AE_BAD_PARAMETER; break; } if (ACPI_SUCCESS(status)) { *return_value = value; } return_ACPI_STATUS(status); }
acpi_status acpi_hw_read(u64 *value, struct acpi_generic_address *reg) { u64 address; u8 access_width; u32 bit_width; u8 bit_offset; u64 value64; u32 value32; u8 index; acpi_status status; ACPI_FUNCTION_NAME(hw_read); /* Validate contents of the GAS register */ status = acpi_hw_validate_register(reg, 64, &address); if (ACPI_FAILURE(status)) { return (status); } /* * Initialize entire 64-bit return value to zero, convert access_width * into number of bits based */ *value = 0; access_width = acpi_hw_get_access_bit_width(address, reg, 64); bit_width = reg->bit_offset + reg->bit_width; bit_offset = reg->bit_offset; /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ index = 0; while (bit_width) { if (bit_offset >= access_width) { value64 = 0; bit_offset -= access_width; } else { if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_read_memory((acpi_physical_address) address + index * ACPI_DIV_8 (access_width), &value64, access_width); } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_read_port((acpi_io_address) address + index * ACPI_DIV_8 (access_width), &value32, access_width); value64 = (u64)value32; } } /* * Use offset style bit writes because "Index * AccessWidth" is * ensured to be less than 64-bits by acpi_hw_validate_register(). */ ACPI_SET_BITS(value, index * access_width, ACPI_MASK_BITS_ABOVE_64(access_width), value64); bit_width -= bit_width > access_width ? access_width : bit_width; index++; } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", ACPI_FORMAT_UINT64(*value), access_width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); }
acpi_status acpi_hw_register_read(u32 register_id, u32 * return_value) { u32 value = 0; acpi_status status; ACPI_FUNCTION_TRACE(hw_register_read); switch (register_id) { case ACPI_REGISTER_PM1_STATUS: status = acpi_hw_read_multiple(&value, &acpi_gbl_xpm1a_status, &acpi_gbl_xpm1b_status); break; case ACPI_REGISTER_PM1_ENABLE: status = acpi_hw_read_multiple(&value, &acpi_gbl_xpm1a_enable, &acpi_gbl_xpm1b_enable); break; case ACPI_REGISTER_PM1_CONTROL: status = acpi_hw_read_multiple(&value, &acpi_gbl_FADT. xpm1a_control_block, &acpi_gbl_FADT. xpm1b_control_block); value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; break; case ACPI_REGISTER_PM2_CONTROL: status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: status = acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); break; default: ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); status = AE_BAD_PARAMETER; break; } if (ACPI_SUCCESS(status)) { *return_value = value; } return_ACPI_STATUS(status); }
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) { u64 address; u8 access_width; u32 bit_width; u8 bit_offset; u64 value64; u32 new_value32, old_value32; u8 index; acpi_status status; ACPI_FUNCTION_NAME(hw_write); /* Validate contents of the GAS register */ status = acpi_hw_validate_register(reg, 32, &address); if (ACPI_FAILURE(status)) { return (status); } /* Convert access_width into number of bits based */ access_width = acpi_hw_get_access_bit_width(reg, 32); bit_width = reg->bit_offset + reg->bit_width; bit_offset = reg->bit_offset; /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ index = 0; while (bit_width) { /* * Use offset style bit reads because "Index * AccessWidth" is * ensured to be less than 32-bits by acpi_hw_validate_register(). */ new_value32 = ACPI_GET_BITS(&value, index * access_width, ACPI_MASK_BITS_ABOVE_32 (access_width)); if (bit_offset >= access_width) { bit_offset -= access_width; } else { /* * Use offset style bit masks because access_width is ensured * to be less than 32-bits by acpi_hw_validate_register() and * bit_offset/bit_width is less than access_width here. */ if (bit_offset) { new_value32 &= ACPI_MASK_BITS_BELOW(bit_offset); } if (bit_width < access_width) { new_value32 &= ACPI_MASK_BITS_ABOVE(bit_width); } if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { if (bit_offset || bit_width < access_width) { /* * Read old values in order not to modify the bits that * are beyond the register bit_width/bit_offset setting. */ status = acpi_os_read_memory((acpi_physical_address) address + index * ACPI_DIV_8 (access_width), &value64, access_width); old_value32 = (u32)value64; /* * Use offset style bit masks because access_width is * ensured to be less than 32-bits by * acpi_hw_validate_register() and bit_offset/bit_width is * less than access_width here. */ if (bit_offset) { old_value32 &= ACPI_MASK_BITS_ABOVE (bit_offset); bit_offset = 0; } if (bit_width < access_width) { old_value32 &= ACPI_MASK_BITS_BELOW (bit_width); } new_value32 |= old_value32; } value64 = (u64)new_value32; status = acpi_os_write_memory((acpi_physical_address) address + index * ACPI_DIV_8 (access_width), value64, access_width); } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ if (bit_offset || bit_width < access_width) { /* * Read old values in order not to modify the bits that * are beyond the register bit_width/bit_offset setting. */ status = acpi_hw_read_port((acpi_io_address) address + index * ACPI_DIV_8 (access_width), &old_value32, access_width); /* * Use offset style bit masks because access_width is * ensured to be less than 32-bits by * acpi_hw_validate_register() and bit_offset/bit_width is * less than access_width here. */ if (bit_offset) { old_value32 &= ACPI_MASK_BITS_ABOVE (bit_offset); bit_offset = 0; } if (bit_width < access_width) { old_value32 &= ACPI_MASK_BITS_BELOW (bit_width); } new_value32 |= old_value32; } status = acpi_hw_write_port((acpi_io_address) address + index * ACPI_DIV_8 (access_width), new_value32, access_width); } } /* * Index * access_width is ensured to be less than 32-bits by * acpi_hw_validate_register(). */ bit_width -= bit_width > access_width ? access_width : bit_width; index++; } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", value, access_width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); }