acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) { u64 address; 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); } /* * 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_write_memory((acpi_physical_address) address, (u64)value, reg->bit_width); } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_write_port((acpi_io_address) address, value, reg->bit_width); } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Wrote: %8.8X width %2d to %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_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_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); }
acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg) { u64 address; u8 access_width; u32 bit_width; u8 bit_offset; u64 value64; u8 index; acpi_status status; ACPI_FUNCTION_NAME(hw_write); /* Validate contents of the GAS register */ status = acpi_hw_validate_register(reg, 64, &address); if (ACPI_FAILURE(status)) { return (status); } /* Convert access_width into number of bits based */ 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) { /* * Use offset style bit reads because "Index * AccessWidth" is * ensured to be less than 64-bits by acpi_hw_validate_register(). */ value64 = ACPI_GET_BITS(&value, index * access_width, ACPI_MASK_BITS_ABOVE_64(access_width)); if (bit_offset >= access_width) { bit_offset -= access_width; } else { if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 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 */ status = acpi_hw_write_port((acpi_io_address) address + index * ACPI_DIV_8 (access_width), (u32)value64, 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%8.8X width %2d to %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_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); }
acpi_status acpi_hw_read(u32 *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, 32, &address); if (ACPI_FAILURE(status)) { return (status); } /* * Initialize entire 32-bit return value to zero, convert access_width * into number of bits based */ *value = 0; 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) { if (bit_offset >= access_width) { value32 = 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); value32 = (u32)value64; } 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); } /* * Use offset style bit masks because: * bit_offset < access_width/bit_width < access_width, and * access_width is ensured to be less than 32-bits by * acpi_hw_validate_register(). */ if (bit_offset) { value32 &= ACPI_MASK_BITS_BELOW(bit_offset); bit_offset = 0; } if (bit_width < access_width) { value32 &= ACPI_MASK_BITS_ABOVE(bit_width); } } /* * Use offset style bit writes because "Index * AccessWidth" is * ensured to be less than 32-bits by acpi_hw_validate_register(). */ ACPI_SET_BITS(value, index * access_width, ACPI_MASK_BITS_ABOVE_32(access_width), value32); bit_width -= bit_width > access_width ? access_width : bit_width; index++; } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", *value, access_width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); }