mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-08-15 09:27:27 +00:00
AMIC: implement floppy DMA channel.
This commit is contained in:
@@ -70,6 +70,8 @@ AMIC::AMIC() : MMIODevice()
|
|||||||
|
|
||||||
// intialize floppy disk HW
|
// intialize floppy disk HW
|
||||||
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
||||||
|
this->floppy_dma = std::unique_ptr<AmicFloppyDma> (new AmicFloppyDma());
|
||||||
|
this->swim3->set_dma_channel(this->floppy_dma.get());
|
||||||
gMachineObj->add_subdevice("SWIM3", this->swim3.get());
|
gMachineObj->add_subdevice("SWIM3", this->swim3.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,16 +159,16 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
|
|||||||
case AMICReg::DMA_Base_Addr_1:
|
case AMICReg::DMA_Base_Addr_1:
|
||||||
case AMICReg::DMA_Base_Addr_2:
|
case AMICReg::DMA_Base_Addr_2:
|
||||||
case AMICReg::DMA_Base_Addr_3:
|
case AMICReg::DMA_Base_Addr_3:
|
||||||
return (this->dma_base >> (offset & 3) * 8) & 0xFF;
|
return (this->dma_base >> (3 - (offset & 3)) * 8) & 0xFF;
|
||||||
case AMICReg::SCSI_DMA_Ctrl:
|
case AMICReg::SCSI_DMA_Ctrl:
|
||||||
return this->scsi_dma_cs;
|
return this->scsi_dma_cs;
|
||||||
case AMICReg::Floppy_Addr_Ptr_0:
|
case AMICReg::Floppy_Addr_Ptr_0:
|
||||||
case AMICReg::Floppy_Addr_Ptr_1:
|
case AMICReg::Floppy_Addr_Ptr_1:
|
||||||
case AMICReg::Floppy_Addr_Ptr_2:
|
case AMICReg::Floppy_Addr_Ptr_2:
|
||||||
case AMICReg::Floppy_Addr_Ptr_3:
|
case AMICReg::Floppy_Addr_Ptr_3:
|
||||||
return (this->floppy_addr_ptr >> (offset & 3) * 8) & 0xFF;
|
return (this->floppy_addr_ptr >> (3 - (offset & 3)) * 8) & 0xFF;
|
||||||
case AMICReg::Floppy_DMA_Ctrl:
|
case AMICReg::Floppy_DMA_Ctrl:
|
||||||
return this->floppy_dma_cs;
|
return this->floppy_dma->read_stat();
|
||||||
default:
|
default:
|
||||||
LOG_F(WARNING, "Unknown AMIC register read, offset=%x", offset);
|
LOG_F(WARNING, "Unknown AMIC register read, offset=%x", offset);
|
||||||
}
|
}
|
||||||
@@ -319,19 +321,14 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
|||||||
SET_SIZE_BYTE(this->floppy_byte_cnt, offset, value);
|
SET_SIZE_BYTE(this->floppy_byte_cnt, offset, value);
|
||||||
break;
|
break;
|
||||||
case AMICReg::Floppy_DMA_Ctrl:
|
case AMICReg::Floppy_DMA_Ctrl:
|
||||||
LOG_F(INFO, "AMIC SWIM3 DMA Ctrl updated, val=%x", value);
|
if (value & 1) { // RST bit set?
|
||||||
// copy over DIR and IE bits
|
this->floppy_addr_ptr = this->dma_base + 0x15000;
|
||||||
this->floppy_dma_cs = (floppy_dma_cs & 0x83) | (value & 0x48);
|
this->floppy_dma->reset(this->floppy_addr_ptr);
|
||||||
if (value & 1) {
|
|
||||||
this->reset_floppy_dma();
|
|
||||||
} else {
|
|
||||||
// copy over RUN bit
|
|
||||||
this->floppy_dma_cs = (floppy_dma_cs & 0xC8) | (value & 2);
|
|
||||||
// clear interrupt flag if requested
|
|
||||||
if (value & 0x80) {
|
|
||||||
this->floppy_dma_cs &= 0x7F;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (value & 2) { // RUN bit set?
|
||||||
|
this->floppy_dma->reinit(this->floppy_addr_ptr, this->floppy_byte_cnt);
|
||||||
|
}
|
||||||
|
this->floppy_dma->write_ctrl(value);
|
||||||
break;
|
break;
|
||||||
case AMICReg::SCC_DMA_Xmt_A_Ctrl:
|
case AMICReg::SCC_DMA_Xmt_A_Ctrl:
|
||||||
LOG_F(INFO, "AMIC SCC Transmit Ch A DMA Ctrl updated, val=%x", value);
|
LOG_F(INFO, "AMIC SCC Transmit Ch A DMA Ctrl updated, val=%x", value);
|
||||||
@@ -414,18 +411,13 @@ void AMIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) {
|
|||||||
ABORT_F("AMIC: ack_dma_int() not implemented");
|
ABORT_F("AMIC: ack_dma_int() not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================== DMA related stuff =============================
|
// ============================ Sound DMA stuff ================================
|
||||||
AmicSndOutDma::AmicSndOutDma()
|
AmicSndOutDma::AmicSndOutDma()
|
||||||
{
|
{
|
||||||
this->dma_out_ctrl = 0;
|
this->dma_out_ctrl = 0;
|
||||||
this->enabled = false;
|
this->enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmicSndOutDma::is_active()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AmicSndOutDma::init(uint32_t buf_base, uint32_t buf_samples)
|
void AmicSndOutDma::init(uint32_t buf_base, uint32_t buf_samples)
|
||||||
{
|
{
|
||||||
this->out_buf0 = buf_base + AMIC_SND_BUF0_OFFS;
|
this->out_buf0 = buf_base + AMIC_SND_BUF0_OFFS;
|
||||||
@@ -490,10 +482,49 @@ DmaPullResult AmicSndOutDma::pull_data(uint32_t req_len, uint32_t *avail_len,
|
|||||||
return DmaPullResult::MoreData;
|
return DmaPullResult::MoreData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================== Floppy DMA stuff ==============================
|
// ============================ Floppy DMA stuff ===============================
|
||||||
void AMIC::reset_floppy_dma()
|
void AmicFloppyDma::reset(const uint32_t addr_ptr)
|
||||||
{
|
{
|
||||||
this->floppy_dma_cs &= 0x48; // clear interrupt flang, RUN and RST bits
|
this->stat &= 0x48; // clear interrupt flag, RUN and RST bits
|
||||||
this->floppy_addr_ptr = this->dma_base + 0x15000;
|
this->addr_ptr = addr_ptr;
|
||||||
this->floppy_byte_cnt = 0;
|
this->byte_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmicFloppyDma::reinit(const uint32_t addr_ptr, const uint16_t byte_cnt)
|
||||||
|
{
|
||||||
|
this->addr_ptr = addr_ptr;
|
||||||
|
this->byte_count = byte_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmicFloppyDma::write_ctrl(uint8_t value)
|
||||||
|
{
|
||||||
|
// copy over DIR, IE and RUN bits
|
||||||
|
this->stat = (this->stat & 0x81) | (value & 0x4A);
|
||||||
|
|
||||||
|
// clear interrupt flag if requested
|
||||||
|
if (value & 0x80) {
|
||||||
|
this->stat &= 0x7F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AmicFloppyDma::push_data(const char* src_ptr, int len)
|
||||||
|
{
|
||||||
|
len = std::min((int)this->byte_count, len);
|
||||||
|
|
||||||
|
uint8_t *p_data = mmu_get_dma_mem(this->addr_ptr, len);
|
||||||
|
std::memcpy(p_data, src_ptr, len);
|
||||||
|
|
||||||
|
this->addr_ptr += len;
|
||||||
|
this->byte_count -= len;
|
||||||
|
if (!this->byte_count) {
|
||||||
|
LOG_F(WARNING, "AMIC: DMA interrupts not implemented yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DmaPullResult AmicFloppyDma::pull_data(uint32_t req_len, uint32_t *avail_len,
|
||||||
|
uint8_t **p_data)
|
||||||
|
{
|
||||||
|
return DmaPullResult::NoMoreData;
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,6 @@ public:
|
|||||||
AmicSndOutDma();
|
AmicSndOutDma();
|
||||||
~AmicSndOutDma() = default;
|
~AmicSndOutDma() = default;
|
||||||
|
|
||||||
bool is_active();
|
|
||||||
void init(uint32_t buf_base, uint32_t buf_samples);
|
void init(uint32_t buf_base, uint32_t buf_samples);
|
||||||
void enable() { this->enabled = true; };
|
void enable() { this->enabled = true; };
|
||||||
void disable() { this->enabled = false; };
|
void disable() { this->enabled = false; };
|
||||||
@@ -82,6 +81,27 @@ private:
|
|||||||
uint32_t cur_buf_pos;
|
uint32_t cur_buf_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** AMIC-specific floppy DMA implementation. */
|
||||||
|
class AmicFloppyDma : public DmaBidirChannel {
|
||||||
|
public:
|
||||||
|
AmicFloppyDma() = default;
|
||||||
|
~AmicFloppyDma() = default;
|
||||||
|
|
||||||
|
void reinit(const uint32_t addr_ptr, const uint16_t byte_cnt);
|
||||||
|
void reset(const uint32_t addr_ptr);
|
||||||
|
void write_ctrl(const uint8_t value);
|
||||||
|
uint8_t read_stat() { return this->stat; };
|
||||||
|
|
||||||
|
int push_data(const char* src_ptr, int len);
|
||||||
|
DmaPullResult pull_data(uint32_t req_len, uint32_t *avail_len,
|
||||||
|
uint8_t **p_data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t addr_ptr;
|
||||||
|
uint16_t byte_count;
|
||||||
|
uint8_t stat;
|
||||||
|
};
|
||||||
|
|
||||||
// macro for byte wise updating of AMIC DMA address registers
|
// macro for byte wise updating of AMIC DMA address registers
|
||||||
#define SET_ADDR_BYTE(reg, offset, value) \
|
#define SET_ADDR_BYTE(reg, offset, value) \
|
||||||
mask = 0xFF000000UL >> (8 * ((offset) & 3)); \
|
mask = 0xFF000000UL >> (8 * ((offset) & 3)); \
|
||||||
@@ -180,7 +200,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void ack_via2_int(uint32_t irq_id, uint8_t irq_line_state);
|
void ack_via2_int(uint32_t irq_id, uint8_t irq_line_state);
|
||||||
void ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state);
|
void ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state);
|
||||||
void reset_floppy_dma();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t imm_snd_regs[4]; // temporary storage for sound control registers
|
uint8_t imm_snd_regs[4]; // temporary storage for sound control registers
|
||||||
@@ -192,7 +211,6 @@ private:
|
|||||||
// floppy DMA state
|
// floppy DMA state
|
||||||
uint32_t floppy_addr_ptr;
|
uint32_t floppy_addr_ptr;
|
||||||
uint16_t floppy_byte_cnt;
|
uint16_t floppy_byte_cnt;
|
||||||
uint8_t floppy_dma_cs; // floppy DMA control/status value
|
|
||||||
|
|
||||||
uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
||||||
|
|
||||||
@@ -214,6 +232,7 @@ private:
|
|||||||
std::unique_ptr<AwacDevicePdm> awacs;
|
std::unique_ptr<AwacDevicePdm> awacs;
|
||||||
|
|
||||||
std::unique_ptr<AmicSndOutDma> snd_out_dma;
|
std::unique_ptr<AmicSndOutDma> snd_out_dma;
|
||||||
|
std::unique_ptr<AmicFloppyDma> floppy_dma;
|
||||||
|
|
||||||
// on-board video
|
// on-board video
|
||||||
std::unique_ptr<DisplayID> disp_id;
|
std::unique_ptr<DisplayID> disp_id;
|
||||||
|
Reference in New Issue
Block a user