macOS smbus Piix4, SuperIO, and Nct6775

This commit is contained in:
Shady Nawara 2025-02-06 17:20:30 +00:00 committed by Adam Honse
parent 3eb14e411d
commit aca9d27808
7 changed files with 127 additions and 12 deletions

View file

@ -847,11 +847,15 @@ macx:contains(QMAKE_HOST.arch, x86_64) {
SOURCES += \ SOURCES += \
i2c_smbus/i2c_smbus_i801.cpp \ i2c_smbus/i2c_smbus_i801.cpp \
i2c_smbus/i2c_smbus_nct6775.cpp \
i2c_smbus/i2c_smbus_piix4.cpp \
scsiapi/scsiapi_macos.c \ scsiapi/scsiapi_macos.c \
HEADERS += \ HEADERS += \
dependencies/macUSPCIO/macUSPCIOAccess.h \ dependencies/macUSPCIO/macUSPCIOAccess.h \
i2c_smbus/i2c_smbus_i801.h \ i2c_smbus/i2c_smbus_i801.h \
i2c_smbus/i2c_smbus_nct6775.h \
i2c_smbus/i2c_smbus_piix4.h \
LIBS += \ LIBS += \
-L/usr/local/lib \ -L/usr/local/lib \

View file

@ -12,7 +12,11 @@
#include "Detector.h" #include "Detector.h"
#include "i2c_smbus_nct6775.h" #include "i2c_smbus_nct6775.h"
#include "LogManager.h" #include "LogManager.h"
#ifdef _WIN32
#include "OlsApi.h" #include "OlsApi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#endif
#include "ResourceManager.h" #include "ResourceManager.h"
#include "SettingsManager.h" #include "SettingsManager.h"
#include "super_io.h" #include "super_io.h"
@ -21,6 +25,7 @@ using namespace std::chrono_literals;
i2c_smbus_nct6775::i2c_smbus_nct6775() i2c_smbus_nct6775::i2c_smbus_nct6775()
{ {
#ifdef _WIN32
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers"); json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool shared_smbus_access = true; 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); global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
} }
#endif
} }
i2c_smbus_nct6775::~i2c_smbus_nct6775() i2c_smbus_nct6775::~i2c_smbus_nct6775()
{ {
#ifdef _WIN32
if(global_smbus_access_handle != NULL) if(global_smbus_access_handle != NULL)
{ {
CloseHandle(global_smbus_access_handle); 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) 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) 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) if(global_smbus_access_handle != NULL)
{ {
WaitForSingleObject(global_smbus_access_handle, INFINITE); WaitForSingleObject(global_smbus_access_handle, INFINITE);
} }
#endif
s32 result = nct6775_access(addr, read_write, command, size, data); s32 result = nct6775_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL) if(global_smbus_access_handle != NULL)
{ {
ReleaseMutex(global_smbus_access_handle); ReleaseMutex(global_smbus_access_handle);
} }
#endif
return result; return result;
} }
@ -237,11 +249,19 @@ s32 i2c_smbus_nct6775::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/,
bool i2c_smbus_nct6775_detect() bool i2c_smbus_nct6775_detect()
{ {
#ifdef _WIN32
if(!InitializeOls() || GetDllStatus()) if(!InitializeOls() || GetDllStatus())
{ {
LOG_INFO("WinRing0 is not loaded, nct6775 I2C bus detection aborted"); LOG_INFO("WinRing0 is not loaded, nct6775 I2C bus detection aborted");
return(false); 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; i2c_smbus_interface* bus;
int sioaddr = 0x2E; int sioaddr = 0x2E;

View file

@ -12,7 +12,9 @@
#pragma once #pragma once
#include "i2c_smbus.h" #include "i2c_smbus.h"
#ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#endif
#define SMBHSTDAT (0 + nct6775_smba) #define SMBHSTDAT (0 + nct6775_smba)
#define SMBBLKSZ (1 + nct6775_smba) #define SMBBLKSZ (1 + nct6775_smba)
@ -48,7 +50,9 @@
/* Other settings */ /* Other settings */
#define NCT6775_MAX_RETRIES 400 #define NCT6775_MAX_RETRIES 400
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method" #define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_nct6775: public i2c_smbus_interface 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_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); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
#ifdef _WIN32
HANDLE global_smbus_access_handle = NULL; HANDLE global_smbus_access_handle = NULL;
#endif
}; };

View file

@ -13,10 +13,16 @@
#include "Detector.h" #include "Detector.h"
#include "i2c_smbus_piix4.h" #include "i2c_smbus_piix4.h"
#include "LogManager.h" #include "LogManager.h"
#ifdef _WIN32
#include "OlsApi.h" #include "OlsApi.h"
#include "wmi.h"
#elif _MACOSX_X86_X64
#include <unistd.h>
#include "macUSPCIOAccess.h"
#include "pci_ids.h"
#endif
#include "ResourceManager.h" #include "ResourceManager.h"
#include "SettingsManager.h" #include "SettingsManager.h"
#include "wmi.h"
i2c_smbus_piix4::i2c_smbus_piix4() 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<bool>(); amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
} }
#ifdef _WIN32
if(amd_smbus_reduce_cpu) if(amd_smbus_reduce_cpu)
{ {
delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); 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); 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() i2c_smbus_piix4::~i2c_smbus_piix4()
{ {
#ifdef _WIN32
if(delay_timer != NULL) if(delay_timer != NULL)
{ {
CloseHandle(delay_timer); CloseHandle(delay_timer);
@ -58,6 +69,7 @@ i2c_smbus_piix4::~i2c_smbus_piix4()
{ {
CloseHandle(global_smbus_access_handle); CloseHandle(global_smbus_access_handle);
} }
#endif
} }
//Logic adapted from piix4_transaction() in i2c-piix4.c //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) */ /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
temp = 0; temp = 0;
#ifdef _WIN32
if(delay_timer != NULL) if(delay_timer != NULL)
{ {
LARGE_INTEGER retry_delay; LARGE_INTEGER retry_delay;
@ -104,6 +117,16 @@ int i2c_smbus_piix4::piix4_transaction()
WaitForSingleObject(delay_timer, INFINITE); WaitForSingleObject(delay_timer, INFINITE);
} }
} }
#else
if(delay_timer)
{
while ((++timeout < MAX_TIMEOUT) && temp <= 1)
{
temp = ReadIoPortByte(SMBHSTSTS);
usleep(250);
}
}
#endif
else else
{ {
while ((++timeout < MAX_TIMEOUT) && temp <= 1) while ((++timeout < MAX_TIMEOUT) && temp <= 1)
@ -111,6 +134,7 @@ int i2c_smbus_piix4::piix4_transaction()
temp = ReadIoPortByte(SMBHSTSTS); temp = ReadIoPortByte(SMBHSTSTS);
} }
} }
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT) 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) 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) if(global_smbus_access_handle != NULL)
{ {
WaitForSingleObject(global_smbus_access_handle, INFINITE); WaitForSingleObject(global_smbus_access_handle, INFINITE);
} }
#endif
s32 result = piix4_access(addr, read_write, command, size, data); s32 result = piix4_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL) if(global_smbus_access_handle != NULL)
{ {
ReleaseMutex(global_smbus_access_handle); ReleaseMutex(global_smbus_access_handle);
} }
#endif
return result; return result;
} }
@ -259,7 +287,7 @@ s32 i2c_smbus_piix4::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u
{ {
return -1; return -1;
} }
#ifdef _WIN32
bool i2c_smbus_piix4_detect() bool i2c_smbus_piix4_detect()
{ {
if(!InitializeOls() || GetDllStatus()) if(!InitializeOls() || GetDllStatus())
@ -331,5 +359,48 @@ bool i2c_smbus_piix4_detect()
return(true); 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); REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect);

View file

@ -13,7 +13,9 @@
#pragma once #pragma once
#include "i2c_smbus.h" #include "i2c_smbus.h"
#ifdef _WIN32
#include "windows.h" #include "windows.h"
#endif
// PIIX4 SMBus address offsets // PIIX4 SMBus address offsets
#define SMBHSTSTS (0 + piix4_smba) #define SMBHSTSTS (0 + piix4_smba)
@ -38,7 +40,9 @@
#define PIIX4_WORD_DATA 0x0C #define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14 #define PIIX4_BLOCK_DATA 0x14
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method" #define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_piix4 : public i2c_smbus_interface 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 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_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); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
#ifdef _WIN32
HANDLE delay_timer = NULL; HANDLE delay_timer = NULL;
HANDLE global_smbus_access_handle = NULL; HANDLE global_smbus_access_handle = NULL;
#else
bool delay_timer;
#endif
}; };

View file

@ -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"); json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
if(drivers_settings.contains("amd_smbus_reduce_cpu")) if(drivers_settings.contains("amd_smbus_reduce_cpu"))
{ {
ui->CheckboxAMDSMBusReduceCPU->setChecked(drivers_settings["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")) if(drivers_settings.contains("shared_smbus_access"))
{ {
ui->CheckboxSharedSMBusAccess->setChecked(drivers_settings["shared_smbus_access"]); ui->CheckboxSharedSMBusAccess->setChecked(drivers_settings["shared_smbus_access"]);
@ -224,8 +231,6 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) :
ui->CheckboxSharedSMBusAccess->setChecked(true); ui->CheckboxSharedSMBusAccess->setChecked(true);
} }
#else #else
ui->DriversSettingsLabel->hide();
ui->CheckboxAMDSMBusReduceCPU->hide();
ui->CheckboxSharedSMBusAccess->hide(); ui->CheckboxSharedSMBusAccess->hide();
#endif #endif

View file

@ -11,10 +11,11 @@
#include "super_io.h" #include "super_io.h"
#ifdef WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#include "OlsApi.h" #include "OlsApi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
@ -33,7 +34,7 @@ int dev_port_fd;
void superio_enter(int ioreg) void superio_enter(int ioreg)
{ {
#ifdef WIN32 #if defined(WIN32) || defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, 0x87); WriteIoPortByte(ioreg, 0x87);
WriteIoPortByte(ioreg, 0x87); WriteIoPortByte(ioreg, 0x87);
#else #else
@ -70,7 +71,7 @@ void superio_enter(int ioreg)
void superio_outb(int ioreg, int reg, int val) void superio_outb(int ioreg, int reg, int val)
{ {
#ifdef WIN32 #if defined(WIN32) || defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, reg); WriteIoPortByte(ioreg, reg);
WriteIoPortByte(ioreg + 1, val); WriteIoPortByte(ioreg + 1, val);
#else #else
@ -105,7 +106,7 @@ void superio_outb(int ioreg, int reg, int val)
int superio_inb(int ioreg, int reg) int superio_inb(int ioreg, int reg)
{ {
#ifdef WIN32 #if defined(WIN32) || defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, reg); WriteIoPortByte(ioreg, reg);
return ReadIoPortByte(ioreg + 1); return ReadIoPortByte(ioreg + 1);
#else #else