From aca9d2780886911a42e261e5cf0edd4c6e91634a Mon Sep 17 00:00:00 2001 From: Shady Nawara Date: Thu, 6 Feb 2025 17:20:30 +0000 Subject: [PATCH] macOS smbus Piix4, SuperIO, and Nct6775 --- OpenRGB.pro | 4 + i2c_smbus/i2c_smbus_nct6775.cpp | 20 +++++ i2c_smbus/i2c_smbus_nct6775.h | 6 ++ i2c_smbus/i2c_smbus_piix4.cpp | 75 ++++++++++++++++++- i2c_smbus/i2c_smbus_piix4.h | 8 ++ .../OpenRGBSettingsPage.cpp | 15 ++-- super_io/super_io.cpp | 11 +-- 7 files changed, 127 insertions(+), 12 deletions(-) diff --git a/OpenRGB.pro b/OpenRGB.pro index d3b13ee8..4ac6ab33 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -847,11 +847,15 @@ macx:contains(QMAKE_HOST.arch, x86_64) { SOURCES += \ i2c_smbus/i2c_smbus_i801.cpp \ + i2c_smbus/i2c_smbus_nct6775.cpp \ + i2c_smbus/i2c_smbus_piix4.cpp \ scsiapi/scsiapi_macos.c \ HEADERS += \ dependencies/macUSPCIO/macUSPCIOAccess.h \ i2c_smbus/i2c_smbus_i801.h \ + i2c_smbus/i2c_smbus_nct6775.h \ + i2c_smbus/i2c_smbus_piix4.h \ LIBS += \ -L/usr/local/lib \ diff --git a/i2c_smbus/i2c_smbus_nct6775.cpp b/i2c_smbus/i2c_smbus_nct6775.cpp index 6a5d31fa..d18674e6 100644 --- a/i2c_smbus/i2c_smbus_nct6775.cpp +++ b/i2c_smbus/i2c_smbus_nct6775.cpp @@ -12,7 +12,11 @@ #include "Detector.h" #include "i2c_smbus_nct6775.h" #include "LogManager.h" +#ifdef _WIN32 #include "OlsApi.h" +#elif _MACOSX_X86_X64 +#include "macUSPCIOAccess.h" +#endif #include "ResourceManager.h" #include "SettingsManager.h" #include "super_io.h" @@ -21,6 +25,7 @@ using namespace std::chrono_literals; i2c_smbus_nct6775::i2c_smbus_nct6775() { +#ifdef _WIN32 json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers"); bool shared_smbus_access = true; @@ -32,14 +37,17 @@ i2c_smbus_nct6775::i2c_smbus_nct6775() { global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME); } +#endif } i2c_smbus_nct6775::~i2c_smbus_nct6775() { +#ifdef _WIN32 if(global_smbus_access_handle != NULL) { CloseHandle(global_smbus_access_handle); } +#endif } s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data) @@ -215,17 +223,21 @@ s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) { +#ifdef _WIN32 if(global_smbus_access_handle != NULL) { WaitForSingleObject(global_smbus_access_handle, INFINITE); } +#endif s32 result = nct6775_access(addr, read_write, command, size, data); +#ifdef _WIN32 if(global_smbus_access_handle != NULL) { ReleaseMutex(global_smbus_access_handle); } +#endif return result; } @@ -237,11 +249,19 @@ s32 i2c_smbus_nct6775::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, bool i2c_smbus_nct6775_detect() { +#ifdef _WIN32 if(!InitializeOls() || GetDllStatus()) { LOG_INFO("WinRing0 is not loaded, nct6775 I2C bus detection aborted"); return(false); } +#elif _MACOSX_X86_X64 + if(!GetMacUSPCIODriverStatus()) + { + LOG_INFO("macUSPCIO is not loaded, nct6775 I2C bus detection aborted"); + return(false); + } +#endif i2c_smbus_interface* bus; int sioaddr = 0x2E; diff --git a/i2c_smbus/i2c_smbus_nct6775.h b/i2c_smbus/i2c_smbus_nct6775.h index 9a9b15f8..651c413c 100644 --- a/i2c_smbus/i2c_smbus_nct6775.h +++ b/i2c_smbus/i2c_smbus_nct6775.h @@ -12,7 +12,9 @@ #pragma once #include "i2c_smbus.h" +#ifdef _WIN32 #include +#endif #define SMBHSTDAT (0 + nct6775_smba) #define SMBBLKSZ (1 + nct6775_smba) @@ -48,7 +50,9 @@ /* Other settings */ #define NCT6775_MAX_RETRIES 400 +#ifdef _WIN32 #define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method" +#endif class i2c_smbus_nct6775: public i2c_smbus_interface { @@ -62,5 +66,7 @@ private: s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); +#ifdef _WIN32 HANDLE global_smbus_access_handle = NULL; +#endif }; diff --git a/i2c_smbus/i2c_smbus_piix4.cpp b/i2c_smbus/i2c_smbus_piix4.cpp index 85cfbb68..4980c6dc 100644 --- a/i2c_smbus/i2c_smbus_piix4.cpp +++ b/i2c_smbus/i2c_smbus_piix4.cpp @@ -13,10 +13,16 @@ #include "Detector.h" #include "i2c_smbus_piix4.h" #include "LogManager.h" +#ifdef _WIN32 #include "OlsApi.h" +#include "wmi.h" +#elif _MACOSX_X86_X64 +#include +#include "macUSPCIOAccess.h" +#include "pci_ids.h" +#endif #include "ResourceManager.h" #include "SettingsManager.h" -#include "wmi.h" i2c_smbus_piix4::i2c_smbus_piix4() { @@ -27,6 +33,7 @@ i2c_smbus_piix4::i2c_smbus_piix4() { amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get(); } +#ifdef _WIN32 if(amd_smbus_reduce_cpu) { delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); @@ -45,10 +52,14 @@ i2c_smbus_piix4::i2c_smbus_piix4() { global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME); } +#else + delay_timer = amd_smbus_reduce_cpu; +#endif } i2c_smbus_piix4::~i2c_smbus_piix4() { +#ifdef _WIN32 if(delay_timer != NULL) { CloseHandle(delay_timer); @@ -58,6 +69,7 @@ i2c_smbus_piix4::~i2c_smbus_piix4() { CloseHandle(global_smbus_access_handle); } +#endif } //Logic adapted from piix4_transaction() in i2c-piix4.c @@ -88,6 +100,7 @@ int i2c_smbus_piix4::piix4_transaction() /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ temp = 0; +#ifdef _WIN32 if(delay_timer != NULL) { LARGE_INTEGER retry_delay; @@ -104,6 +117,16 @@ int i2c_smbus_piix4::piix4_transaction() WaitForSingleObject(delay_timer, INFINITE); } } +#else + if(delay_timer) + { + while ((++timeout < MAX_TIMEOUT) && temp <= 1) + { + temp = ReadIoPortByte(SMBHSTSTS); + usleep(250); + } + } +#endif else { while ((++timeout < MAX_TIMEOUT) && temp <= 1) @@ -111,6 +134,7 @@ int i2c_smbus_piix4::piix4_transaction() temp = ReadIoPortByte(SMBHSTSTS); } } + /* If the SMBus is still busy, we give up */ if (timeout == MAX_TIMEOUT) { @@ -240,17 +264,21 @@ s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int siz s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) { +#ifdef _WIN32 if(global_smbus_access_handle != NULL) { WaitForSingleObject(global_smbus_access_handle, INFINITE); } +#endif s32 result = piix4_access(addr, read_write, command, size, data); +#ifdef _WIN32 if(global_smbus_access_handle != NULL) { ReleaseMutex(global_smbus_access_handle); } +#endif return result; } @@ -259,7 +287,7 @@ s32 i2c_smbus_piix4::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u { return -1; } - +#ifdef _WIN32 bool i2c_smbus_piix4_detect() { if(!InitializeOls() || GetDllStatus()) @@ -331,5 +359,48 @@ bool i2c_smbus_piix4_detect() return(true); } +#elif _MACOSX_X86_X64 +bool i2c_smbus_piix4_detect() +{ + if(!GetMacUSPCIODriverStatus()) + { + LOG_INFO("macUSPCIO is not loaded, piix4 I2C bus detection aborted"); + return(false); + } + + // addresses are referenced from: https://opensource.apple.com/source/IOPCIFamily/IOPCIFamily-146/IOKit/pci/IOPCIDevice.h.auto.html + uint16_t vendor_id = ReadConfigPortWord(0x00); + uint16_t device_id = ReadConfigPortWord(0x02); + uint16_t subsystem_vendor_id = ReadConfigPortWord(0x2c); + uint16_t subsystem_device_id = ReadConfigPortWord(0x2e); + + if(vendor_id != AMD_VEN || !device_id || !subsystem_vendor_id || !subsystem_device_id) + { + return(false); + } + + i2c_smbus_interface * bus; + + bus = new i2c_smbus_piix4(); + bus->pci_vendor = vendor_id; + bus->pci_device = device_id; + bus->pci_subsystem_vendor = subsystem_vendor_id; + bus->pci_subsystem_device = subsystem_device_id; + strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B00"); + ((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00; + ResourceManager::get()->RegisterI2CBus(bus); + + bus = new i2c_smbus_piix4(); + bus->pci_vendor = vendor_id; + bus->pci_device = device_id; + bus->pci_subsystem_vendor = subsystem_vendor_id; + bus->pci_subsystem_device = subsystem_device_id; + ((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20; + strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B20"); + ResourceManager::get()->RegisterI2CBus(bus); + + return(true); +} +#endif REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect); diff --git a/i2c_smbus/i2c_smbus_piix4.h b/i2c_smbus/i2c_smbus_piix4.h index 18e9f7b4..985cbad4 100644 --- a/i2c_smbus/i2c_smbus_piix4.h +++ b/i2c_smbus/i2c_smbus_piix4.h @@ -13,7 +13,9 @@ #pragma once #include "i2c_smbus.h" +#ifdef _WIN32 #include "windows.h" +#endif // PIIX4 SMBus address offsets #define SMBHSTSTS (0 + piix4_smba) @@ -38,7 +40,9 @@ #define PIIX4_WORD_DATA 0x0C #define PIIX4_BLOCK_DATA 0x14 +#ifdef _WIN32 #define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method" +#endif class i2c_smbus_piix4 : public i2c_smbus_interface { @@ -52,6 +56,10 @@ private: s32 piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); +#ifdef _WIN32 HANDLE delay_timer = NULL; HANDLE global_smbus_access_handle = NULL; +#else + bool delay_timer; +#endif }; diff --git a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp index 305c7e55..f3bfa454 100644 --- a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp +++ b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp @@ -205,16 +205,23 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) : } /*---------------------------------------------------------*\ - | Load drivers settings (Windows only) | + | Load drivers settings (Windows only or Mac) | \*---------------------------------------------------------*/ -#ifdef _WIN32 +#if defined(WIN32) || defined(_MACOSX_X86_X64) json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers"); if(drivers_settings.contains("amd_smbus_reduce_cpu")) { ui->CheckboxAMDSMBusReduceCPU->setChecked(drivers_settings["amd_smbus_reduce_cpu"]); } - +#else + ui->DriversSettingsLabel->hide(); + ui->CheckboxAMDSMBusReduceCPU->hide(); +#endif + /*---------------------------------------------------------*\ + | Load drivers settings (Windows only) | + \*---------------------------------------------------------*/ +#ifdef _WIN32 if(drivers_settings.contains("shared_smbus_access")) { ui->CheckboxSharedSMBusAccess->setChecked(drivers_settings["shared_smbus_access"]); @@ -224,8 +231,6 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) : ui->CheckboxSharedSMBusAccess->setChecked(true); } #else - ui->DriversSettingsLabel->hide(); - ui->CheckboxAMDSMBusReduceCPU->hide(); ui->CheckboxSharedSMBusAccess->hide(); #endif diff --git a/super_io/super_io.cpp b/super_io/super_io.cpp index 97bed221..b97f389f 100644 --- a/super_io/super_io.cpp +++ b/super_io/super_io.cpp @@ -11,10 +11,11 @@ #include "super_io.h" -#ifdef WIN32 +#ifdef _WIN32 #include #include "OlsApi.h" - +#elif _MACOSX_X86_X64 +#include "macUSPCIOAccess.h" #else #include #include @@ -33,7 +34,7 @@ int dev_port_fd; void superio_enter(int ioreg) { -#ifdef WIN32 +#if defined(WIN32) || defined(_MACOSX_X86_X64) WriteIoPortByte(ioreg, 0x87); WriteIoPortByte(ioreg, 0x87); #else @@ -70,7 +71,7 @@ void superio_enter(int ioreg) void superio_outb(int ioreg, int reg, int val) { -#ifdef WIN32 +#if defined(WIN32) || defined(_MACOSX_X86_X64) WriteIoPortByte(ioreg, reg); WriteIoPortByte(ioreg + 1, val); #else @@ -105,7 +106,7 @@ void superio_outb(int ioreg, int reg, int val) int superio_inb(int ioreg, int reg) { -#ifdef WIN32 +#if defined(WIN32) || defined(_MACOSX_X86_X64) WriteIoPortByte(ioreg, reg); return ReadIoPortByte(ioreg + 1); #else