mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-08-07 17:25:08 +00:00
dbdma: Schedule interpret_cmd.
Have the entire dbdma program executed by scheduling each iteration in the CPU loop. This is done only for devices that use the dbdma program to drive data input/output (has_data_callbacks) rather than have the device drive the dbdma program.
This commit is contained in:
@@ -43,6 +43,7 @@ void DMAChannel::set_data_callbacks(DbdmaCallback in_cb, DbdmaCallback out_cb, D
|
|||||||
this->in_cb = in_cb;
|
this->in_cb = in_cb;
|
||||||
this->out_cb = out_cb;
|
this->out_cb = out_cb;
|
||||||
this->flush_cb = flush_cb;
|
this->flush_cb = flush_cb;
|
||||||
|
this->has_data_callbacks = in_cb || out_cb || flush_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load DMACmd from physical memory. */
|
/* Load DMACmd from physical memory. */
|
||||||
@@ -60,16 +61,32 @@ DMACmd* DMAChannel::fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writabl
|
|||||||
return cmd_host;
|
return cmd_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DMAChannel::interpret_cmd() {
|
void DMAChannel::schedule_cmd() {
|
||||||
|
if (!interpret_timer_id) {
|
||||||
|
interpret_timer_id = TimerManager::get_instance()->add_oneshot_timer(1000000, [this] {
|
||||||
|
interpret_timer_id = 0;
|
||||||
|
if (this->ch_stat & CH_STAT_ACTIVE) {
|
||||||
|
this->interpret_cmd();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMAChannel::interpret_cmd() {
|
||||||
DMACmd cmd_struct;
|
DMACmd cmd_struct;
|
||||||
MapDmaResult res;
|
MapDmaResult res;
|
||||||
|
|
||||||
if (this->cmd_in_progress) {
|
if (this->cmd_in_progress) {
|
||||||
// return current command if there is data to transfer
|
// if there is data remaining to transfer then the command is not finished
|
||||||
if (this->queue_len)
|
if (this->queue_len)
|
||||||
return this->cur_cmd;
|
return;
|
||||||
|
|
||||||
|
// if there is no data remaining to transfer then the command is finished and the program should procede to the next command
|
||||||
this->finish_cmd();
|
this->finish_cmd();
|
||||||
|
if (this->has_data_callbacks) {
|
||||||
|
schedule_cmd();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmd_is_writable;
|
bool cmd_is_writable;
|
||||||
@@ -140,7 +157,11 @@ uint8_t DMAChannel::interpret_cmd() {
|
|||||||
this->ch_stat &= ~CH_STAT_ACTIVE;
|
this->ch_stat &= ~CH_STAT_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->cur_cmd;
|
if (this->has_data_callbacks) {
|
||||||
|
if (this->has_data_callbacks) {
|
||||||
|
schedule_cmd();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMAChannel::finish_cmd() {
|
void DMAChannel::finish_cmd() {
|
||||||
|
@@ -129,8 +129,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DMACmd* fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writable);
|
static DMACmd* fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writable);
|
||||||
uint8_t interpret_cmd(void);
|
void schedule_cmd();
|
||||||
|
void interpret_cmd();
|
||||||
void finish_cmd();
|
void finish_cmd();
|
||||||
void xfer_quad(const DMACmd *cmd_desc, DMACmd *cmd_host);
|
void xfer_quad(const DMACmd *cmd_desc, DMACmd *cmd_host);
|
||||||
void update_irq();
|
void update_irq();
|
||||||
@@ -147,6 +148,8 @@ private:
|
|||||||
std::function<void(void)> in_cb = nullptr; // DMA channel in 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)> out_cb = nullptr; // DMA channel out callback
|
||||||
std::function<void(void)> flush_cb = nullptr; // DMA channel flush callback
|
std::function<void(void)> flush_cb = nullptr; // DMA channel flush callback
|
||||||
|
bool has_data_callbacks = false;
|
||||||
|
uint32_t interpret_timer_id = 0;
|
||||||
|
|
||||||
uint16_t ch_stat = 0;
|
uint16_t ch_stat = 0;
|
||||||
uint32_t cmd_ptr = 0;
|
uint32_t cmd_ptr = 0;
|
||||||
|
Reference in New Issue
Block a user