| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/graphics/display/drivers/intel-i915/firmware-bridge.h" |
| |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/loop.h> |
| #include <lib/device-protocol/pci.h> |
| #include <lib/fidl/cpp/wire/channel.h> |
| #include <lib/mmio/mmio-buffer.h> |
| #include <lib/stdcompat/span.h> |
| #include <lib/zx/result.h> |
| #include <zircon/errors.h> |
| #include <zircon/types.h> |
| |
| #include <cstdint> |
| #include <optional> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/devices/pci/testing/pci_protocol_fake.h" |
| |
| namespace i915 { |
| |
| namespace { |
| |
| class PciConfigOpRegionTest : public ::testing::Test { |
| public: |
| void SetUp() override { |
| loop_.StartThread("pci-fidl-server-thread"); |
| pci_ = fake_pci_.SetUpFidlServer(loop_); |
| pci_op_region_.emplace(pci_); |
| } |
| |
| protected: |
| async::Loop loop_{&kAsyncLoopConfigNeverAttachToThread}; |
| pci::FakePciProtocol fake_pci_; |
| ddk::Pci pci_; |
| std::optional<PciConfigOpRegion> pci_op_region_; |
| }; |
| |
| TEST_F(PciConfigOpRegionTest, ReadMemoryOpRegionAddress) { |
| pci_.WriteConfig32(0xfc, 0x42424242); |
| |
| const zx::result<zx_paddr_t> address = pci_op_region_->ReadMemoryOpRegionAddress(); |
| ASSERT_TRUE(address.is_ok()) << address.status_string(); |
| EXPECT_EQ(0x42424242u, address.value()); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, ReadMemoryOpRegionAddressUnsupported) { |
| pci_.WriteConfig32(0xfc, 0); |
| |
| const zx::result<zx_paddr_t> address = pci_op_region_->ReadMemoryOpRegionAddress(); |
| EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, address.status_value()) << address.status_string(); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, ReadMemoryOpRegionAddressError) { |
| auto [pci_client, pci_server] = fidl::Endpoints<fuchsia_hardware_pci::Device>::Create(); |
| pci_server.Close(ZX_OK); |
| |
| ddk::Pci disconnected_pci(std::move(pci_client)); |
| PciConfigOpRegion disconnected_pci_op_region(disconnected_pci); |
| |
| const zx::result<zx_paddr_t> address = disconnected_pci_op_region.ReadMemoryOpRegionAddress(); |
| EXPECT_EQ(ZX_ERR_PEER_CLOSED, address.status_value()) << address.status_string(); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, IsSystemControlInterruptInUse) { |
| { |
| pci_.WriteConfig16(0xe8, 0x8000); |
| const zx::result<bool> in_use = pci_op_region_->IsSystemControlInterruptInUse(); |
| ASSERT_TRUE(in_use.is_ok()) << in_use.status_string(); |
| EXPECT_EQ(false, in_use.value()); |
| } |
| { |
| pci_.WriteConfig16(0xe8, 0x8001); |
| const zx::result<bool> in_use = pci_op_region_->IsSystemControlInterruptInUse(); |
| ASSERT_TRUE(in_use.is_ok()) << in_use.status_string(); |
| EXPECT_EQ(true, in_use.value()); |
| } |
| } |
| |
| TEST_F(PciConfigOpRegionTest, IsSystemControlInterruptInUseUnsupported) { |
| { |
| pci_.WriteConfig16(0xe8, 0x0000); |
| const zx::result<bool> in_use = pci_op_region_->IsSystemControlInterruptInUse(); |
| EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, in_use.status_value()); |
| } |
| { |
| pci_.WriteConfig16(0xe8, 0x0001); |
| const zx::result<bool> in_use = pci_op_region_->IsSystemControlInterruptInUse(); |
| EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, in_use.status_value()); |
| } |
| } |
| |
| TEST_F(PciConfigOpRegionTest, IsSystemControlInterruptInUseError) { |
| auto [pci_client, pci_server] = fidl::Endpoints<fuchsia_hardware_pci::Device>::Create(); |
| pci_server.Close(ZX_OK); |
| |
| ddk::Pci disconnected_pci(std::move(pci_client)); |
| PciConfigOpRegion disconnected_pci_op_region(disconnected_pci); |
| |
| const zx::result<bool> in_use = disconnected_pci_op_region.IsSystemControlInterruptInUse(); |
| EXPECT_EQ(ZX_ERR_PEER_CLOSED, in_use.status_value()) << in_use.status_string(); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, TriggerSystemControlInterrupt) { |
| pci_.WriteConfig16(0xe8, 0x8000); |
| |
| const zx::result<> trigger_result = pci_op_region_->TriggerSystemControlInterrupt(); |
| ASSERT_TRUE(trigger_result.is_ok()) << trigger_result.status_string(); |
| |
| uint16_t swsci_trigger_register = 0; |
| EXPECT_EQ(ZX_OK, pci_.ReadConfig16(0xe8, &swsci_trigger_register)); |
| EXPECT_EQ(0x8001, swsci_trigger_register); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, TriggerSystemControlInterruptInUse) { |
| pci_.WriteConfig16(0xe8, 0x8001); |
| const zx::result<> result = pci_op_region_->TriggerSystemControlInterrupt(); |
| EXPECT_EQ(ZX_ERR_BAD_STATE, result.status_value()) << result.status_string(); |
| } |
| |
| TEST_F(PciConfigOpRegionTest, TriggerSystemControlInterruptUnsupported) { |
| { |
| pci_.WriteConfig16(0xe8, 0x0000); |
| const zx::result<> result = pci_op_region_->TriggerSystemControlInterrupt(); |
| EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, result.status_value()) << result.status_string(); |
| } |
| { |
| pci_.WriteConfig16(0xe8, 0x0001); |
| const zx::result<> result = pci_op_region_->TriggerSystemControlInterrupt(); |
| EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, result.status_value()) << result.status_string(); |
| } |
| } |
| |
| TEST_F(PciConfigOpRegionTest, TriggerSystemControlInterruptPciError) { |
| auto [pci_client, pci_server] = fidl::Endpoints<fuchsia_hardware_pci::Device>::Create(); |
| pci_server.Close(ZX_OK); |
| |
| ddk::Pci disconnected_pci(std::move(pci_client)); |
| PciConfigOpRegion disconnected_pci_op_region(disconnected_pci); |
| |
| const zx::result<> result = disconnected_pci_op_region.TriggerSystemControlInterrupt(); |
| EXPECT_EQ(ZX_ERR_PEER_CLOSED, result.status_value()) << result.status_string(); |
| } |
| |
| } // namespace |
| |
| } // namespace i915 |