mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 22:19:02 +00:00
rsx: rewrite io mappings
Along with some with fixes to cellGcmSys HLE.
This commit is contained in:
parent
f47333997f
commit
bdab26ec09
9 changed files with 233 additions and 186 deletions
|
|
@ -49,23 +49,6 @@ const u32 tiled_pitches[] = {
|
|||
0x00010000
|
||||
};
|
||||
|
||||
struct gcm_config
|
||||
{
|
||||
u32 zculls_addr;
|
||||
vm::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
|
||||
u32 tiles_addr;
|
||||
u32 ctxt_addr;
|
||||
CellGcmConfig current_config;
|
||||
CellGcmContextData current_context;
|
||||
gcmInfo gcm_info;
|
||||
};
|
||||
|
||||
u64 system_mode = 0;
|
||||
u32 local_size = 0;
|
||||
u32 local_addr = 0;
|
||||
|
||||
atomic_t<u32> reserved_size = 0;
|
||||
|
||||
// Auxiliary functions
|
||||
|
||||
/*
|
||||
|
|
@ -93,22 +76,31 @@ u32 gcmGetLocalMemorySize(u32 sdk_version)
|
|||
return 0x0E000000; // 224MB
|
||||
}
|
||||
|
||||
CellGcmOffsetTable offsetTable;
|
||||
atomic_t<u16> IoMapTable[0xC00]{};
|
||||
|
||||
error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict);
|
||||
|
||||
u32 gcmIoOffsetToAddress(u32 ioOffset)
|
||||
{
|
||||
const u32 upper12Bits = g_fxo->get<gcm_config>()->offsetTable.eaAddress[ioOffset >> 20];
|
||||
|
||||
if (static_cast<s16>(upper12Bits) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (upper12Bits << 20) | (ioOffset & 0xFFFFF);
|
||||
}
|
||||
|
||||
void InitOffsetTable()
|
||||
{
|
||||
offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main));
|
||||
offsetTable.eaAddress.set(vm::alloc(512 * sizeof(u16), vm::main));
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
|
||||
memset(offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16));
|
||||
memset(offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
|
||||
memset(IoMapTable, 0, 3072 * sizeof(u16));
|
||||
cfg->offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main));
|
||||
cfg->offsetTable.eaAddress.set(vm::alloc(512 * sizeof(u16), vm::main));
|
||||
|
||||
memset(&RSXIOMem, 0xFF, sizeof(RSXIOMem));
|
||||
reserved_size = 0;
|
||||
std::memset(cfg->offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16));
|
||||
std::memset(cfg->offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
|
||||
|
||||
cfg->reserved_size = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -132,7 +124,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
|
|||
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index);
|
||||
}
|
||||
|
||||
return vm::ptr<CellGcmReportData>::make(RSXIOMem.RealAddr(0x0e000000 + index * 0x10));
|
||||
return vm::cast(gcmIoOffsetToAddress(0x0e000000 + index * 0x10));
|
||||
}
|
||||
|
||||
// Anything else is Local
|
||||
|
|
@ -142,7 +134,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
|
|||
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
|
||||
}
|
||||
|
||||
return vm::ptr<CellGcmReportData>::make(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
|
||||
return vm::cast(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
|
||||
}
|
||||
|
||||
u64 cellGcmGetTimeStamp(u32 index)
|
||||
|
|
@ -168,7 +160,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
|
|||
cellGcmSys.warning("cellGcmGetNotifyDataAddress(index=%d)", index);
|
||||
|
||||
// If entry not in use, return NULL
|
||||
u16 entry = offsetTable.eaAddress[241];
|
||||
u16 entry = g_fxo->get<gcm_config>()->offsetTable.eaAddress[241];
|
||||
if (entry == 0xFFFF) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -225,24 +217,8 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
|
|||
{
|
||||
cellGcmSys.warning("cellGcmGetTimeStampLocation(index=%d, location=%d)", index, location);
|
||||
|
||||
if (location == CELL_GCM_LOCATION_LOCAL) {
|
||||
if (index >= 2048) {
|
||||
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index);
|
||||
return 0;
|
||||
}
|
||||
return vm::read64(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
|
||||
}
|
||||
|
||||
if (location == CELL_GCM_LOCATION_MAIN) {
|
||||
if (index >= 1024 * 1024) {
|
||||
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong main index (%d)", index);
|
||||
return 0;
|
||||
}
|
||||
return vm::read64(RSXIOMem.RealAddr(index * 0x10));
|
||||
}
|
||||
|
||||
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong location (%d)", location);
|
||||
return 0;
|
||||
// NOTE: No error checkings
|
||||
return cellGcmGetReportDataAddressLocation(index, location)->timer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -365,25 +341,26 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
|||
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
|
||||
|
||||
const auto gcm_cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(gcm_cfg->gcmio_mutex);
|
||||
|
||||
gcm_cfg->current_config.ioAddress = 0;
|
||||
gcm_cfg->current_config.localAddress = 0;
|
||||
local_size = 0;
|
||||
local_addr = 0;
|
||||
gcm_cfg->local_size = 0;
|
||||
gcm_cfg->local_addr = 0;
|
||||
|
||||
if (!local_size && !local_addr)
|
||||
//if (!gcm_cfg->local_size && !gcm_cfg->local_addr)
|
||||
{
|
||||
local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
|
||||
local_addr = rsx::constants::local_mem_base;
|
||||
vm::falloc(local_addr, local_size, vm::video);
|
||||
gcm_cfg->local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
|
||||
gcm_cfg->local_addr = rsx::constants::local_mem_base;
|
||||
vm::falloc(gcm_cfg->local_addr, gcm_cfg->local_size, vm::video);
|
||||
}
|
||||
|
||||
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);
|
||||
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", gcm_cfg->local_addr, gcm_cfg->local_size);
|
||||
|
||||
InitOffsetTable();
|
||||
|
||||
const auto render = rsx::get_current_renderer();
|
||||
if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
||||
if (gcm_cfg->system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmInit(): 512MB io address space used");
|
||||
render->main_mem_size = 0x20000000;
|
||||
|
|
@ -401,8 +378,8 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
|||
|
||||
gcm_cfg->current_config.ioSize = ioSize;
|
||||
gcm_cfg->current_config.ioAddress = ioAddress;
|
||||
gcm_cfg->current_config.localSize = local_size;
|
||||
gcm_cfg->current_config.localAddress = local_addr;
|
||||
gcm_cfg->current_config.localSize = gcm_cfg->local_size;
|
||||
gcm_cfg->current_config.localAddress = gcm_cfg->local_addr;
|
||||
gcm_cfg->current_config.memoryFrequency = 650000000;
|
||||
gcm_cfg->current_config.coreFrequency = 500000000;
|
||||
|
||||
|
|
@ -446,7 +423,7 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
|||
render->isHLE = true;
|
||||
render->label_addr = gcm_cfg->gcm_info.label_addr;
|
||||
render->device_addr = gcm_cfg->gcm_info.context_addr;
|
||||
render->local_mem_size = local_size;
|
||||
render->local_mem_size = gcm_cfg->local_size;
|
||||
render->init(gcm_cfg->gcm_info.control_addr - 0x40);
|
||||
|
||||
return CELL_OK;
|
||||
|
|
@ -855,7 +832,7 @@ error_code cellGcmInitSystemMode(u64 mode)
|
|||
{
|
||||
cellGcmSys.trace("cellGcmInitSystemMode(mode=0x%x)", mode);
|
||||
|
||||
system_mode = mode;
|
||||
g_fxo->get<gcm_config>()->system_mode = mode;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
@ -930,7 +907,7 @@ error_code cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset)
|
|||
// Address in main memory else check
|
||||
else
|
||||
{
|
||||
const u32 upper12Bits = offsetTable.ioAddress[address >> 20];
|
||||
const u32 upper12Bits = g_fxo->get<gcm_config>()->offsetTable.ioAddress[address >> 20];
|
||||
|
||||
// If the address is mapped in IO
|
||||
if (upper12Bits != 0xFFFF)
|
||||
|
|
@ -951,29 +928,31 @@ u32 cellGcmGetMaxIoMapSize()
|
|||
{
|
||||
cellGcmSys.trace("cellGcmGetMaxIoMapSize()");
|
||||
|
||||
return rsx::get_current_renderer()->main_mem_size - reserved_size;
|
||||
return rsx::get_current_renderer()->main_mem_size - g_fxo->get<gcm_config>()->reserved_size;
|
||||
}
|
||||
|
||||
void cellGcmGetOffsetTable(vm::ptr<CellGcmOffsetTable> table)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetOffsetTable(table=*0x%x)", table);
|
||||
|
||||
table->ioAddress = offsetTable.ioAddress;
|
||||
table->eaAddress = offsetTable.eaAddress;
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
|
||||
table->ioAddress = cfg->offsetTable.ioAddress;
|
||||
table->eaAddress = cfg->offsetTable.eaAddress;
|
||||
}
|
||||
|
||||
error_code cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmIoOffsetToAddress(ioOffset=0x%x, address=*0x%x)", ioOffset, address);
|
||||
|
||||
const u32 upper12Bits = offsetTable.eaAddress[ioOffset >> 20];
|
||||
const u32 addr = gcmIoOffsetToAddress(ioOffset);
|
||||
|
||||
if (static_cast<s16>(upper12Bits) < 0)
|
||||
if (!addr)
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*address = (upper12Bits << 20) | (ioOffset & 0xFFFFF);
|
||||
*address = addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
@ -990,16 +969,18 @@ error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
|
|||
return error;
|
||||
}
|
||||
|
||||
// Assume lock is acquired
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
ea >>= 20, io >>= 20, size >>= 20;
|
||||
|
||||
// Fill the offset table
|
||||
for (u32 i = 0; i < size; i++)
|
||||
{
|
||||
offsetTable.ioAddress[ea + i] = io + i;
|
||||
offsetTable.eaAddress[io + i] = ea + i;
|
||||
cfg->offsetTable.ioAddress[ea + i] = io + i;
|
||||
cfg->offsetTable.eaAddress[io + i] = ea + i;
|
||||
}
|
||||
|
||||
IoMapTable[ea] = size;
|
||||
cfg->IoMapTable[ea] = size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1007,6 +988,9 @@ error_code cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
|
|||
{
|
||||
cellGcmSys.warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
|
||||
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
return gcmMapEaIoAddress(ea, io, size, false);
|
||||
}
|
||||
|
||||
|
|
@ -1016,6 +1000,9 @@ error_code cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
|
|||
|
||||
verify(HERE), flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/;
|
||||
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
return gcmMapEaIoAddress(ea, io, size, true);
|
||||
}
|
||||
|
||||
|
|
@ -1023,17 +1010,17 @@ error_code cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size)
|
|||
{
|
||||
cellGcmSys.warning("cellGcmMapLocalMemory(address=*0x%x, size=*0x%x)", address, size);
|
||||
|
||||
if (!local_addr && !local_size && vm::falloc(local_addr = rsx::constants::local_mem_base, local_size = 0xf900000 /* TODO */, vm::video))
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
if (!cfg->local_addr && !cfg->local_size && vm::falloc(cfg->local_addr = rsx::constants::local_mem_base, cfg->local_size = 0xf900000 /* TODO */, vm::video))
|
||||
{
|
||||
*address = local_addr;
|
||||
*size = local_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
*address = cfg->local_addr;
|
||||
*size = cfg->local_size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
error_code cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
|
||||
|
|
@ -1042,10 +1029,13 @@ error_code cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
|
|||
|
||||
if (!size || (ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
|
||||
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
// Use the offset table to find the next free io address
|
||||
for (u32 io = 0, end = (rsx::get_current_renderer()->main_mem_size - reserved_size) >> 20, unmap_count = 1; io < end; unmap_count++)
|
||||
for (u32 io = 0, end = (rsx::get_current_renderer()->main_mem_size - cfg->reserved_size) >> 20, unmap_count = 1; io < end; unmap_count++)
|
||||
{
|
||||
if (static_cast<s16>(offsetTable.eaAddress[io + unmap_count - 1]) < 0)
|
||||
if (static_cast<s16>(cfg->offsetTable.eaAddress[io + unmap_count - 1]) < 0)
|
||||
{
|
||||
if (unmap_count >= (size >> 20))
|
||||
{
|
||||
|
|
@ -1079,12 +1069,15 @@ error_code cellGcmReserveIoMapSize(u32 size)
|
|||
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
|
||||
}
|
||||
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
if (size > cellGcmGetMaxIoMapSize())
|
||||
{
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
reserved_size += size;
|
||||
cfg->reserved_size += size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1092,48 +1085,60 @@ error_code cellGcmUnmapEaIoAddress(u32 ea)
|
|||
{
|
||||
cellGcmSys.warning("cellGcmUnmapEaIoAddress(ea=0x%x)", ea);
|
||||
|
||||
if (const u32 size = IoMapTable[ea >>= 20].exchange(0))
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
if (const u32 size = cfg->IoMapTable[ea >> 20])
|
||||
{
|
||||
const u32 io = offsetTable.ioAddress[ea];
|
||||
u32 io = cfg->offsetTable.ioAddress[ea];
|
||||
|
||||
if (auto error = sys_rsx_context_iounmap(0x55555555, io, size))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ea >>= 20, io >>= 20;
|
||||
|
||||
const auto render = rsx::get_current_renderer();
|
||||
|
||||
for (u32 i = 0; i < size; i++)
|
||||
{
|
||||
RSXIOMem.io[ea + i].raw() = offsetTable.ioAddress[ea + i] = 0xFFFF;
|
||||
RSXIOMem.ea[io + i].raw() = offsetTable.eaAddress[io + i] = 0xFFFF;
|
||||
cfg->offsetTable.ioAddress[ea + i] = 0xFFFF;
|
||||
cfg->offsetTable.eaAddress[io + i] = 0xFFFF;
|
||||
}
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
cfg->IoMapTable[ea] = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
error_code cellGcmUnmapIoAddress(u32 io)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmUnmapIoAddress(io=0x%x)", io);
|
||||
|
||||
if (u32 size = IoMapTable[RSXIOMem.ea[io >>= 20]].exchange(0))
|
||||
{
|
||||
const u32 ea = offsetTable.eaAddress[io];
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
for (u32 i = 0; i < size; i++)
|
||||
if (u32 ea = cfg->offsetTable.eaAddress[io >>= 20], size = cfg->IoMapTable[ea]; size)
|
||||
{
|
||||
if (auto error = sys_rsx_context_iounmap(0x55555555, io, size))
|
||||
{
|
||||
RSXIOMem.io[ea + i].raw() = offsetTable.ioAddress[ea + i] = 0xFFFF;
|
||||
RSXIOMem.ea[io + i].raw() = offsetTable.eaAddress[io + i] = 0xFFFF;
|
||||
return error;
|
||||
}
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
const auto render = rsx::get_current_renderer();
|
||||
for (u32 i = 0; i < size; i++)
|
||||
{
|
||||
cfg->offsetTable.ioAddress[ea + i] = 0xFFFF;
|
||||
cfg->offsetTable.eaAddress[io + i] = 0xFFFF;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
error_code cellGcmUnreserveIoMapSize(u32 size)
|
||||
|
|
@ -1145,12 +1150,15 @@ error_code cellGcmUnreserveIoMapSize(u32 size)
|
|||
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
|
||||
}
|
||||
|
||||
if (size > reserved_size)
|
||||
const auto cfg = g_fxo->get<gcm_config>();
|
||||
std::lock_guard lock(cfg->gcmio_mutex);
|
||||
|
||||
if (size > cfg->reserved_size)
|
||||
{
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
reserved_size -= size;
|
||||
cfg->reserved_size -= size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1375,7 +1383,7 @@ static std::pair<u32, u32> getNextCommandBufferBeginEnd(u32 current)
|
|||
|
||||
static u32 getOffsetFromAddress(u32 address)
|
||||
{
|
||||
const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
|
||||
const u32 upper = g_fxo->get<gcm_config>()->offsetTable.ioAddress[address >> 20]; // 12 bits
|
||||
verify(HERE), (upper != 0xFFFF);
|
||||
return (upper << 20) | (address & 0xFFFFF);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue