mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-10-08 00:55:15 +00:00
amic: implement SCSI DMA.
This commit is contained in:
parent
a00b87790b
commit
c87fc10376
@ -53,6 +53,8 @@ AMIC::AMIC() : MMIODevice()
|
|||||||
|
|
||||||
// connect internal SCSI controller
|
// connect internal SCSI controller
|
||||||
this->scsi = dynamic_cast<Sc53C94*>(gMachineObj->get_comp_by_name("Sc53C94"));
|
this->scsi = dynamic_cast<Sc53C94*>(gMachineObj->get_comp_by_name("Sc53C94"));
|
||||||
|
this->scsi_dma = std::unique_ptr<AmicScsiDma> (new AmicScsiDma());
|
||||||
|
this->scsi->set_dma_channel(this->scsi_dma.get());
|
||||||
|
|
||||||
// connect serial HW
|
// connect serial HW
|
||||||
this->escc = dynamic_cast<EsccController*>(gMachineObj->get_comp_by_name("Escc"));
|
this->escc = dynamic_cast<EsccController*>(gMachineObj->get_comp_by_name("Escc"));
|
||||||
@ -170,7 +172,7 @@ uint32_t AMIC::read(uint32_t rgn_start, uint32_t offset, int size)
|
|||||||
case AMICReg::DMA_Base_Addr_3:
|
case AMICReg::DMA_Base_Addr_3:
|
||||||
return (this->dma_base >> (3 - (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->read_stat();
|
||||||
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:
|
||||||
@ -324,9 +326,24 @@ void AMIC::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
|
|||||||
case AMICReg::Enet_DMA_Xmt_Ctrl:
|
case AMICReg::Enet_DMA_Xmt_Ctrl:
|
||||||
LOG_F(INFO, "AMIC Ethernet Transmit DMA Ctrl updated, val=%x", value);
|
LOG_F(INFO, "AMIC Ethernet Transmit DMA Ctrl updated, val=%x", value);
|
||||||
break;
|
break;
|
||||||
|
case AMICReg::SCSI_DMA_Base_0:
|
||||||
|
case AMICReg::SCSI_DMA_Base_1:
|
||||||
|
case AMICReg::SCSI_DMA_Base_2:
|
||||||
|
case AMICReg::SCSI_DMA_Base_3:
|
||||||
|
SET_ADDR_BYTE(this->scsi_dma_base, offset, value);
|
||||||
|
this->scsi_dma_base &= 0xFFFFFFF8UL;
|
||||||
|
LOG_F(9, "AMIC: SCSI DMA base address set to 0x%X", this->scsi_dma_base);
|
||||||
|
break;
|
||||||
case AMICReg::SCSI_DMA_Ctrl:
|
case AMICReg::SCSI_DMA_Ctrl:
|
||||||
LOG_F(INFO, "AMIC SCSI DMA Ctrl updated, val=%x", value);
|
if (value & 1) { // RST bit set?
|
||||||
this->scsi_dma_cs = value;
|
this->scsi_addr_ptr = this->scsi_dma_base;
|
||||||
|
this->scsi_dma->reset(this->scsi_addr_ptr);
|
||||||
|
}
|
||||||
|
if (value & 2) { // RUN bit set?
|
||||||
|
this->scsi_dma->reinit(this->scsi_dma_base);
|
||||||
|
this->scsi->real_dma_xfer((value >> 6) & 1);
|
||||||
|
}
|
||||||
|
this->scsi_dma->write_ctrl(value);
|
||||||
break;
|
break;
|
||||||
case AMICReg::Enet_DMA_Rcv_Ctrl:
|
case AMICReg::Enet_DMA_Rcv_Ctrl:
|
||||||
LOG_F(INFO, "AMIC Ethernet Receive DMA Ctrl updated, val=%x", value);
|
LOG_F(INFO, "AMIC Ethernet Receive DMA Ctrl updated, val=%x", value);
|
||||||
@ -554,6 +571,50 @@ DmaPullResult AmicFloppyDma::pull_data(uint32_t req_len, uint32_t *avail_len,
|
|||||||
return DmaPullResult::NoMoreData;
|
return DmaPullResult::NoMoreData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================ SCSI DMA stuff ================================
|
||||||
|
void AmicScsiDma::reset(const uint32_t addr_ptr)
|
||||||
|
{
|
||||||
|
this->stat &= 0x48; // clear interrupt flag, RUN and RST bits
|
||||||
|
this->addr_ptr = addr_ptr;
|
||||||
|
this->byte_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmicScsiDma::reinit(const uint32_t addr_ptr)
|
||||||
|
{
|
||||||
|
this->addr_ptr = addr_ptr;
|
||||||
|
this->byte_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmicScsiDma::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 AmicScsiDma::push_data(const char* src_ptr, int len)
|
||||||
|
{
|
||||||
|
uint8_t *p_data = mmu_get_dma_mem(this->addr_ptr, len);
|
||||||
|
std::memcpy(p_data, src_ptr, len);
|
||||||
|
|
||||||
|
this->addr_ptr += len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DmaPullResult AmicScsiDma::pull_data(uint32_t req_len, uint32_t *avail_len,
|
||||||
|
uint8_t **p_data)
|
||||||
|
{
|
||||||
|
*p_data = mmu_get_dma_mem(this->addr_ptr, req_len);
|
||||||
|
this->addr_ptr += req_len;
|
||||||
|
*avail_len = req_len;
|
||||||
|
return DmaPullResult::MoreData;
|
||||||
|
}
|
||||||
|
|
||||||
static vector<string> Amic_Subdevices = {
|
static vector<string> Amic_Subdevices = {
|
||||||
"Sc53C94", "Escc", "Mace", "ViaCuda", "Swim3"
|
"Sc53C94", "Escc", "Mace", "ViaCuda", "Swim3"
|
||||||
};
|
};
|
||||||
|
@ -102,6 +102,27 @@ private:
|
|||||||
uint8_t stat;
|
uint8_t stat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** AMIC-specific SCSI DMA implementation. */
|
||||||
|
class AmicScsiDma : public DmaBidirChannel {
|
||||||
|
public:
|
||||||
|
AmicScsiDma() = default;
|
||||||
|
~AmicScsiDma() = default;
|
||||||
|
|
||||||
|
void reinit(const uint32_t addr_ptr);
|
||||||
|
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)); \
|
||||||
@ -164,9 +185,15 @@ enum AMICReg : uint32_t {
|
|||||||
DMA_Base_Addr_2 = 0x31002,
|
DMA_Base_Addr_2 = 0x31002,
|
||||||
DMA_Base_Addr_3 = 0x31003,
|
DMA_Base_Addr_3 = 0x31003,
|
||||||
Enet_DMA_Xmt_Ctrl = 0x31C20,
|
Enet_DMA_Xmt_Ctrl = 0x31C20,
|
||||||
SCSI_DMA_Ctrl = 0x32008,
|
|
||||||
Enet_DMA_Rcv_Ctrl = 0x32028,
|
Enet_DMA_Rcv_Ctrl = 0x32028,
|
||||||
|
|
||||||
|
// SCSI DMA registers
|
||||||
|
SCSI_DMA_Base_0 = 0x32000,
|
||||||
|
SCSI_DMA_Base_1 = 0x32001,
|
||||||
|
SCSI_DMA_Base_2 = 0x32002,
|
||||||
|
SCSI_DMA_Base_3 = 0x32003,
|
||||||
|
SCSI_DMA_Ctrl = 0x32008,
|
||||||
|
|
||||||
// Floppy (SWIM3) DMA registers
|
// Floppy (SWIM3) DMA registers
|
||||||
Floppy_Addr_Ptr_0 = 0x32060,
|
Floppy_Addr_Ptr_0 = 0x32060,
|
||||||
Floppy_Addr_Ptr_1 = 0x32061,
|
Floppy_Addr_Ptr_1 = 0x32061,
|
||||||
@ -214,15 +241,19 @@ private:
|
|||||||
|
|
||||||
uint8_t emmo_pin; // EMMO aka factory tester pin status, active low
|
uint8_t emmo_pin; // EMMO aka factory tester pin status, active low
|
||||||
|
|
||||||
uint32_t dma_base = 0; // DMA physical base address
|
uint32_t dma_base = 0; // DMA physical base address
|
||||||
uint16_t snd_buf_size = 0; // sound buffer size in bytes
|
uint32_t scsi_dma_base = 0; // physical base address for SCSI DMA
|
||||||
uint8_t snd_out_ctrl = 0;
|
uint16_t snd_buf_size = 0; // sound buffer size in bytes
|
||||||
|
uint8_t snd_out_ctrl = 0;
|
||||||
|
|
||||||
// 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 scsi_dma_cs = 0; // SCSI DMA control/status register value
|
// SCSI DMA state
|
||||||
|
uint32_t scsi_addr_ptr;
|
||||||
|
|
||||||
|
//uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
||||||
|
|
||||||
// interrupt state
|
// interrupt state
|
||||||
uint8_t int_ctrl = 0;
|
uint8_t int_ctrl = 0;
|
||||||
@ -245,6 +276,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;
|
std::unique_ptr<AmicFloppyDma> floppy_dma;
|
||||||
|
std::unique_ptr<AmicScsiDma> scsi_dma;
|
||||||
|
|
||||||
// on-board video
|
// on-board video
|
||||||
std::unique_ptr<DisplayID> disp_id;
|
std::unique_ptr<DisplayID> disp_id;
|
||||||
|
Loading…
Reference in New Issue
Block a user