mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-02-23 21:29:00 +00:00
Mock up DBDMA channel execution for sound.
This commit is contained in:
parent
787ebfaff1
commit
8e34c1657c
@ -52,6 +52,7 @@ AddressMapEntry last_read_area = { 0 };
|
||||
AddressMapEntry last_write_area = { 0 };
|
||||
AddressMapEntry last_exec_area = { 0 };
|
||||
AddressMapEntry last_ptab_area = { 0 };
|
||||
AddressMapEntry last_dma_area = { 0 };
|
||||
|
||||
|
||||
/* macro for generating code reading from physical memory */
|
||||
@ -110,6 +111,26 @@ AddressMapEntry last_ptab_area = { 0 };
|
||||
} \
|
||||
}
|
||||
|
||||
uint8_t *mmu_get_dma_mem(uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (addr >= last_dma_area.start && (addr + size) <= last_dma_area.end) {
|
||||
return last_dma_area.mem_ptr + (addr - last_dma_area.start);
|
||||
}
|
||||
else {
|
||||
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
|
||||
if (entry && entry->type & (RT_ROM | RT_RAM)) {
|
||||
last_dma_area.start = entry->start;
|
||||
last_dma_area.end = entry->end;
|
||||
last_dma_area.mem_ptr = entry->mem_ptr;
|
||||
return last_dma_area.mem_ptr + (addr - last_dma_area.start);
|
||||
}
|
||||
else {
|
||||
LOG_F(ERROR, "SOS: DMA access to unmapped memory %08X!\n", addr);
|
||||
exit(-1); // FIXME: ugly error handling, must be the proper exception!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_set_cur_instruction(const uint8_t* ptr)
|
||||
{
|
||||
ppc_cur_instruction = READ_DWORD_BE_A(ptr);
|
||||
|
@ -44,6 +44,8 @@ typedef struct PPC_BAT_entry {
|
||||
extern void ibat_update(uint32_t bat_reg);
|
||||
extern void dbat_update(uint32_t bat_reg);
|
||||
|
||||
extern uint8_t *mmu_get_dma_mem(uint32_t addr, uint32_t size);
|
||||
|
||||
extern void ppc_set_cur_instruction(const uint8_t* ptr);
|
||||
extern void mem_write_byte(uint32_t addr, uint8_t value);
|
||||
extern void mem_write_word(uint32_t addr, uint16_t value);
|
||||
|
@ -68,6 +68,7 @@ void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
|
||||
switch(offset) {
|
||||
case AWAC_SOUND_CTRL_REG:
|
||||
this->snd_ctrl_reg = value;
|
||||
LOG_F(INFO, "New sound control value = 0x%X", this->snd_ctrl_reg);
|
||||
break;
|
||||
case AWAC_CODEC_CTRL_REG:
|
||||
subframe = (value >> 14) & 3;
|
||||
|
@ -25,6 +25,79 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <thirdparty/loguru.hpp>
|
||||
#include "dbdma.h"
|
||||
#include "endianswap.h"
|
||||
#include "cpu/ppc/ppcmmu.h"
|
||||
|
||||
void DMAChannel::get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd)
|
||||
{
|
||||
/* load DMACmd from physical memory */
|
||||
memcpy((uint8_t *)p_cmd, mmu_get_dma_mem(cmd_addr, 16), 16);
|
||||
}
|
||||
|
||||
uint8_t DMAChannel::interpret_cmd()
|
||||
{
|
||||
DMACmd cmd_struct;
|
||||
|
||||
get_next_cmd(this->cmd_ptr, &cmd_struct);
|
||||
|
||||
this->ch_stat &= ~CH_STAT_WAKE; /* clear wake bit (DMA spec, 5.5.3.4) */
|
||||
|
||||
switch(cmd_struct.cmd_key >> 4) {
|
||||
case 0:
|
||||
LOG_F(INFO, "Executing DMA Command OUTPUT_MORE");
|
||||
if (cmd_struct.cmd_key & 7) {
|
||||
LOG_F(ERROR, "Key > 0 not implemented");
|
||||
break;
|
||||
}
|
||||
if (cmd_struct.cmd_bits & 0x3F) {
|
||||
LOG_F(ERROR, "non-zero i/b/w not implemented");
|
||||
break;
|
||||
}
|
||||
LOG_F(INFO, "Transfer data, addr = 0x%X, length = 0x%X",
|
||||
cmd_struct.address, cmd_struct.req_count);
|
||||
this->cmd_ptr += 16;
|
||||
break;
|
||||
case 1:
|
||||
LOG_F(INFO, "Executing DMA Command OUTPUT_LAST");
|
||||
if (cmd_struct.cmd_key & 7) {
|
||||
LOG_F(ERROR, "Key > 0 not implemented");
|
||||
break;
|
||||
}
|
||||
if (cmd_struct.cmd_bits & 0x3F) {
|
||||
LOG_F(ERROR, "non-zero i/b/w not implemented");
|
||||
break;
|
||||
}
|
||||
LOG_F(INFO, "Transfer data, addr = 0x%X, length = 0x%X",
|
||||
cmd_struct.address, cmd_struct.req_count);
|
||||
this->cmd_ptr += 16;
|
||||
break;
|
||||
case 2:
|
||||
LOG_F(ERROR, "Unsupported DMA Command INPUT_MORE");
|
||||
break;
|
||||
case 3:
|
||||
LOG_F(ERROR, "Unsupported DMA Command INPUT_LAST");
|
||||
break;
|
||||
case 4:
|
||||
LOG_F(ERROR, "Unsupported DMA Command STORE_QUAD");
|
||||
break;
|
||||
case 5:
|
||||
LOG_F(ERROR, "Unsupported DMA Command LOAD_QUAD");
|
||||
break;
|
||||
case 6:
|
||||
LOG_F(INFO, "Unsupported DMA Command NOP");
|
||||
break;
|
||||
case 7:
|
||||
LOG_F(INFO, "DMA Command: 7 (STOP)");
|
||||
this->ch_stat &= ~CH_STAT_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "Unsupported DMA command 0x%X", cmd_struct.cmd_key >> 4);
|
||||
this->ch_stat |= CH_STAT_DEAD;
|
||||
this->ch_stat &= ~CH_STAT_ACTIVE;
|
||||
}
|
||||
|
||||
return (cmd_struct.cmd_key >> 4);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DMAChannel::reg_read(uint32_t offset, int size)
|
||||
{
|
||||
@ -99,7 +172,7 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
|
||||
break; /* ingore writes to ChannelStatus */
|
||||
case DMAReg::CMD_PTR_LO:
|
||||
if (!(this->ch_stat & CH_STAT_RUN) && !(this->ch_stat & CH_STAT_ACTIVE)) {
|
||||
this->cmd_ptr = BYTESWAP_32(value);
|
||||
this->cmd_ptr = value;
|
||||
LOG_F(INFO, "CommandPtrLo set to 0x%X", this->cmd_ptr);
|
||||
}
|
||||
break;
|
||||
@ -116,6 +189,9 @@ void DMAChannel::start()
|
||||
}
|
||||
|
||||
LOG_F(INFO, "Starting DMA channel, stat = 0x%X", this->ch_stat);
|
||||
|
||||
while (this->interpret_cmd() != 7) {
|
||||
}
|
||||
}
|
||||
|
||||
void DMAChannel::resume()
|
||||
|
@ -48,6 +48,17 @@ enum {
|
||||
CH_STAT_RUN = 0x8000
|
||||
};
|
||||
|
||||
/** DBDMA command (DBDMA spec, 5.6.1) - all fields are little-endian! */
|
||||
typedef struct DMACmd {
|
||||
uint16_t req_count;
|
||||
uint8_t cmd_bits;
|
||||
uint8_t cmd_key;
|
||||
uint32_t address;
|
||||
uint32_t cmd_arg;
|
||||
uint16_t res_count;
|
||||
uint16_t xfer_stat;
|
||||
} DMACmd;
|
||||
|
||||
class DMAChannel {
|
||||
public:
|
||||
DMAChannel() = default;
|
||||
@ -57,6 +68,9 @@ public:
|
||||
void reg_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
protected:
|
||||
void get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd);
|
||||
uint8_t interpret_cmd(void);
|
||||
|
||||
void start(void);
|
||||
void resume(void);
|
||||
void abort(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user