Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <Kernel/Devices/CharacterDevice.h>
10#include <Kernel/IOWindow.h>
11
12namespace Kernel {
13
14class SerialDevice final : public CharacterDevice {
15 friend class DeviceManagement;
16
17public:
18 static NonnullLockRefPtr<SerialDevice> must_create(size_t com_number);
19
20 virtual ~SerialDevice() override;
21
22 // ^CharacterDevice
23 virtual bool can_read(OpenFileDescription const&, u64) const override;
24 virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override;
25 virtual bool can_write(OpenFileDescription const&, u64) const override;
26 virtual ErrorOr<size_t> write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override;
27
28 void put_char(char);
29
30 enum InterruptEnable {
31 LowPowerMode = 0x01 << 5,
32 SleepMode = 0x01 << 4,
33 ModemStatusInterrupt = 0x01 << 3,
34 ReceiverLineStatusInterrupt = 0x01 << 2,
35 TransmitterHoldingRegisterEmptyInterrupt = 0x01 << 1,
36 ReceivedDataAvailableInterrupt = 0x01 << 0
37 };
38
39 enum Baud {
40 Baud50 = 2304,
41 Baud110 = 1047,
42 Baud220 = 524,
43 Baud300 = 384,
44 Baud600 = 192,
45 Baud1200 = 96,
46 Baud2400 = 48,
47 Baud4800 = 24,
48 Baud9600 = 12,
49 Baud19200 = 6,
50 Baud38400 = 3,
51 Baud57600 = 2,
52 Baud115200 = 1
53 };
54
55 enum ParitySelect {
56 None = 0x00 << 3,
57 Odd = 0x01 << 3,
58 Even = 0x03 << 3,
59 Mark = 0x05 << 3,
60 Space = 0x07 << 3
61 };
62
63 enum StopBits {
64 One = 0x00 << 2,
65 Two = 0x01 << 2
66 };
67
68 enum WordLength {
69 FiveBits = 0x00,
70 SixBits = 0x01,
71 SevenBits = 0x02,
72 EightBits = 0x03
73 };
74
75 enum FIFOControl {
76 EnableFIFO = 0x01 << 0,
77 ClearReceiveFIFO = 0x01 << 1,
78 ClearTransmitFIFO = 0x01 << 2,
79 Enable64ByteFIFO = 0x01 << 5,
80 TriggerLevel1 = 0x00 << 6,
81 TriggerLevel2 = 0x01 << 6,
82 TriggerLevel3 = 0x02 << 6,
83 TriggerLevel4 = 0x03 << 6
84 };
85
86 enum ModemControl {
87 AutoflowControlEnabled = 0x01 << 5,
88 LoopbackMode = 0x01 << 4,
89 AuxiliaryOutput2 = 0x01 << 3,
90 AuxiliaryOutput1 = 0x01 << 2,
91 RequestToSend = 0x01 << 1,
92 DataTerminalReady = 0x01 << 0
93 };
94
95 enum LineStatus {
96 ErrorInReceivedFIFO = 0x01 << 7,
97 EmptyDataHoldingRegisters = 0x01 << 6,
98 EmptyTransmitterHoldingRegister = 0x01 << 5,
99 BreakInterrupt = 0x01 << 4,
100 FramingError = 0x01 << 3,
101 ParityError = 0x01 << 2,
102 OverrunError = 0x01 << 1,
103 DataReady = 0x01 << 0
104 };
105
106private:
107 SerialDevice(NonnullOwnPtr<IOWindow> registers_io_window, unsigned minor);
108
109 friend class PCISerialDevice;
110
111 // ^CharacterDevice
112 virtual StringView class_name() const override { return "SerialDevice"sv; }
113
114 void initialize();
115 void set_interrupts(bool interrupt_enable);
116 void set_baud(Baud);
117 void set_fifo_control(u8 fifo_control);
118 void set_line_control(ParitySelect, StopBits, WordLength);
119 void set_break_enable(bool break_enable);
120 void set_modem_control(u8 modem_control);
121 u8 get_line_status() const;
122
123 mutable NonnullOwnPtr<IOWindow> m_registers_io_window;
124 bool m_interrupt_enable { false };
125 u8 m_fifo_control { 0 };
126 Baud m_baud { Baud38400 };
127 ParitySelect m_parity_select { None };
128 StopBits m_stop_bits { One };
129 WordLength m_word_length { EightBits };
130 bool m_break_enable { false };
131 u8 m_modem_control { 0 };
132 bool m_last_put_char_was_carriage_return { false };
133 Spinlock<LockRank::None> m_serial_lock {};
134};
135
136}