2020-01-18 11:38:21 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2020-05-28 21:40:53 +03:00
|
|
|
#pragma once
|
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
#include <Kernel/Devices/CharacterDevice.h>
|
2021-05-15 13:51:13 +03:00
|
|
|
#include <Kernel/IO.h>
|
2019-06-08 16:24:34 +03:00
|
|
|
|
2020-02-16 03:27:42 +03:00
|
|
|
namespace Kernel {
|
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
class SerialDevice final : public CharacterDevice {
|
|
|
|
AK_MAKE_ETERNAL
|
|
|
|
public:
|
2021-06-18 11:37:26 +03:00
|
|
|
static NonnullRefPtr<SerialDevice> must_create(size_t com_number);
|
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
virtual ~SerialDevice() override;
|
|
|
|
|
|
|
|
// ^CharacterDevice
|
2021-09-07 14:39:11 +03:00
|
|
|
virtual bool can_read(const OpenFileDescription&, size_t) const override;
|
|
|
|
virtual KResultOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override;
|
|
|
|
virtual bool can_write(const OpenFileDescription&, size_t) const override;
|
|
|
|
virtual KResultOr<size_t> write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override;
|
2019-06-08 16:24:34 +03:00
|
|
|
|
2021-04-23 17:25:40 +03:00
|
|
|
void put_char(char);
|
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
enum InterruptEnable {
|
|
|
|
LowPowerMode = 0x01 << 5,
|
|
|
|
SleepMode = 0x01 << 4,
|
|
|
|
ModemStatusInterrupt = 0x01 << 3,
|
|
|
|
ReceiverLineStatusInterrupt = 0x01 << 2,
|
|
|
|
TransmitterHoldingRegisterEmptyInterrupt = 0x01 << 1,
|
|
|
|
ReceivedDataAvailableInterrupt = 0x01 << 0
|
|
|
|
};
|
|
|
|
|
|
|
|
enum Baud {
|
|
|
|
Baud50 = 2304,
|
|
|
|
Baud110 = 1047,
|
|
|
|
Baud220 = 524,
|
|
|
|
Baud300 = 384,
|
|
|
|
Baud600 = 192,
|
|
|
|
Baud1200 = 96,
|
|
|
|
Baud2400 = 48,
|
|
|
|
Baud4800 = 24,
|
|
|
|
Baud9600 = 12,
|
|
|
|
Baud19200 = 6,
|
|
|
|
Baud38400 = 3,
|
|
|
|
Baud57600 = 2,
|
|
|
|
Baud115200 = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ParitySelect {
|
|
|
|
None = 0x00 << 3,
|
|
|
|
Odd = 0x01 << 3,
|
|
|
|
Even = 0x03 << 3,
|
|
|
|
Mark = 0x05 << 3,
|
|
|
|
Space = 0x07 << 3
|
|
|
|
};
|
|
|
|
|
|
|
|
enum StopBits {
|
|
|
|
One = 0x00 << 2,
|
|
|
|
Two = 0x01 << 2
|
|
|
|
};
|
|
|
|
|
|
|
|
enum WordLength {
|
|
|
|
FiveBits = 0x00,
|
|
|
|
SixBits = 0x01,
|
|
|
|
SevenBits = 0x02,
|
|
|
|
EightBits = 0x03
|
|
|
|
};
|
|
|
|
|
|
|
|
enum FIFOControl {
|
|
|
|
EnableFIFO = 0x01 << 0,
|
|
|
|
ClearReceiveFIFO = 0x01 << 1,
|
|
|
|
ClearTransmitFIFO = 0x01 << 2,
|
|
|
|
Enable64ByteFIFO = 0x01 << 5,
|
|
|
|
TriggerLevel1 = 0x00 << 6,
|
|
|
|
TriggerLevel2 = 0x01 << 6,
|
|
|
|
TriggerLevel3 = 0x02 << 6,
|
|
|
|
TriggerLevel4 = 0x03 << 6
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ModemControl {
|
|
|
|
AutoflowControlEnabled = 0x01 << 5,
|
|
|
|
LoopbackMode = 0x01 << 4,
|
|
|
|
AuxiliaryOutput2 = 0x01 << 3,
|
|
|
|
AuxiliaryOutput1 = 0x01 << 2,
|
|
|
|
RequestToSend = 0x01 << 1,
|
|
|
|
DataTerminalReady = 0x01 << 0
|
|
|
|
};
|
|
|
|
|
|
|
|
enum LineStatus {
|
|
|
|
ErrorInReceivedFIFO = 0x01 << 7,
|
|
|
|
EmptyDataHoldingRegisters = 0x01 << 6,
|
|
|
|
EmptyTransmitterHoldingRegister = 0x01 << 5,
|
|
|
|
BreakInterrupt = 0x01 << 4,
|
|
|
|
FramingError = 0x01 << 3,
|
|
|
|
ParityError = 0x01 << 2,
|
|
|
|
OverrunError = 0x01 << 1,
|
|
|
|
DataReady = 0x01 << 0
|
|
|
|
};
|
|
|
|
|
2020-12-25 20:01:19 +03:00
|
|
|
// ^Device
|
|
|
|
virtual mode_t required_mode() const override { return 0620; }
|
2021-01-21 20:49:56 +03:00
|
|
|
virtual String device_name() const override;
|
2020-12-25 20:01:19 +03:00
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
private:
|
2021-04-23 17:26:52 +03:00
|
|
|
friend class PCISerialDevice;
|
|
|
|
|
2021-06-18 11:37:26 +03:00
|
|
|
SerialDevice(IOAddress base_addr, unsigned minor);
|
|
|
|
|
2019-06-08 16:24:34 +03:00
|
|
|
// ^CharacterDevice
|
2021-07-11 02:46:09 +03:00
|
|
|
virtual StringView class_name() const override { return "SerialDevice"; }
|
2019-06-08 16:24:34 +03:00
|
|
|
|
|
|
|
void initialize();
|
2021-04-23 17:25:07 +03:00
|
|
|
void set_interrupts(bool interrupt_enable);
|
2019-06-08 16:24:34 +03:00
|
|
|
void set_baud(Baud);
|
2021-04-23 17:25:07 +03:00
|
|
|
void set_fifo_control(u8 fifo_control);
|
2019-06-08 16:24:34 +03:00
|
|
|
void set_line_control(ParitySelect, StopBits, WordLength);
|
|
|
|
void set_break_enable(bool break_enable);
|
2021-04-23 17:25:07 +03:00
|
|
|
void set_modem_control(u8 modem_control);
|
|
|
|
u8 get_line_status() const;
|
|
|
|
|
2021-05-15 13:51:13 +03:00
|
|
|
IOAddress m_base_addr;
|
2021-04-23 17:25:07 +03:00
|
|
|
bool m_interrupt_enable { false };
|
|
|
|
u8 m_fifo_control { 0 };
|
|
|
|
Baud m_baud { Baud38400 };
|
|
|
|
ParitySelect m_parity_select { None };
|
|
|
|
StopBits m_stop_bits { One };
|
|
|
|
WordLength m_word_length { EightBits };
|
|
|
|
bool m_break_enable { false };
|
|
|
|
u8 m_modem_control { 0 };
|
2021-04-23 17:25:40 +03:00
|
|
|
bool m_last_put_char_was_carriage_return { false };
|
2021-09-05 20:02:03 +03:00
|
|
|
Spinlock m_serial_lock;
|
2019-06-08 16:24:34 +03:00
|
|
|
};
|
2020-02-16 03:27:42 +03:00
|
|
|
|
|
|
|
}
|