blob: e7c1619bcb4f83344f14ff9d0c8bedafed94389a [file] [log] [blame]
// 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