Serenity Operating System
1/*
2 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/Bus/PCI/API.h>
8#include <Kernel/Devices/PCISerialDevice.h>
9#include <Kernel/IOWindow.h>
10#include <Kernel/Sections.h>
11
12namespace Kernel {
13
14static SerialDevice* s_the = nullptr;
15
16UNMAP_AFTER_INIT void PCISerialDevice::detect()
17{
18 size_t current_device_minor = 68;
19 MUST(PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
20 for (auto& board_definition : board_definitions) {
21 if (board_definition.device_id != device_identifier.hardware_id())
22 continue;
23
24 auto registers_io_window = IOWindow::create_for_pci_device_bar(device_identifier, static_cast<PCI::HeaderType0BaseRegister>(board_definition.pci_bar)).release_value_but_fixme_should_propagate_errors();
25 auto first_offset_registers_io_window = registers_io_window->create_from_io_window_with_offset(board_definition.first_offset).release_value_but_fixme_should_propagate_errors();
26
27 for (size_t i = 0; i < board_definition.port_count; i++) {
28 auto port_registers_io_window = first_offset_registers_io_window->create_from_io_window_with_offset(board_definition.port_size * i).release_value_but_fixme_should_propagate_errors();
29 auto serial_device = new SerialDevice(move(port_registers_io_window), current_device_minor++);
30 if (board_definition.baud_rate != SerialDevice::Baud::Baud38400) // non-default baud
31 serial_device->set_baud(board_definition.baud_rate);
32
33 // If this is the first port of the first pci serial device, store it as the debug PCI serial port (TODO: Make this configurable somehow?)
34 if (!is_available())
35 s_the = serial_device;
36 // NOTE: We intentionally leak the reference to serial_device here.
37 }
38
39 dmesgln("PCISerialDevice: Found {} @ {}", board_definition.name, device_identifier.address());
40 return;
41 }
42 }));
43}
44
45SerialDevice& PCISerialDevice::the()
46{
47 VERIFY(s_the);
48 return *s_the;
49}
50
51bool PCISerialDevice::is_available()
52{
53 return s_the;
54}
55
56}