Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions source/StartUpProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "settings/CGameCategories.hpp"
#include "settings/GameTitles.h"
#include "usbloader/usbstorage2.h"
#include "usbloader/usbstorage_libogc.h"
#include "usbloader/MountGamePartition.h"
#include "usbloader/GameBooter.hpp"
#include "usbloader/GameList.h"
Expand Down Expand Up @@ -366,6 +367,44 @@ int StartUpProcess::Execute(bool quickGameBoot, bool isBadBoot)
gprintf("\tLoading game categories...%s\n", GameCategories.Load(Settings.ConfigPath) ? "done" : "failed");
gprintf("\tLoading cached titles...%s\n", GameTitles.ReadCachedTitles(Settings.titlestxt_path) ? "done" : "failed (using default)");

// Apply volatile ATA power settings while the IOS58/libogc USB backend is
// still mounted. The later cIOS backend does not expose raw SCSI commands.
if (Settings.DisableHDDPowerSaving && USBSuccess)
{
if (IOS_GetVersion() == 58)
{
SetTextf("Disabling HDD power saving\n");
s32 result = USBStorage_OGC_DisablePowerSaving();
if (result == USBSTORAGE_POWER_ALL_DISABLED)
{
SetTextf("HDD power saving disabled\n");
gprintf("Disable HDD power saving: APM and standby timer disabled\n");
}
else if (result > 0)
{
SetTextf("HDD power saving partially disabled\n");
gprintf("Disable HDD power saving: APM %s, standby timer %s\n",
(result & USBSTORAGE_POWER_APM_DISABLED) ? "disabled" : "failed",
(result & USBSTORAGE_POWER_STANDBY_DISABLED) ? "disabled" : "failed");
}
else if (result == 0)
{
SetTextf("HDD power saving not supported\n");
gprintf("Disable HDD power saving: ATA power commands not supported\n");
}
else
{
SetTextf("HDD power saving command failed\n");
gprintf("Disable HDD power saving: transport error (%i)\n", result);
}
}
else
{
SetTextf("HDD power saving requires IOS58\n");
gprintf("Disable HDD power saving: skipped (requires IOS58 USB backend)\n");
}
}

// Some settings need to be enabled to boot directly into games
gprintf("Quick game boot: %s\n", quickGameBoot ? "yes" : "no");
if (quickGameBoot)
Expand Down
7 changes: 7 additions & 0 deletions source/settings/CSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ void CSettings::SetDefault()
MultiplePartitions = OFF;
BlockIOSReload = AUTO;
USBPort = 0;
DisableHDDPowerSaving = OFF;
WSFactor = 0.8f; //actually should be 0.75 for real widescreen
FontScaleFactor = 0.8f; //it's a work around to not have to change ALL fonts now
ClockFontScaleFactor = 1.0f; // Scale of 1 to prevent misaligned clock.
Expand Down Expand Up @@ -414,6 +415,7 @@ bool CSettings::Save()
fprintf(file, "SilentHomeMenu = %d\n", SilentHomeMenu);
fprintf(file, "MultiplePartitions = %d\n", MultiplePartitions);
fprintf(file, "USBPort = %d\n", USBPort);
fprintf(file, "DisableHDDPowerSaving = %d\n", DisableHDDPowerSaving);
fprintf(file, "BlockIOSReload = %d\n", BlockIOSReload);
fprintf(file, "WSFactor = %0.3f\n", WSFactor);
fprintf(file, "FontScaleFactor = %0.3f\n", FontScaleFactor);
Expand Down Expand Up @@ -829,6 +831,11 @@ bool CSettings::SetSetting(char *name, char *value)
USBPort = atoi(value);
return true;
}
else if (strcmp(name, "DisableHDDPowerSaving") == 0)
{
DisableHDDPowerSaving = atoi(value);
return true;
}
else if (strcmp(name, "patchcountrystrings") == 0)
{
patchcountrystrings = atoi(value);
Expand Down
1 change: 1 addition & 0 deletions source/settings/CSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class CSettings
short SilentHomeMenu;
short MultiplePartitions;
short USBPort;
short DisableHDDPowerSaving;
short BlockIOSReload;
u32 InstallPartitions;
u32 ParentalBlocks;
Expand Down
18 changes: 18 additions & 0 deletions source/settings/menus/HardDriveSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ HardDriveSM::HardDriveSM()
if (strncmp(Settings.ConfigPath, "sd", 2) == 0)
Options->SetName(Idx++, "%s", tr( "SD Card Mode" ));
Options->SetName(Idx++, "%s", tr( "USB Port" ));
Options->SetName(Idx++, "%s", tr( "Disable HDD Power Saving" ));
Options->SetName(Idx++, "%s", tr( "Install Directories" ));
Options->SetName(Idx++, "%s", tr( "Game Split Size" ));
Options->SetName(Idx++, "%s", tr( "Install Partitions" ));
Expand Down Expand Up @@ -185,6 +186,9 @@ void HardDriveSM::SetOptionValues()
else
Options->SetValue(Idx++, "%i", NewSettingsUSBPort);

//! Settings: Disable HDD power saving
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.DisableHDDPowerSaving] ));

//! Settings: Install directories
Options->SetValue(Idx++, "%s", tr( InstallToText[Settings.InstallToDir] ));

Expand Down Expand Up @@ -274,6 +278,20 @@ int HardDriveSM::GetMenuInternal()
NewSettingsUSBPort = 0;
}

//! Settings: Disable HDD power saving
else if (ret == ++Idx)
{
if (++Settings.DisableHDDPowerSaving >= MAX_ON_OFF)
Settings.DisableHDDPowerSaving = 0;

if (Settings.DisableHDDPowerSaving == ON)
{
WindowPrompt(0,
tr("Applied on the next launch after testing ATA support. This may keep a mechanical HDD spinning, increasing power use, heat, noise, and running time."),
tr("OK"));
}
}

//! Settings: Install directories
else if (ret == ++Idx)
{
Expand Down
52 changes: 51 additions & 1 deletion source/usbloader/usbstorage_libogc.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u
__stwbrx(cbw_buffer, 8, len);
cbw_buffer[12] = flags;
cbw_buffer[13] = lun;
cbw_buffer[14] = (cbLen > 6 ? 10 : 6);
cbw_buffer[14] = (cbLen > 6 ? cbLen : 6);

memcpy(cbw_buffer + 15, cb, cbLen);

Expand Down Expand Up @@ -1013,6 +1013,56 @@ int USBStorage_OGC_ioctl(int request, ...)
return retval;
}

static s32 __usbstorage_ogc_ata_nodata(u8 ata_command, u8 feature)
{
raw_device_command rdc;
s32 retval;

memset(&rdc, 0, sizeof(rdc));
rdc.command[0] = 0x85; /* ATA PASS-THROUGH (16) */
rdc.command[1] = 0x06; /* Non-data protocol */
rdc.command[2] = 0x0c;
rdc.command[4] = feature;
rdc.command[14] = ata_command;
rdc.command_length = sizeof(rdc.command);
rdc.flags = B_RAW_DEVICE_DATA_IN;

retval = USBStorage_OGC_ioctl(B_RAW_DEVICE_COMMAND, &rdc);
if (retval < 0)
return retval;

return rdc.scsi_status == 0 ? USBSTORAGE_OK : USBSTORAGE_ESTATUS;
}

s32 USBStorage_OGC_DisablePowerSaving()
{
/* CHECK POWER MODE does not change drive state. */
s32 retval = __usbstorage_ogc_ata_nodata(0xe5, 0x00);
if (retval == USBSTORAGE_ESTATUS)
return 0;
if (retval < 0)
return retval;

s32 result = 0;
s32 transport_error = 0;

/* SET FEATURES, DISABLE APM. */
retval = __usbstorage_ogc_ata_nodata(0xef, 0x85);
if (retval == USBSTORAGE_OK)
result |= USBSTORAGE_POWER_APM_DISABLED;
else if (retval != USBSTORAGE_ESTATUS)
transport_error = retval;

/* IDLE with sector count zero disables the standby timer. */
retval = __usbstorage_ogc_ata_nodata(0xe3, 0x00);
if (retval == USBSTORAGE_OK)
result |= USBSTORAGE_POWER_STANDBY_DISABLED;
else if (retval != USBSTORAGE_ESTATUS && transport_error == 0)
transport_error = retval;

return result != 0 ? result : transport_error;
}

DISC_INTERFACE __io_usbstorage_ogc = {
DEVICE_TYPE_WII_USB,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
Expand Down
13 changes: 13 additions & 0 deletions source/usbloader/usbstorage_libogc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ s32 USBStorage_OGC_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sector
s32 USBStorage_OGC_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer);
s32 USBStorage_OGC_StartStop(usbstorage_handle *dev, u8 lun, u8 lo_ej, u8 start, u8 imm);

#define USBSTORAGE_POWER_APM_DISABLED (1 << 0)
#define USBSTORAGE_POWER_STANDBY_DISABLED (1 << 1)
#define USBSTORAGE_POWER_ALL_DISABLED (USBSTORAGE_POWER_APM_DISABLED | USBSTORAGE_POWER_STANDBY_DISABLED)

/**
* Disable ATA Advanced Power Management and the ATA standby timer on the
* currently mounted USB/SAT disk. A non-mutating ATA command is used to check
* pass-through support first. Returns a USBSTORAGE_POWER_* bitmask, zero when
* unsupported, or a negative transport error. The settings are volatile and
* do not write sectors or bridge firmware.
*/
s32 USBStorage_OGC_DisablePowerSaving();

extern DISC_INTERFACE __io_usbstorage_ogc;

#ifdef __cplusplus
Expand Down