#include #include #include #include #include #include SCENARIO("Devices allow access to their resources", "[kapi][devices]") { GIVEN("A device without any resources") { auto device = kstd::make_shared("test_device"); THEN("its resources vector is empty") { REQUIRE(device->resources().empty()); } WHEN("trying to get the first MMIO resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first MMIO resource via the unsafe accessor") { auto result = device->request_resource(kapi::devices::resource_type::mmio, 0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first I/O port resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first I/O port resource via the unsafe accessor") { auto result = device->request_resource(kapi::devices::resource_type::port, 0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first IRQ resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first IRQ resource via the unsafe accessor") { auto result = device->request_resource(kapi::devices::resource_type::irq, 0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first DMA resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("trying to get the first DMA resource via the unsafe accessor") { auto result = device->request_resource(kapi::devices::resource_type::dma, 0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } WHEN("adding an MMIO resource") { auto range = kapi::devices::mmio_range{{}, kstd::units::bytes{100}}; device->set_resources({kapi::devices::resource{range}}); AND_WHEN("trying to get the first MMIO resource via the type-safe accessor") { auto result = device->request_resource(); THEN("the result is a success") { REQUIRE(result); } THEN("the result is the expected MMIO range") { REQUIRE(result == range); } } AND_WHEN("trying to get the first I/O port resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first IRQ resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first DMA resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } } WHEN("adding an I/O port resource") { auto port = kapi::devices::io_port{0x40, 1}; device->set_resources({kapi::devices::resource{port}}); AND_WHEN("trying to get the first MMIO resource via the type-safe accessor") { auto result = device->request_resource(); THEN("the result is en error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first I/O port resource via the type-safe accessor") { auto result = device->request_resource(); THEN("the result is a success") { REQUIRE(result); } THEN("the result is the expected MMIO range") { REQUIRE(result == port); } } AND_WHEN("trying to get the first IRQ resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first DMA resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } } WHEN("adding an interrupt line resource") { auto line = kapi::devices::interrupt_line{128}; device->set_resources({kapi::devices::resource{line}}); AND_WHEN("trying to get the first MMIO resource via the type-safe accessor") { auto result = device->request_resource(); THEN("the result is en error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first I/O port resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first IRQ resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is a success") { REQUIRE(result); } THEN("the result is the expected interrupt line") { REQUIRE(result == line); } } AND_WHEN("trying to get the first DMA resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } } WHEN("adding a DMA channel resource") { auto channel = kapi::devices::dma_channel{1024}; device->set_resources({kapi::devices::resource{channel}}); AND_WHEN("trying to get the first MMIO resource via the type-safe accessor") { auto result = device->request_resource(); THEN("the result is en error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first I/O port resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first IRQ resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is an error") { REQUIRE_FALSE(result); } THEN("the error is 'invalid argument'") { REQUIRE(result.error() == kstd::errc::invalid_argument); } } AND_WHEN("trying to get the first DMA resource via the type-safe accessor") { auto result = device->request_resource(0); THEN("the result is a success") { REQUIRE(result); } THEN("the result it the expected DMA channel") { REQUIRE(result == channel); } } } } }