duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

sio.cpp (3723B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #include "sio.h"
      5 #include "controller.h"
      6 
      7 #include "util/state_wrapper.h"
      8 
      9 #include "common/bitfield.h"
     10 #include "common/bitutils.h"
     11 #include "common/log.h"
     12 
     13 #include <array>
     14 #include <memory>
     15 
     16 Log_SetChannel(SIO);
     17 
     18 namespace SIO {
     19 namespace {
     20 
     21 union SIO_CTRL
     22 {
     23   u16 bits;
     24 
     25   BitField<u16, bool, 0, 1> TXEN;
     26   BitField<u16, bool, 1, 1> DTROUTPUT;
     27   BitField<u16, bool, 2, 1> RXEN;
     28   BitField<u16, bool, 3, 1> TXOUTPUT;
     29   BitField<u16, bool, 4, 1> ACK;
     30   BitField<u16, bool, 5, 1> RTSOUTPUT;
     31   BitField<u16, bool, 6, 1> RESET;
     32   BitField<u16, u8, 8, 2> RXIMODE;
     33   BitField<u16, bool, 10, 1> TXINTEN;
     34   BitField<u16, bool, 11, 1> RXINTEN;
     35   BitField<u16, bool, 12, 1> ACKINTEN;
     36 };
     37 
     38 union SIO_STAT
     39 {
     40   u32 bits;
     41 
     42   BitField<u32, bool, 0, 1> TXRDY;
     43   BitField<u32, bool, 1, 1> RXFIFONEMPTY;
     44   BitField<u32, bool, 2, 1> TXDONE;
     45   BitField<u32, bool, 3, 1> RXPARITY;
     46   BitField<u32, bool, 4, 1> RXFIFOOVERRUN;
     47   BitField<u32, bool, 5, 1> RXBADSTOPBIT;
     48   BitField<u32, bool, 6, 1> RXINPUTLEVEL;
     49   BitField<u32, bool, 7, 1> DSRINPUTLEVEL;
     50   BitField<u32, bool, 8, 1> CTSINPUTLEVEL;
     51   BitField<u32, bool, 9, 1> INTR;
     52   BitField<u32, u32, 11, 15> TMR;
     53 };
     54 
     55 union SIO_MODE
     56 {
     57   u16 bits;
     58 
     59   BitField<u16, u8, 0, 2> reload_factor;
     60   BitField<u16, u8, 2, 2> character_length;
     61   BitField<u16, bool, 4, 1> parity_enable;
     62   BitField<u16, u8, 5, 1> parity_type;
     63   BitField<u16, u8, 6, 2> stop_bit_length;
     64 };
     65 } // namespace
     66 
     67 static void SoftReset();
     68 
     69 static SIO_CTRL s_SIO_CTRL = {};
     70 static SIO_STAT s_SIO_STAT = {};
     71 static SIO_MODE s_SIO_MODE = {};
     72 static u16 s_SIO_BAUD = 0;
     73 
     74 } // namespace SIO
     75 
     76 void SIO::Initialize()
     77 {
     78   Reset();
     79 }
     80 
     81 void SIO::Shutdown()
     82 {
     83 }
     84 
     85 void SIO::Reset()
     86 {
     87   SoftReset();
     88 }
     89 
     90 bool SIO::DoState(StateWrapper& sw)
     91 {
     92   sw.Do(&s_SIO_CTRL.bits);
     93   sw.Do(&s_SIO_STAT.bits);
     94   sw.Do(&s_SIO_MODE.bits);
     95   sw.Do(&s_SIO_BAUD);
     96 
     97   return !sw.HasError();
     98 }
     99 
    100 u32 SIO::ReadRegister(u32 offset)
    101 {
    102   switch (offset)
    103   {
    104     case 0x00: // SIO_DATA
    105     {
    106       ERROR_LOG("Read SIO_DATA");
    107 
    108       const u8 value = 0xFF;
    109       return (ZeroExtend32(value) | (ZeroExtend32(value) << 8) | (ZeroExtend32(value) << 16) |
    110               (ZeroExtend32(value) << 24));
    111     }
    112 
    113     case 0x04: // SIO_STAT
    114     {
    115       const u32 bits = s_SIO_STAT.bits;
    116       return bits;
    117     }
    118 
    119     case 0x08: // SIO_MODE
    120       return ZeroExtend32(s_SIO_MODE.bits);
    121 
    122     case 0x0A: // SIO_CTRL
    123       return ZeroExtend32(s_SIO_CTRL.bits);
    124 
    125     case 0x0E: // SIO_BAUD
    126       return ZeroExtend32(s_SIO_BAUD);
    127 
    128     [[unlikely]] default:
    129       ERROR_LOG("Unknown register read: 0x{:X}", offset);
    130       return UINT32_C(0xFFFFFFFF);
    131   }
    132 }
    133 
    134 void SIO::WriteRegister(u32 offset, u32 value)
    135 {
    136   switch (offset)
    137   {
    138     case 0x00: // SIO_DATA
    139     {
    140       WARNING_LOG("SIO_DATA (W) <- 0x{:02X}", value);
    141       return;
    142     }
    143 
    144     case 0x0A: // SIO_CTRL
    145     {
    146       DEBUG_LOG("SIO_CTRL <- 0x{:04X}", value);
    147 
    148       s_SIO_CTRL.bits = Truncate16(value);
    149       if (s_SIO_CTRL.RESET)
    150         SoftReset();
    151 
    152       return;
    153     }
    154 
    155     case 0x08: // SIO_MODE
    156     {
    157       DEBUG_LOG("SIO_MODE <- 0x{:08X}", value);
    158       s_SIO_MODE.bits = Truncate16(value);
    159       return;
    160     }
    161 
    162     case 0x0E:
    163     {
    164       DEBUG_LOG("SIO_BAUD <- 0x{:08X}", value);
    165       s_SIO_BAUD = Truncate16(value);
    166       return;
    167     }
    168 
    169     default:
    170       ERROR_LOG("Unknown register write: 0x{:X} <- 0x{:08X}", offset, value);
    171       return;
    172   }
    173 }
    174 
    175 void SIO::SoftReset()
    176 {
    177   s_SIO_CTRL.bits = 0;
    178   s_SIO_STAT.bits = 0;
    179   s_SIO_STAT.DSRINPUTLEVEL = true;
    180   s_SIO_STAT.CTSINPUTLEVEL = true;
    181   s_SIO_STAT.TXDONE = true;
    182   s_SIO_STAT.TXRDY = true;
    183   s_SIO_MODE.bits = 0;
    184   s_SIO_BAUD = 0xDC;
    185 }