Compare commits

..

No commits in common. "11d61359c19960ea1d1e4482f25d9517024f19e6" and "6adba32238169ec33c0648e60e555a757f514beb" have entirely different histories.

9 changed files with 27 additions and 264 deletions

View File

@ -82,9 +82,6 @@ AddressMapEntry last_write_area;
AddressMapEntry last_exec_area;
AddressMapEntry last_ptab_area;
/** Dummy pages for catching writes to physical read-only pages */
static std::array<uint64_t, 8192 / sizeof(uint64_t)> dummy_page;
/** 601-style block address translation. */
static BATResult mpc601_block_address_translation(uint32_t la)
{
@ -313,23 +310,11 @@ MapDmaResult mmu_map_dma_mem(uint32_t addr, uint32_t size, bool allow_mmio) {
AddressMapEntry *cur_dma_rgn;
cur_dma_rgn = mem_ctrl_instance->find_range(addr);
if (!cur_dma_rgn) {
ABORT_F("SOS: DMA access to unmapped physical memory 0x%08X..0x%08X!",
addr, addr + size - 1
);
}
if (!cur_dma_rgn || (addr + size) > cur_dma_rgn->end)
ABORT_F("SOS: DMA access to unmapped physical memory %08X!", addr);
if (addr + size - 1 > cur_dma_rgn->end) {
ABORT_F("SOS: DMA access to unmapped physical memory 0x%08X..0x%08X because size extends outside region 0x%08X..0x%08X!",
addr, addr + size - 1, cur_dma_rgn->start, cur_dma_rgn->end
);
}
if ((cur_dma_rgn->type & RT_MMIO) && !allow_mmio) {
ABORT_F("SOS: DMA access to a MMIO region 0x%08X..0x%08X (%s) for physical memory 0x%08X..0x%08X is not allowed.",
cur_dma_rgn->start, cur_dma_rgn->end, cur_dma_rgn->devobj->get_name().c_str(), addr, addr + size - 1
);
}
if ((cur_dma_rgn->type & RT_MMIO) && !allow_mmio)
ABORT_F("SOS: DMA access to a MMIO region is not allowed");
if (cur_dma_rgn->type & (RT_ROM | RT_RAM)) {
host_va = cur_dma_rgn->mem_ptr + (addr - cur_dma_rgn->start);
@ -374,6 +359,9 @@ uint32_t tlb_size_mask = TLB_SIZE - 1;
uint64_t UnmappedVal = -1ULL;
TLBEntry UnmappedMem = {TLB_INVALID_TAG, TLBFlags::PAGE_NOPHYS, 0, 0};
// Dummy page for catching writes to physical read-only pages
static std::array<uint64_t, 4096 / sizeof(uint64_t)> dummy_page;
uint8_t CurITLBMode = {0xFF}; // current ITLB mode
uint8_t CurDTLBMode = {0xFF}; // current DTLB mode

View File

@ -39,12 +39,6 @@ void DMAChannel::set_callbacks(DbdmaCallback start_cb, DbdmaCallback stop_cb) {
this->stop_cb = stop_cb;
}
void DMAChannel::set_data_callbacks(DbdmaCallback in_cb, DbdmaCallback out_cb, DbdmaCallback flush_cb) {
this->in_cb = in_cb;
this->out_cb = out_cb;
this->flush_cb = flush_cb;
}
/* Load DMACmd from physical memory. */
DMACmd* DMAChannel::fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writable) {
MapDmaResult res = mmu_map_dma_mem(cmd_addr, 16, false);
@ -94,18 +88,6 @@ uint8_t DMAChannel::interpret_cmd() {
this->queue_data = res.host_va;
this->res_count = 0;
this->cmd_in_progress = true;
switch (this->cur_cmd) {
case DBDMA_Cmd::OUTPUT_MORE:
case DBDMA_Cmd::OUTPUT_LAST:
if (this->out_cb)
this->out_cb();
break;
case DBDMA_Cmd::INPUT_MORE:
case DBDMA_Cmd::INPUT_LAST:
if (this->in_cb)
this->in_cb();
break;
}
} else
this->finish_cmd();
break;
@ -171,7 +153,6 @@ void DMAChannel::finish_cmd() {
if (res.is_writable)
WRITE_WORD_LE_A(&cmd_desc[14], this->ch_stat | CH_STAT_ACTIVE);
this->ch_stat &= ~CH_STAT_FLUSH;
// react to cmd.b (branch) bits
if (cmd_desc[2] & 0xC) {
@ -339,13 +320,9 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size) {
// That means we need to update memory before channel operation
// is aborted to prevent data loss.
if (new_stat & CH_STAT_FLUSH) {
if (this->cur_cmd <= DBDMA_Cmd::INPUT_LAST && this->flush_cb && (new_stat & CH_STAT_ACTIVE) && !(this->ch_stat & CH_STAT_DEAD)) {
this->flush_cb();
} else {
// NOTE: because this implementation doesn't currently support
// partial memory updates no special action is taken here
new_stat &= ~CH_STAT_FLUSH;
}
// NOTE: because this implementation doesn't currently support
// partial memory updates no special action is taken here
new_stat &= ~CH_STAT_FLUSH;
this->ch_stat = new_stat;
}
@ -469,40 +446,6 @@ int DMAChannel::push_data(const char* src_ptr, int len) {
return 0;
}
void DMAChannel::end_pull_data() {
if (this->ch_stat & CH_STAT_DEAD || !(this->ch_stat & CH_STAT_ACTIVE)) {
// dead or idle channel? -> no more data
LOG_F(WARNING, "%s: Ending Dead/idle channel -> no more data", this->get_name().c_str());
return;
}
if (this->queue_len) {
this->queue_len = 0;
} else {
this->ch_stat &= ~CH_STAT_FLUSH;
}
// proceed with the DBDMA program
this->interpret_cmd();
}
void DMAChannel::end_push_data() {
if (this->ch_stat & CH_STAT_DEAD || !(this->ch_stat & CH_STAT_ACTIVE)) {
LOG_F(WARNING, "%s: Attempt to end push data to dead/idle channel",
this->get_name().c_str());
return;
}
if (this->queue_len) {
this->queue_len = 0;
} else {
this->ch_stat &= ~CH_STAT_FLUSH;
}
// proceed with the DBDMA program
this->interpret_cmd();
}
bool DMAChannel::is_out_active() {
if (this->ch_stat & CH_STAT_DEAD || !(this->ch_stat & CH_STAT_ACTIVE)) {
return false;

View File

@ -109,7 +109,6 @@ public:
~DMAChannel() = default;
void set_callbacks(DbdmaCallback start_cb, DbdmaCallback stop_cb);
void set_data_callbacks(DbdmaCallback in_cb, DbdmaCallback out_cb, DbdmaCallback flush_cb);
uint32_t reg_read(uint32_t offset, int size);
void reg_write(uint32_t offset, uint32_t value, int size);
void set_stat(uint8_t new_stat) { this->ch_stat = (this->ch_stat & 0xff00) | new_stat; }
@ -118,10 +117,6 @@ public:
bool is_in_active();
DmaPullResult pull_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data);
int push_data(const char* src_ptr, int len);
int get_pull_data_remaining() { return this->queue_len; }
int get_push_data_remaining() { return this->queue_len; }
void end_pull_data();
void end_push_data();
void register_dma_int(InterruptCtrl* int_ctrl_obj, uint32_t irq_id) {
this->int_ctrl = int_ctrl_obj;
@ -143,9 +138,6 @@ protected:
private:
std::function<void(void)> start_cb = nullptr; // DMA channel start callback
std::function<void(void)> stop_cb = nullptr; // DMA channel stop callback
std::function<void(void)> in_cb = nullptr; // DMA channel in callback
std::function<void(void)> out_cb = nullptr; // DMA channel out callback
std::function<void(void)> flush_cb = nullptr; // DMA channel flush callback
uint16_t ch_stat = 0;
uint32_t cmd_ptr = 0;

View File

@ -39,8 +39,6 @@ public:
virtual bool is_out_active() { return true; };
virtual DmaPullResult pull_data(uint32_t req_len, uint32_t *avail_len,
uint8_t **p_data) = 0;
virtual int get_pull_data_remaining() { return 1; };
virtual void end_pull_data() { };
std::string get_name(void) { return this->name; };
@ -54,8 +52,6 @@ public:
virtual bool is_in_active() { return true; };
virtual int push_data(const char* src_ptr, int len) = 0;
virtual int get_push_data_remaining() { return 1; };
virtual void end_push_data() { };
std::string get_name(void) { return this->name; };

View File

@ -113,7 +113,7 @@ int AthensClocks::get_dot_freq()
22, 27, 28, 31, 35, 37, 38, 42, 49, 55, 56, 78, 125
};
if (this->regs[AthensRegs::P2_MUX2] & 0x80) {
if (this->regs[AthensRegs::P2_MUX2] & 0xC0) {
LOG_F(INFO, "%s: dot clock disabled", this->name.c_str());
return 0;
}

View File

@ -21,7 +21,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file Enhanced Serial Communications Controller (ESCC) emulation. */
#include <core/timermanager.h>
#include <devices/deviceregistry.h>
#include <devices/serial/chario.h>
#include <devices/serial/escc.h>
@ -73,47 +72,36 @@ void EsccController::reset()
uint8_t EsccController::read(uint8_t reg_offset)
{
uint8_t value;
uint8_t result = 0;
switch(reg_offset) {
case EsccReg::Port_B_Cmd:
LOG_F(9, "ESCC: reading Port B register RR%d", this->reg_ptr);
if (this->reg_ptr == 2) {
// TODO: implement interrupt vector modifications
value = this->int_vec;
result = this->int_vec;
} else {
value = this->ch_b->read_reg(this->reg_ptr);
result = this->ch_b->read_reg(this->reg_ptr);
}
this->reg_ptr = 0;
break;
case EsccReg::Port_A_Cmd:
LOG_F(9, "ESCC: reading Port A register RR%d", this->reg_ptr);
if (this->reg_ptr == 2) {
value = this->int_vec;
return this->int_vec;
} else {
value = this->ch_a->read_reg(this->reg_ptr);
return this->ch_a->read_reg(this->reg_ptr);
}
break;
case EsccReg::Port_B_Data:
value = this->ch_b->receive_byte();
break;
return this->ch_b->receive_byte();
case EsccReg::Port_A_Data:
value = this->ch_a->receive_byte();
break;
case EsccReg::Enh_Reg_B:
LOG_F(WARNING, "ESCC_B: reading from unimplemented register 0x%x", reg_offset);
value = 0;
break;
case EsccReg::Enh_Reg_A:
LOG_F(WARNING, "ESCC_A: reading from unimplemented register 0x%x", reg_offset);
value = 0;
break;
return this->ch_a->receive_byte();
default:
LOG_F(WARNING, "ESCC: reading from unimplemented register 0x%x", reg_offset);
value = 0;
LOG_F(9, "ESCC: reading from unimplemented register 0x%x", reg_offset);
}
return value;
return result;
}
void EsccController::write(uint8_t reg_offset, uint8_t value)
@ -336,97 +324,6 @@ uint8_t EsccChannel::receive_byte()
return c;
}
void EsccChannel::dma_start_tx()
{
}
void EsccChannel::dma_start_rx()
{
}
void EsccChannel::dma_stop_tx()
{
if (this->timer_id_tx) {
TimerManager::get_instance()->cancel_timer(this->timer_id_tx);
this->timer_id_tx = 0;
}
}
void EsccChannel::dma_stop_rx()
{
if (this->timer_id_rx) {
TimerManager::get_instance()->cancel_timer(this->timer_id_rx);
this->timer_id_rx = 0;
}
}
void EsccChannel::dma_in_tx()
{
LOG_F(ERROR, "%s: Unexpected DMA INPUT command for transmit.", this->name.c_str());
}
void EsccChannel::dma_in_rx()
{
if (dma_ch[1]->get_push_data_remaining()) {
this->timer_id_rx = TimerManager::get_instance()->add_oneshot_timer(
0,
[this]() {
this->timer_id_rx = 0;
char c = receive_byte();
int xx = dma_ch[1]->push_data(&c, 1);
this->dma_in_rx();
});
}
}
void EsccChannel::dma_out_tx()
{
this->timer_id_tx = TimerManager::get_instance()->add_oneshot_timer(
10,
[this]() {
this->timer_id_tx = 0;
uint8_t *data;
uint32_t avail_len;
if (dma_ch[1]->pull_data(256, &avail_len, &data) == MoreData) {
while(avail_len) {
this->send_byte(*data++);
avail_len--;
}
this->dma_out_tx();
}
});
}
void EsccChannel::dma_out_rx()
{
LOG_F(ERROR, "%s: Unexpected DMA OUTPUT command for receive.", this->name.c_str());
}
void EsccChannel::dma_flush_tx()
{
this->dma_stop_tx();
this->timer_id_tx = TimerManager::get_instance()->add_oneshot_timer(
10,
[this]() {
this->timer_id_tx = 0;
dma_ch[1]->end_pull_data();
});
}
void EsccChannel::dma_flush_rx()
{
this->dma_stop_rx();
this->timer_id_rx = TimerManager::get_instance()->add_oneshot_timer(
10,
[this]() {
this->timer_id_rx = 0;
dma_ch[1]->end_push_data();
});
}
static const vector<string> CharIoBackends = {"null", "stdio", "socket"};
static const PropMap Escc_Properties = {

View File

@ -25,7 +25,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define ESCC_H
#include <devices/common/hwcomponent.h>
#include <devices/common/dbdma.h>
#include <devices/serial/chario.h>
#include <cinttypes>
@ -105,55 +104,7 @@ public:
void send_byte(uint8_t value);
uint8_t receive_byte();
void set_dma_channel(int dir_index, DmaBidirChannel *dma_ch) {
this->dma_ch[dir_index] = dma_ch;
auto dbdma_ch = dynamic_cast<DMAChannel*>(dma_ch);
if (dbdma_ch) {
switch (dir_index) {
case 0:
dbdma_ch->set_callbacks(
std::bind(&EsccChannel::dma_start_tx, this),
std::bind(&EsccChannel::dma_stop_tx, this)
);
dbdma_ch->set_data_callbacks(
std::bind(&EsccChannel::dma_in_tx, this),
std::bind(&EsccChannel::dma_out_tx, this),
std::bind(&EsccChannel::dma_flush_tx, this)
);
break;
case 1:
dbdma_ch->set_callbacks(
std::bind(&EsccChannel::dma_start_rx, this),
std::bind(&EsccChannel::dma_stop_rx, this)
);
dbdma_ch->set_data_callbacks(
std::bind(&EsccChannel::dma_in_rx, this),
std::bind(&EsccChannel::dma_out_rx, this),
std::bind(&EsccChannel::dma_flush_rx, this)
);
break;
}
}
};
private:
uint32_t timer_id_tx = 0;
uint32_t timer_id_rx = 0;
void dma_start_tx();
void dma_stop_tx();
void dma_in_tx();
void dma_out_tx();
void dma_flush_tx();
void dma_start_rx();
void dma_stop_rx();
void dma_in_rx();
void dma_out_rx();
void dma_flush_rx();
DmaBidirChannel* dma_ch[2];
std::string name;
uint8_t read_regs[16];
uint8_t write_regs[16];
@ -181,11 +132,10 @@ public:
uint8_t read(uint8_t reg_offset);
void write(uint8_t reg_offset, uint8_t value);
void set_dma_channel(int ch_dir_index, DmaBidirChannel *dma_ch) {
switch (ch_dir_index >> 1) {
case 0: ch_a->set_dma_channel(ch_dir_index & 1, dma_ch); break;
case 1: ch_b->set_dma_channel(ch_dir_index & 1, dma_ch); break;
}
void dma_start();
void dma_stop();
void set_dma_channel(int ch_index, DmaBidirChannel *dma_ch) {
this->dma_ch[ch_index] = dma_ch;
};
private:
@ -199,6 +149,8 @@ private:
uint8_t master_int_cntrl;
uint8_t int_vec;
DmaBidirChannel* dma_ch[4];
};
#endif // ESCC_H

View File

@ -591,10 +591,7 @@ void ControlVideo::enable_display()
}
this->pixel_depth = this->radacal->get_pix_width();
if (swatch_params[ControlRegs::HAL-1] != swatch_params[ControlRegs::PIPE_DELAY-1] + 1 ||
this->pixel_depth == 32 ||
(this->pixel_depth == 16 && this->active_width == 1280)
) {
if (swatch_params[ControlRegs::HAL-1] != swatch_params[ControlRegs::PIPE_DELAY-1] + 1 || this->pixel_depth == 32) {
// don't know how to calculate offset from GBASE (fb_base); it is always hard coded as + 16 in the ndrv.
this->fb_ptr += 16; // first 16 bytes are for 4 bpp HW cursor
}

View File

@ -102,8 +102,6 @@ int initialize_tnt(std::string& id)
std::string cpu = GET_STR_PROP("cpu");
if (cpu == "604e")
ppc_cpu_init(memctrl_obj, PPC_VER::MPC604E, false, 12500000ULL);
else if (cpu == "604")
ppc_cpu_init(memctrl_obj, PPC_VER::MPC604, false, 12500000ULL);
else if (cpu == "601")
ppc_cpu_init(memctrl_obj, PPC_VER::MPC601, true, 7833600ULL);
else if (cpu == "750") {