dbdma: introduce new DMA API.

This commit is contained in:
Maxim Poliakovski 2024-07-15 02:08:14 +02:00
parent 293e869acb
commit 4a425c4ecf
3 changed files with 67 additions and 2 deletions

View File

@ -102,6 +102,7 @@ uint8_t DMAChannel::interpret_cmd() {
break;
case DBDMA_Cmd::INPUT_MORE:
case DBDMA_Cmd::INPUT_LAST:
this->xfer_from_device();
if (this->in_cb)
this->in_cb();
break;
@ -406,6 +407,20 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size) {
}
}
void DMAChannel::xfer_from_device() {
if (this->dev_obj == nullptr)
return;
this->xfer_dir = DMA_DIR_FROM_DEV;
if (!this->dev_obj->xfer_from(this->queue_data, this->queue_len)) {
this->queue_len = 0;
this->finish_cmd();
}
this->interpret_cmd();
}
DmaPullResult DMAChannel::pull_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data)
{
*avail_len = 0;

View File

@ -103,7 +103,7 @@ namespace DBDMA_Cmd {
typedef std::function<void(void)> DbdmaCallback;
class DMAChannel : public DmaBidirChannel {
class DMAChannel : public DmaBidirChannel, public DmaChannel {
public:
DMAChannel(std::string name) : DmaBidirChannel(name) {}
~DMAChannel() = default;
@ -134,6 +134,7 @@ protected:
void finish_cmd();
void xfer_quad(const DMACmd *cmd_desc, DMACmd *cmd_host);
void update_irq();
void xfer_from_device();
void start(void);
void resume(void);

View File

@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-22 divingkatae and maximum
Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define DMA_CORE_H
#include <cstdint>
#include <cinttypes>
#include <string>
enum DmaPullResult : int {
@ -75,4 +76,52 @@ private:
std::string name;
};
// ---------------------- New DMA API -------------------------
enum DmaMsg : unsigned {
CH_START = 1,
CH_STOP,
DATA_AVAIL,
};
enum XferDir : unsigned {
DMA_DIR_UNDEF = 0,
DMA_DIR_TO_DEV,
DMA_DIR_FROM_DEV,
};
class DmaChannel;
class DmaDevice {
public:
DmaDevice() = default;
~DmaDevice() = default;
void connect(DmaChannel *ch_obj) { this->channel_obj = ch_obj; };
void notify(DmaMsg msg) {};
virtual int xfer_from(uint8_t *buf, int len) { return len; };
protected:
DmaChannel* channel_obj = nullptr;
};
class DmaChannel {
public:
DmaChannel() = default;
~DmaChannel() = default;
void connect(DmaDevice *dev_obj) { this->dev_obj = dev_obj; };
void notify(DmaMsg msg) {};
protected:
DmaDevice* dev_obj = nullptr;
XferDir xfer_dir = DMA_DIR_UNDEF;
};
/*
TODO: write CONNECT macro that
- constructs both DmaChannel and DmaDevice objects
- calls connect() method on both objects
- initializes DMA interrupts
*/
#endif // DMA_CORE_H