Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <Kernel/Devices/CharacterDevice.h>
28
29namespace Kernel {
30
31#define SERIAL_COM1_ADDR 0x3F8
32#define SERIAL_COM2_ADDR 0x2F8
33#define SERIAL_COM3_ADDR 0x3E8
34#define SERIAL_COM4_ADDR 0x2E8
35
36class SerialDevice final : public CharacterDevice {
37 AK_MAKE_ETERNAL
38public:
39 SerialDevice(int base_addr, unsigned minor);
40 virtual ~SerialDevice() override;
41
42 // ^CharacterDevice
43 virtual bool can_read(const FileDescription&) const override;
44 virtual ssize_t read(FileDescription&, u8*, ssize_t) override;
45 virtual bool can_write(const FileDescription&) const override;
46 virtual ssize_t write(FileDescription&, const u8*, ssize_t) override;
47
48 enum InterruptEnable {
49 LowPowerMode = 0x01 << 5,
50 SleepMode = 0x01 << 4,
51 ModemStatusInterrupt = 0x01 << 3,
52 ReceiverLineStatusInterrupt = 0x01 << 2,
53 TransmitterHoldingRegisterEmptyInterrupt = 0x01 << 1,
54 ReceivedDataAvailableInterrupt = 0x01 << 0
55 };
56
57 enum Baud {
58 Baud50 = 2304,
59 Baud110 = 1047,
60 Baud220 = 524,
61 Baud300 = 384,
62 Baud600 = 192,
63 Baud1200 = 96,
64 Baud2400 = 48,
65 Baud4800 = 24,
66 Baud9600 = 12,
67 Baud19200 = 6,
68 Baud38400 = 3,
69 Baud57600 = 2,
70 Baud115200 = 1
71 };
72
73 enum ParitySelect {
74 None = 0x00 << 3,
75 Odd = 0x01 << 3,
76 Even = 0x03 << 3,
77 Mark = 0x05 << 3,
78 Space = 0x07 << 3
79 };
80
81 enum StopBits {
82 One = 0x00 << 2,
83 Two = 0x01 << 2
84 };
85
86 enum WordLength {
87 FiveBits = 0x00,
88 SixBits = 0x01,
89 SevenBits = 0x02,
90 EightBits = 0x03
91 };
92
93 enum FIFOControl {
94 EnableFIFO = 0x01 << 0,
95 ClearReceiveFIFO = 0x01 << 1,
96 ClearTransmitFIFO = 0x01 << 2,
97 Enable64ByteFIFO = 0x01 << 5,
98 TriggerLevel1 = 0x00 << 6,
99 TriggerLevel2 = 0x01 << 6,
100 TriggerLevel3 = 0x02 << 6,
101 TriggerLevel4 = 0x03 << 6
102 };
103
104 enum ModemControl {
105 AutoflowControlEnabled = 0x01 << 5,
106 LoopbackMode = 0x01 << 4,
107 AuxiliaryOutput2 = 0x01 << 3,
108 AuxiliaryOutput1 = 0x01 << 2,
109 RequestToSend = 0x01 << 1,
110 DataTerminalReady = 0x01 << 0
111 };
112
113 enum LineStatus {
114 ErrorInReceivedFIFO = 0x01 << 7,
115 EmptyDataHoldingRegisters = 0x01 << 6,
116 EmptyTransmitterHoldingRegister = 0x01 << 5,
117 BreakInterrupt = 0x01 << 4,
118 FramingError = 0x01 << 3,
119 ParityError = 0x01 << 2,
120 OverrunError = 0x01 << 1,
121 DataReady = 0x01 << 0
122 };
123
124private:
125 // ^CharacterDevice
126 virtual const char* class_name() const override { return "SerialDevice"; }
127
128 void initialize();
129 void set_interrupts(char interrupt_enable);
130 void set_baud(Baud);
131 void set_fifo_control(char fifo_control);
132 void set_line_control(ParitySelect, StopBits, WordLength);
133 void set_break_enable(bool break_enable);
134 void set_modem_control(char modem_control);
135 char get_line_status() const;
136 bool rx_ready();
137 bool tx_ready();
138
139 int m_base_addr;
140 char m_interrupt_enable;
141 char m_fifo_control;
142 Baud m_baud;
143 ParitySelect m_parity_select;
144 StopBits m_stop_bits;
145 WordLength m_word_length;
146 bool m_break_enable;
147 char m_modem_control;
148};
149
150}