mirror of
https://github.com/akuker/RASCSI.git
synced 2024-11-22 01:31:25 +00:00
227 lines
8.1 KiB
C++
227 lines
8.1 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// SCSI Target Emulator RaSCSI Reloaded
|
|
// for Raspberry Pi
|
|
//
|
|
// Copyright (C) 2022 akuker
|
|
//
|
|
// [ Hardware version detection routines ]
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "sbc_version.h"
|
|
#include "shared/log.h"
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
SBC_Version::sbc_version_type SBC_Version::m_sbc_version = sbc_version_type::sbc_unknown;
|
|
|
|
// TODO: THESE NEED TO BE VALIDATED!!!!
|
|
const std::string SBC_Version::m_str_raspberry_pi_1 = "Raspberry Pi 1";
|
|
const std::string SBC_Version::m_str_raspberry_pi_2_3 = "Raspberry Pi 2/3";
|
|
const std::string SBC_Version::m_str_raspberry_pi_4 = "Raspberry Pi 4";
|
|
const std::string SBC_Version::m_str_bananapi_m1_plus = "Banana Pi M1 Plus";
|
|
const std::string SBC_Version::m_str_bananapi_m2_berry = "Banana Pi M2 Berry/Ultra";
|
|
const std::string SBC_Version::m_str_bananapi_m2_zero = "Banana Pi M2 Zero";
|
|
const std::string SBC_Version::m_str_bananapi_m2_plus = "Banana Pi BPI-M2-Plus H3";
|
|
const std::string SBC_Version::m_str_bananapi_m3 = "Banana Pi M3";
|
|
const std::string SBC_Version::m_str_bananapi_m4 = "Banana Pi M4";
|
|
const std::string SBC_Version::m_str_bananapi_m5 = "Banana Pi M5";
|
|
const std::string SBC_Version::m_str_bananapi_m64 = "Banana Pi M64";
|
|
const std::string SBC_Version::m_str_unknown_sbc = "Unknown SBC";
|
|
|
|
// The strings in this table should align with the 'model' embedded
|
|
// in the device tree. This can be aquired by running:
|
|
// cat /proc/device-tree/model
|
|
// Only the first part of the string is checked. Anything following
|
|
// will be ignored. For example:
|
|
// "Raspberry Pi 4 Model B" will match with both of the following:
|
|
// - Raspberry Pi 4 Model B Rev 1.4
|
|
// - Raspberry Pi 4 Model B Rev 1.3
|
|
const std::map<std::string, SBC_Version::sbc_version_type, std::less<>> SBC_Version::m_proc_device_tree_mapping = {
|
|
{"Raspberry Pi 1 Model ", sbc_version_type::sbc_raspberry_pi_1},
|
|
{"Raspberry Pi 2 Model ", sbc_version_type::sbc_raspberry_pi_2_3},
|
|
{"Raspberry Pi 3 Model ", sbc_version_type::sbc_raspberry_pi_2_3},
|
|
{"Raspberry Pi 4 Model ", sbc_version_type::sbc_raspberry_pi_4},
|
|
{"Raspberry Pi 400 ", sbc_version_type::sbc_raspberry_pi_4},
|
|
{"Raspberry Pi Zero W", sbc_version_type::sbc_raspberry_pi_1},
|
|
{"Raspberry Pi Zero", sbc_version_type::sbc_raspberry_pi_1},
|
|
{"Banana Pi BPI-M2-Zero ", sbc_version_type::sbc_bananapi_m2_zero},
|
|
{"Banana Pi BPI-M2-Ultra ", sbc_version_type::sbc_bananapi_m2_berry},
|
|
{"Banana Pi BPI-M2-Plus H3", sbc_version_type::sbc_bananapi_m2_plus},
|
|
{"Banana Pi M2 Berry ", sbc_version_type::sbc_bananapi_m2_berry},
|
|
// sbc_bananapi_m3, TBD....
|
|
// sbc_bananapi_m4,
|
|
};
|
|
|
|
const std::string SBC_Version::m_device_tree_model_path = "/proc/device-tree/model";
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Convert the SBC Version to a printable string
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
const std::string *SBC_Version::GetString()
|
|
{
|
|
switch (m_sbc_version) {
|
|
case sbc_version_type::sbc_raspberry_pi_1:
|
|
return &m_str_raspberry_pi_1;
|
|
case sbc_version_type::sbc_raspberry_pi_2_3:
|
|
return &m_str_raspberry_pi_2_3;
|
|
case sbc_version_type::sbc_raspberry_pi_4:
|
|
return &m_str_raspberry_pi_4;
|
|
case sbc_version_type::sbc_bananapi_m2_berry:
|
|
return &m_str_bananapi_m2_berry;
|
|
case sbc_version_type::sbc_bananapi_m2_zero:
|
|
return &m_str_bananapi_m2_zero;
|
|
case sbc_version_type::sbc_bananapi_m2_plus:
|
|
return &m_str_bananapi_m2_plus;
|
|
case sbc_version_type::sbc_bananapi_m3:
|
|
return &m_str_bananapi_m3;
|
|
case sbc_version_type::sbc_bananapi_m4:
|
|
return &m_str_bananapi_m4;
|
|
default:
|
|
LOGERROR("Unknown type of sbc detected: %d", static_cast<int>(m_sbc_version))
|
|
return &m_str_unknown_sbc;
|
|
}
|
|
}
|
|
|
|
SBC_Version::sbc_version_type SBC_Version::GetSbcVersion()
|
|
{
|
|
return m_sbc_version;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Determine which version of single board computer (Pi) is being used
|
|
// based upon the device tree model string.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
void SBC_Version::Init()
|
|
{
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
|
std::string device_tree_model;
|
|
|
|
const std::ifstream input_stream(SBC_Version::m_device_tree_model_path);
|
|
|
|
if (input_stream.fail()) {
|
|
#if defined(__x86_64__) || defined(__X86__)
|
|
// We expect this to fail on x86
|
|
LOGINFO("Detected device %s", GetString()->c_str())
|
|
m_sbc_version = sbc_version_type::sbc_unknown;
|
|
return;
|
|
#else
|
|
LOGERROR("Failed to open %s. Are you running as root?", SBC_Version::m_device_tree_model_path.c_str())
|
|
throw std::invalid_argument("Failed to open /proc/device-tree/model");
|
|
#endif
|
|
}
|
|
|
|
std::stringstream str_buffer;
|
|
str_buffer << input_stream.rdbuf();
|
|
device_tree_model = str_buffer.str();
|
|
|
|
for (const auto &[key, value] : m_proc_device_tree_mapping) {
|
|
if (device_tree_model.rfind(key, 0) == 0) {
|
|
m_sbc_version = value;
|
|
LOGINFO("Detected device %s", GetString()->c_str())
|
|
return;
|
|
}
|
|
}
|
|
LOGERROR("%s Unable to determine single board computer type. Defaulting to Raspberry Pi 4", __PRETTY_FUNCTION__)
|
|
m_sbc_version = sbc_version_type::sbc_raspberry_pi_4;
|
|
}
|
|
|
|
bool SBC_Version::IsRaspberryPi()
|
|
{
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
|
switch (m_sbc_version) {
|
|
case sbc_version_type::sbc_raspberry_pi_1:
|
|
case sbc_version_type::sbc_raspberry_pi_2_3:
|
|
case sbc_version_type::sbc_raspberry_pi_4:
|
|
return true;
|
|
case sbc_version_type::sbc_bananapi_m2_berry:
|
|
case sbc_version_type::sbc_bananapi_m2_zero:
|
|
case sbc_version_type::sbc_bananapi_m2_plus:
|
|
case sbc_version_type::sbc_bananapi_m3:
|
|
case sbc_version_type::sbc_bananapi_m4:
|
|
return false;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool SBC_Version::IsBananaPi()
|
|
{
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
|
switch (m_sbc_version) {
|
|
case sbc_version_type::sbc_raspberry_pi_1:
|
|
case sbc_version_type::sbc_raspberry_pi_2_3:
|
|
case sbc_version_type::sbc_raspberry_pi_4:
|
|
return false;
|
|
case sbc_version_type::sbc_bananapi_m2_berry:
|
|
case sbc_version_type::sbc_bananapi_m2_zero:
|
|
case sbc_version_type::sbc_bananapi_m2_plus:
|
|
case sbc_version_type::sbc_bananapi_m3:
|
|
case sbc_version_type::sbc_bananapi_m4:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// The following functions are only used on the Raspberry Pi
|
|
// (imported from bcm_host.c)
|
|
uint32_t SBC_Version::GetDeviceTreeRanges(const char *filename, uint32_t offset)
|
|
{
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
|
uint32_t address = ~0;
|
|
if (FILE *fp = fopen(filename, "rb"); fp) {
|
|
fseek(fp, offset, SEEK_SET);
|
|
if (std::array<uint8_t, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
|
|
address = (int)buf[0] << 24 | (int)buf[1] << 16 | (int)buf[2] << 8 | (int)buf[3] << 0;
|
|
}
|
|
fclose(fp);
|
|
}
|
|
return address;
|
|
}
|
|
|
|
#if defined __linux__
|
|
uint32_t SBC_Version::GetPeripheralAddress(void)
|
|
{
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
|
uint32_t address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 4);
|
|
if (address == 0) {
|
|
address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 8);
|
|
}
|
|
address = (address == (uint32_t)~0) ? 0x20000000 : address;
|
|
|
|
LOGDEBUG("Peripheral address : 0x%8x\n", address)
|
|
|
|
return address;
|
|
}
|
|
#elif defined __NetBSD__
|
|
uint32_t SBC_Version::GetPeripheralAddress(void)
|
|
{
|
|
char buf[1024];
|
|
size_t len = sizeof(buf);
|
|
uint32_t address;
|
|
|
|
if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) {
|
|
// Failed to get CPU model || Not BCM2835
|
|
// use the address of BCM283[67]
|
|
address = 0x3f000000;
|
|
} else {
|
|
// Use BCM2835 address
|
|
address = 0x20000000;
|
|
}
|
|
LOGDEBUG("Peripheral address : 0x%lx\n", address);
|
|
return address;
|
|
}
|
|
#else
|
|
uint32_t SBC_Version::GetPeripheralAddress(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|