| 269 | |
| 270 | return true; |
| 271 | } |
| 272 | |
| 273 | BAN::ErrorOr<void> PS2Controller::initialize_impl(uint8_t scancode_set) |
| 274 | { |
| 275 | PS2DeviceInitInfo::DeviceInfo devices[2] { |
| 276 | PS2DeviceInitInfo::DeviceInfo { |
| 277 | .type = DeviceType::None, |
| 278 | .interrupt = 0xFF, |
| 279 | }, |
| 280 | PS2DeviceInitInfo::DeviceInfo { |
| 281 | .type = DeviceType::None, |
| 282 | .interrupt = 0xFF, |
| 283 | }, |
| 284 | }; |
| 285 | |
| 286 | if (auto* ns = ACPI::ACPI::get().acpi_namespace()) |
| 287 | { |
| 288 | dprintln("Looking for PS/2 devices in ACPI namespace..."); |
| 289 | |
| 290 | const auto lookup_devices = |
| 291 | [ns](const BAN::Vector<BAN::String>& eisa_id_strs) -> decltype(ns->find_device_with_eisa_id(""_sv)) |
| 292 | { |
| 293 | BAN::Vector<BAN::StringView> eisa_ids; |
| 294 | TRY(eisa_ids.reserve(eisa_id_strs.size())); |
| 295 | for (const auto& str : eisa_id_strs) |
| 296 | TRY(eisa_ids.push_back(str.sv())); |
| 297 | return ns->find_device_with_eisa_id(eisa_ids.span()); |
| 298 | }; |
| 299 | |
| 300 | struct PS2ResourceSetting |
| 301 | { |
| 302 | DeviceType type; |
| 303 | BAN::Optional<uint16_t> command_port; |
| 304 | BAN::Optional<uint16_t> data_port; |
| 305 | BAN::Optional<uint8_t> irq; |
| 306 | }; |
| 307 | |
| 308 | const auto get_device_info = |
| 309 | [ns](const ACPI::AML::Scope& scope, const auto& type) -> BAN::ErrorOr<PS2ResourceSetting> |
| 310 | { |
| 311 | auto [sta_path, sta_obj] = TRY(ns->find_named_object(scope, TRY(ACPI::AML::NameString::from_string("_STA"_sv)), true)); |
| 312 | if (sta_obj == nullptr) |
| 313 | return BAN::Error::from_errno(ENODEV); |
| 314 | const auto sta_result = TRY(ACPI::AML::convert_node(TRY(ACPI::AML::evaluate_node(sta_path, sta_obj->node)), ACPI::AML::ConvInteger, -1)).as.integer.value; |
| 315 | if ((sta_result & 0b11) != 0b11) |
| 316 | return BAN::Error::from_errno(ENODEV); |
| 317 | |
| 318 | auto [crs_path, crs_obj] = TRY(ns->find_named_object(scope, TRY(ACPI::AML::NameString::from_string("_CRS"_sv)), true)); |
| 319 | if (crs_obj == nullptr) |
| 320 | return PS2ResourceSetting {}; |
| 321 | |
| 322 | const auto crs = TRY(ACPI::AML::evaluate_node(crs_path, crs_obj->node)); |
| 323 | if (crs.type != ACPI::AML::Node::Type::Buffer) |
| 324 | { |
| 325 | dwarnln("PS/2 _CRS is not a buffer, but {}", crs); |
| 326 | return BAN::Error::from_errno(EINVAL); |
| 327 | } |
| 328 |
no test coverage detected