Commit Diff


commit - 69da5ffe1eeea1c4e88eaa4bbc4ce4ab4e296c94
commit + 6ed628b42830938a7919dd60f8af14519ce778f2
blob - e12fb16f4c3017b5c462c6b4c4b43279565a4098
blob + fb3b039ec6b295a04932f32082d51301caf35381
--- include/uart16550.h
+++ include/uart16550.h
@@ -8,6 +8,25 @@
 namespace Uart16550 {
 
 
+struct ReceiveBufferRegister {
+    static constexpr auto OFFSET = 0x00;
+};
+
+struct TransmitHoldingRegister {
+    static constexpr auto OFFSET = 0x00;
+};
+
+struct DivisorLatchLowRegister {
+    static constexpr auto OFFSET = 0x00;
+};
+
+
+
+struct DivisorLatchHighRegister {
+    static constexpr auto OFFSET = 0x04;
+};
+
+
 struct InterruptEnableRegister {
     union _U {
         struct _Bits {
@@ -54,6 +73,37 @@ struct FifoControlRegister {
 static_assert(sizeof(FifoControlRegister) == 1, "should be byte");
 
 
+struct LineControlRegister {
+    enum DataLengthSelect
+    {
+        BITS_5 = 0,
+        BITS_6 = 1,
+        BITS_7 = 2,
+        BITS_8 = 3,
+    };
+
+    union _U {
+        struct _Bits {
+            uint8_t m_DataLengthSelect  : 2;
+            uint8_t m_NumberOfStopBits  : 1;
+            uint8_t m_ParityEnable      : 1;
+            uint8_t m_EvenParitySelect  : 2;
+            uint8_t m_BreakControl      : 1;
+            uint8_t m_DivisorLatchAccess: 1;
+        } m_Bits;
+        uint8_t m_nValue;
+    } m_u;
+
+    explicit LineControlRegister(uint8_t nValue = 0)
+    {
+        m_u.m_nValue = nValue;
+    }
+
+    static constexpr auto OFFSET = 0x0c;
+};
+static_assert(sizeof(LineControlRegister) == 1, "should be byte");
+
+
 struct ModemControlRegister {
     union _U {
         struct _Bits {
blob - 2e8d89e89f1d6851336fc4fe2137e6450fdac72c
blob + 5c655aa36e41c08c9bb6f142c97148954713f1c9
--- uart_a64.cc
+++ uart_a64.cc
@@ -22,18 +22,29 @@ constexpr auto CLOCK_DIVISOR = (SERIAL_CLOCK + (BAUDRA
 
 static_assert(CLOCK_DIVISOR == 13, "Should be 13");
 
+template <typename T>
+uint8_t read8()
+{
+    return Hw::read8(UART0_BASE + T::OFFSET);
+}
 
 template <typename T>
 T read()
 {
-    return T{Hw::read8(UART0_BASE + T::OFFSET)};
+    return T{read8<T>()};
 }
 
 
 template <typename T>
+void write8(uint8_t nValue)
+{
+    Hw::write8(UART0_BASE + T::OFFSET, nValue);
+}
+
+template <typename T>
 void write(T Register)
 {
-    Hw::write8(UART0_BASE + T::OFFSET, Register.m_u.m_nValue);
+    write8<T>(Register.m_u.m_nValue);
 }
 
 
@@ -61,21 +72,43 @@ void initialize()
     FifoControlRegister.m_u.m_Bits.m_RcvrFifoReset = 1;
     FifoControlRegister.m_u.m_Bits.m_XmitFifoReset = 1;
     write(FifoControlRegister);
+
+    Uart16550::LineControlRegister LineControlRegister;
+    LineControlRegister.m_u.m_Bits.m_DataLengthSelect = Uart16550::LineControlRegister::BITS_8;
+    write(LineControlRegister);
+
+    LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 1;
+    write(LineControlRegister);
+
+    write8<Uart16550::DivisorLatchLowRegister>(CLOCK_DIVISOR & 0xff);
+    write8<Uart16550::DivisorLatchHighRegister>((CLOCK_DIVISOR >> 8) & 0xff);
+
+    LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 0;
+    write(LineControlRegister);
 }
 
 
 void send(uint8_t nValue)
 {
-    (void)nValue;
-    /* TBD! */
-    // Hw::write32(UART_BASE + Pl011::DATA_REGISTER, nValue);
+    for (; ; )
+    {
+        const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
+        if (LineStatusRegister.m_u.m_Bits.m_TxHoldingRegisterEmpty)
+            break;
+    }
+    write8<Uart16550::TransmitHoldingRegister>(nValue);
 }
 
 
 uint8_t recv()
 {
-    // return Hw::read32(UART_BASE + Pl011::DATA_REGISTER) & 0xff;
-    return 0;
+    for (; ; )
+    {
+        const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
+        if (LineStatusRegister.m_u.m_Bits.m_DataReady)
+            break;
+    }
+    return read8<Uart16550::ReceiveBufferRegister>();
 }