Skip to content

Commit

Permalink
Added smc device
Browse files Browse the repository at this point in the history
  • Loading branch information
ergo720 committed Aug 21, 2024
1 parent 0b6f7b5 commit cf2ae5c
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ set(HEADERS
"${NXBX_ROOT_DIR}/src/hw/pic.hpp"
"${NXBX_ROOT_DIR}/src/hw/pit.hpp"
"${NXBX_ROOT_DIR}/src/hw/smbus.hpp"
"${NXBX_ROOT_DIR}/src/hw/smc.hpp"
"${NXBX_ROOT_DIR}/src/hw/video/vga.hpp"
"${NXBX_ROOT_DIR}/src/hw/video/gpu/nv2a.hpp"
"${NXBX_ROOT_DIR}/src/hw/video/gpu/nv2a_defs.hpp"
Expand Down Expand Up @@ -102,6 +103,7 @@ set(SOURCES
"${NXBX_ROOT_DIR}/src/hw/pic.cpp"
"${NXBX_ROOT_DIR}/src/hw/pit.cpp"
"${NXBX_ROOT_DIR}/src/hw/smbus.cpp"
"${NXBX_ROOT_DIR}/src/hw/smc.cpp"
"${NXBX_ROOT_DIR}/src/hw/video/vga.cpp"
"${NXBX_ROOT_DIR}/src/hw/video/gpu/nv2a.cpp"
"${NXBX_ROOT_DIR}/src/hw/video/gpu/pbus.cpp"
Expand Down
4 changes: 4 additions & 0 deletions src/console.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class console {
m_machine.apply_log_settings();
}
}
void update_tray_state(tray_state state, bool do_int)
{
m_machine.get<smc>().update_tray_state(state, do_int);
}

private:
console() : m_is_init(false) {}
Expand Down
2 changes: 2 additions & 0 deletions src/hw/eeprom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// SPDX-FileCopyrightText: 2023 ergo720

#pragma once

#include "smbus.hpp"
#include <fstream>
#include <filesystem>
Expand Down
10 changes: 9 additions & 1 deletion src/hw/machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "pci.hpp"
#include "smbus.hpp"
#include "eeprom.hpp"
#include "smc.hpp"
#include "video/vga.hpp"
#include "video/gpu/nv2a.hpp"

Expand All @@ -22,7 +23,7 @@ concept is_cpu_t = std::is_same_v<T, cpu_t *>;
class machine {
public:
machine() : m_cpu(this), m_pit(this), m_pic{ {this, 0, "MASTER PIC"}, {this, 1, "SLAVE PIC"} }, m_pci(this), m_cmos(this), m_nv2a(this),
m_vga(this), m_smbus(this), m_eeprom(log_module::eeprom) {}
m_vga(this), m_smbus(this), m_eeprom(log_module::eeprom), m_smc(log_module::smc) {}
bool init(const init_info_t &init_info)
{
if (!m_cpu.init(init_info)) {
Expand Down Expand Up @@ -55,6 +56,9 @@ class machine {
if (!m_eeprom.init(init_info.m_nxbx_path)) {
return false;
}
if (!m_smc.init()) {
return false;
}
return true;
}
void deinit()
Expand Down Expand Up @@ -99,6 +103,9 @@ class machine {
else if constexpr (std::is_same_v<T, eeprom>) {
return m_eeprom;
}
else if constexpr (std::is_same_v<T, smc>) {
return m_smc;
}
else if constexpr (std::is_same_v<T, nv2a>) {
return m_nv2a;
}
Expand Down Expand Up @@ -180,4 +187,5 @@ class machine {
vga m_vga;
smbus m_smbus;
eeprom m_eeprom;
smc m_smc;
};
1 change: 1 addition & 0 deletions src/hw/smbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ smbus::init()
}

m_devs[0x54] = &m_machine->get<eeprom>(); // eeprom
m_devs[0x10] = &m_machine->get<smc>(); // smc
reset();
return true;
}
130 changes: 130 additions & 0 deletions src/hw/smc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: GPL-3.0-or-later

// SPDX-FileCopyrightText: 2024 ergo720

#include "machine.hpp"
#include <cinttypes>

#define MODULE_NAME smc

#define SMC_VERSION_STR 0x01
#define SMC_TRAY_STATE 0x03
#define SMC_VIDEO_MODE 0x04
#define SMC_FAN_MODE 0x05
#define SMC_FAN_SPEED 0x06
#define SMC_LED_OVERRIDE 0x07
#define SMC_LED_STATES 0x08
#define SMC_WRITE_SCRATCH 0x0E
#define SMC_READ_SCRATCH 0x0F
#define SMC_READ_FAN_SPEED 0x10
#define SMC_SCRATCH 0x1B

#define SMC_TRAY_STATE_OPEN 0x10
#define SMC_TRAY_STATE_NO_MEDIA 0x40
#define SMC_TRAY_STATE_MEDIA_DETECT 0x60

#define SMC_VIDEO_MODE_SCART 0x00
#define SMC_VIDEO_MODE_HDTV 0x01
#define SMC_VIDEO_MODE_VGA 0x02
#define SMC_VIDEO_MODE_RFU 0x03
#define SMC_VIDEO_MODE_SVIDEO 0x04
#define SMC_VIDEO_MODE_STANDARD 0x06
#define SMC_VIDEO_MODE_NONE 0x07


std::optional<uint16_t>
smc::read_byte(uint8_t command)
{
uint8_t value;
switch (command)
{
case SMC_VERSION_STR:
value = m_version[m_version_idx];
break;

case SMC_TRAY_STATE:
value = m_tray_state.load();
break;

case SMC_VIDEO_MODE:
case SMC_SCRATCH:
value = m_regs[command];
break;

case SMC_READ_SCRATCH:
value = m_regs[SMC_WRITE_SCRATCH];
break;

case SMC_READ_FAN_SPEED:
value = (m_regs[SMC_FAN_MODE] == 1) ? m_regs[SMC_FAN_SPEED] : 0;
break;

default:
nxbx_fatal("Unhandled read with command 0x%" PRIX8, command);
}

return value;
}

std::optional<uint16_t>
smc::write_byte(uint8_t command, uint8_t data)
{
switch (command)
{
case SMC_VERSION_STR:
m_version_idx = (data == 0) ? 0 : m_version_idx;
break;

case SMC_FAN_MODE:
m_regs[command] = data & 1;
break;

case SMC_FAN_SPEED:
m_regs[command] = (data > 50) ? m_regs[command] : data;
break;

case SMC_LED_OVERRIDE: // TODO: display on the gui somehow
m_regs[command] = data & 1;
if (m_regs[command] == 0) {
m_regs[SMC_LED_STATES] = 0x0F; // solid green
}
break;

case SMC_LED_STATES:
m_regs[command] = data;
break;

default:
nxbx_fatal("Unhandled write with command 0x%" PRIX8 " and value 0x%" PRIX8, command, data);
}

return 0;
}

void
smc::update_tray_state(::tray_state state, bool do_int)
{
m_tray_state = (uint8_t)state;
if (do_int) {
// TODO: trigger interrupt
nxbx_fatal("Interrupts not supported yet");
}
}

void
smc::reset()
{
std::fill(std::begin(m_regs), std::end(m_regs), 0);
m_regs[SMC_LED_STATES] = 0x0F; // solid green
m_version_idx = 0;
}

bool
smc::init()
{
reset();
m_regs[SMC_TRAY_STATE] = SMC_TRAY_STATE_MEDIA_DETECT; // TODO: should change state when the user boots new XBEs/XISOs from the gui
m_regs[SMC_VIDEO_MODE] = SMC_VIDEO_MODE_HDTV; // TODO: make configurable

return true;
}
35 changes: 35 additions & 0 deletions src/hw/smc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-3.0-or-later

// SPDX-FileCopyrightText: 2024 ergo720

#pragma once

#include "smbus.hpp"
#include <atomic>
#include <cstdint>


// NOTE: same state values as used internally by the smc, to avoid conversions
enum class tray_state : uint8_t {
open = 0x10,
no_media = 0x40,
media_detect = 0x60,
};

class smc : public smbus_device {
public:
smc(log_module module_name) : smbus_device(module_name) {}
bool init();
void deinit() override {}
void reset();
std::optional<uint16_t> read_byte(uint8_t command) override;
std::optional<uint16_t> write_byte(uint8_t command, uint8_t data) override;
void update_tray_state(tray_state state, bool do_int);

private:
//machine *const m_machine;
static constexpr uint8_t m_version[3] = { 'P', '0', '5' };
uint8_t m_version_idx;
uint8_t m_regs[34];
std::atomic_uint8_t m_tray_state; // atomic because it can be updated by console::update_tray_state
};
6 changes: 3 additions & 3 deletions src/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#include "io.hpp"
#include "logger.hpp"
#include "cpu.hpp"
#include "eeprom.hpp"
#include "kernel.hpp"
#include "xiso.hpp"
#include "xpartition.hpp"
#include "console.hpp"
#include <thread>
#include <deque>
#include <unordered_map>
Expand Down Expand Up @@ -633,8 +633,7 @@ namespace io {
xbe_path = "\\Device\\CdRom0\\" + xbe_name;
dvd_input_type = input_t::xbe;
if (dvd_path.string().starts_with(hdd_path.string())) {
// XBE is installed inside a HDD partition, so set the dvd drive to be empty by setting th dvd path to an invalid directory
// TODO: this should also set the SMC tray state to have no media
// XBE is installed inside a HDD partition, so set the dvd drive to be empty by setting the dvd path to an invalid directory
size_t partition_num_off = hdd_path.string().size() + 9;
std::string xbox_hdd_dir = "\\Device\\Harddisk0\\Partition" + std::to_string(dvd_path.string()[partition_num_off] - '0');
std::string xbox_remaining_hdd_dir = dvd_path.string().substr(partition_num_off + 1);
Expand All @@ -645,6 +644,7 @@ namespace io {
}
xbe_path = util::traits_cast<util::xbox_char_traits, char, std::char_traits<char>>(xbox_hdd_dir + xbox_remaining_hdd_dir + xbe_name.c_str());
dvd_path = "";
console::get().update_tray_state(tray_state::no_media, false);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ enum class log_module : int32_t {
user,
smbus,
eeprom,
smc,
max,
};

Expand Down Expand Up @@ -82,6 +83,7 @@ inline constexpr std::array module_to_str = {
"NV2A.USER -> ",
"SMBUS -> ",
"EEPROM -> ",
"SMC -> ",
};
static_assert(module_to_str.size() == (uint32_t)(log_module::max));

Expand Down

0 comments on commit cf2ae5c

Please sign in to comment.