hpc3: Fixed up and re-enabled audio DMA. Gets SGI Indy driver its boot chime back. [Ryan Holtz]

This commit is contained in:
mooglyguy 2018-11-06 23:01:52 +01:00
parent 35d42f82f8
commit 489c6eaba0
3 changed files with 206 additions and 262 deletions

View File

@ -72,6 +72,7 @@ public:
, m_mainram(*this, "mainram") , m_mainram(*this, "mainram")
, m_mem_ctrl(*this, "memctrl") , m_mem_ctrl(*this, "memctrl")
, m_scsi_ctrl(*this, "wd33c93") , m_scsi_ctrl(*this, "wd33c93")
, m_dac(*this, "dac")
, m_newport(*this, "newport") , m_newport(*this, "newport")
, m_hal2(*this, HAL2_TAG) , m_hal2(*this, HAL2_TAG)
, m_hpc3(*this, HPC3_TAG) , m_hpc3(*this, HPC3_TAG)
@ -90,6 +91,9 @@ private:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override; virtual void machine_reset() override;
DECLARE_READ32_MEMBER(enet_r);
DECLARE_WRITE32_MEMBER(enet_w);
DECLARE_WRITE32_MEMBER(ip22_write_ram); DECLARE_WRITE32_MEMBER(ip22_write_ram);
void ip225015_map(address_map &map); void ip225015_map(address_map &map);
@ -105,6 +109,7 @@ private:
required_shared_ptr<uint32_t> m_mainram; required_shared_ptr<uint32_t> m_mainram;
required_device<sgi_mc_device> m_mem_ctrl; required_device<sgi_mc_device> m_mem_ctrl;
required_device<wd33c93_device> m_scsi_ctrl; required_device<wd33c93_device> m_scsi_ctrl;
required_device<dac_16bit_r2r_twos_complement_device> m_dac;
required_device<newport_video_device> m_newport; required_device<newport_video_device> m_newport;
required_device<hal2_device> m_hal2; required_device<hal2_device> m_hal2;
required_device<hpc3_device> m_hpc3; required_device<hpc3_device> m_hpc3;
@ -134,6 +139,29 @@ inline void ATTR_PRINTF(3,4) ip22_state::verboselog(int n_level, const char *s_f
} }
} }
READ32_MEMBER(ip22_state::enet_r)
{
switch (offset)
{
case 0x000/4:
logerror("%s: enet_r: Read MAC Address bytes 0-3, 0x80675309 & %08x\n", machine().describe_context(), mem_mask);
return 0x80675309;
default:
logerror("%s: enet_r: Read Unknown Register %08x & %08x\n", machine().describe_context(), 0x1fbd4000 + (offset << 2), mem_mask);
return 0;
}
}
WRITE32_MEMBER(ip22_state::enet_w)
{
switch (offset)
{
default:
logerror("%s: enet_w: Write Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x1fbd4000 + (offset << 2), data, mem_mask);
break;
}
}
// a bit hackish, but makes the memory detection work properly and allows a big cleanup of the mapping // a bit hackish, but makes the memory detection work properly and allows a big cleanup of the mapping
WRITE32_MEMBER(ip22_state::ip22_write_ram) WRITE32_MEMBER(ip22_state::ip22_write_ram)
{ {
@ -164,6 +192,7 @@ void ip22_state::ip225015_map(address_map &map)
map(0x1fbc0000, 0x1fbc7fff).rw(m_hpc3, FUNC(hpc3_device::hd0_r), FUNC(hpc3_device::hd0_w)); map(0x1fbc0000, 0x1fbc7fff).rw(m_hpc3, FUNC(hpc3_device::hd0_r), FUNC(hpc3_device::hd0_w));
map(0x1fbc8000, 0x1fbcffff).rw(m_hpc3, FUNC(hpc3_device::unkpbus0_r), FUNC(hpc3_device::unkpbus0_w)).share("unkpbus0"); map(0x1fbc8000, 0x1fbcffff).rw(m_hpc3, FUNC(hpc3_device::unkpbus0_r), FUNC(hpc3_device::unkpbus0_w)).share("unkpbus0");
map(0x1fb80000, 0x1fb8ffff).rw(m_hpc3, FUNC(hpc3_device::pbusdma_r), FUNC(hpc3_device::pbusdma_w)); map(0x1fb80000, 0x1fb8ffff).rw(m_hpc3, FUNC(hpc3_device::pbusdma_r), FUNC(hpc3_device::pbusdma_w));
map(0x1fbd4000, 0x1fbd44ff).rw(FUNC(ip22_state::enet_r), FUNC(ip22_state::enet_w));
map(0x1fbd8000, 0x1fbd83ff).rw(m_hal2, FUNC(hal2_device::read), FUNC(hal2_device::write)); map(0x1fbd8000, 0x1fbd83ff).rw(m_hal2, FUNC(hal2_device::read), FUNC(hal2_device::write));
map(0x1fbd8400, 0x1fbd87ff).ram(); /* hack */ map(0x1fbd8400, 0x1fbd87ff).ram(); /* hack */
map(0x1fbd9000, 0x1fbd93ff).rw(m_hpc3, FUNC(hpc3_device::pbus4_r), FUNC(hpc3_device::pbus4_w)); map(0x1fbd9000, 0x1fbd93ff).rw(m_hpc3, FUNC(hpc3_device::pbus4_r), FUNC(hpc3_device::pbus4_w));
@ -230,9 +259,9 @@ void ip22_state::ip225015(machine_config &config)
SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right(); SPEAKER(config, "rspeaker").front_right();
dac_16bit_r2r_twos_complement_device &dac(DAC_16BIT_R2R_TWOS_COMPLEMENT(config, "dac", 0)); DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac, 0);
dac.add_route(ALL_OUTPUTS, "lspeaker", 0.25); m_dac->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
dac.add_route(ALL_OUTPUTS, "rspeaker", 0.25); m_dac->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
voltage_regulator_device &vreg = VOLTAGE_REGULATOR(config, "vref"); voltage_regulator_device &vreg = VOLTAGE_REGULATOR(config, "vref");
vreg.set_output(5.0); vreg.set_output(5.0);
@ -250,7 +279,7 @@ void ip22_state::ip225015(machine_config &config)
SGI_HAL2(config, m_hal2); SGI_HAL2(config, m_hal2);
SGI_IOC2_GUINNESS(config, m_ioc2, m_maincpu); SGI_IOC2_GUINNESS(config, m_ioc2, m_maincpu);
SGI_HPC3(config, m_hpc3, m_maincpu, m_scsi_ctrl, m_ioc2); SGI_HPC3(config, m_hpc3, m_maincpu, m_scsi_ctrl, m_ioc2, m_dac);
DS1386_8K(config, m_rtc, 32768); DS1386_8K(config, m_rtc, 32768);
MACHINE_CONFIG_END MACHINE_CONFIG_END

View File

@ -16,6 +16,7 @@ hpc3_device::hpc3_device(const machine_config &mconfig, const char *tag, device_
, m_maincpu(*this, finder_base::DUMMY_TAG) , m_maincpu(*this, finder_base::DUMMY_TAG)
, m_wd33c93(*this, finder_base::DUMMY_TAG) , m_wd33c93(*this, finder_base::DUMMY_TAG)
, m_ioc2(*this, finder_base::DUMMY_TAG) , m_ioc2(*this, finder_base::DUMMY_TAG)
, m_dac(*this, finder_base::DUMMY_TAG)
, m_mainram(*this, ":mainram") , m_mainram(*this, ":mainram")
, m_unkpbus0(*this, ":unkpbus0") , m_unkpbus0(*this, ":unkpbus0")
{ {
@ -38,6 +39,8 @@ inline void ATTR_PRINTF(3,4) hpc3_device::verboselog(int n_level, const char *s_
void hpc3_device::device_start() void hpc3_device::device_start()
{ {
m_pbus_dma_timer = timer_alloc(TIMER_PBUS_DMA);
m_pbus_dma_timer->adjust(attotime::never);
} }
void hpc3_device::device_reset() void hpc3_device::device_reset()
@ -45,13 +48,14 @@ void hpc3_device::device_reset()
m_enetr_nbdp = 0x80000000; m_enetr_nbdp = 0x80000000;
m_enetr_cbp = 0x80000000; m_enetr_cbp = 0x80000000;
m_pbus_dma.m_active = 0; m_pbus_dma.m_active = 0;
m_pbus_dma_timer->adjust(attotime::never);
} }
void hpc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) void hpc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
switch (id) switch (id)
{ {
case TIMER_DMA: case TIMER_PBUS_DMA:
do_dma(ptr, param); do_dma(ptr, param);
break; break;
default: default:
@ -61,26 +65,31 @@ void hpc3_device::device_timer(emu_timer &timer, device_timer_id id, int param,
TIMER_CALLBACK_MEMBER(hpc3_device::do_dma) TIMER_CALLBACK_MEMBER(hpc3_device::do_dma)
{ {
timer_set(attotime::never, TIMER_DMA); m_pbus_dma_timer->adjust(attotime::never);
#if 0
if (m_pbus_dma.m_active) if (m_pbus_dma.m_active)
{ {
uint16_t temp16 = ( m_mainram[(m_pbus_dma.m_cur_ptr - 0x08000000)/4] & 0xffff0000 ) >> 16; address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t temp16 = space.read_dword(m_pbus_dma.m_cur_ptr) >> 16;
int16_t stemp16 = (int16_t)((temp16 >> 8) | (temp16 << 8)); int16_t stemp16 = (int16_t)((temp16 >> 8) | (temp16 << 8));
m_dac->write_signed16(stemp16); m_dac->write(stemp16);
m_pbus_dma.m_cur_ptr += 4; m_pbus_dma.m_cur_ptr += 4;
m_pbus_dma.m_words_left -= 4; m_pbus_dma.m_words_left -= 4;
if (m_pbus_dma.m_words_left == 0) if (m_pbus_dma.m_words_left == 0)
{ {
if (m_pbus_dma.m_next_ptr != 0) if (m_pbus_dma.m_next_ptr != 0)
{ {
m_pbus_dma.m_desc_ptr = m_pbus_dma.m_next_ptr; m_pbus_dma.m_desc_ptr = m_pbus_dma.m_next_ptr;
m_pbus_dma.m_cur_ptr = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4]; logerror("Next PBUS_DMA_DescPtr = %08x\n", m_pbus_dma.m_desc_ptr); fflush(stdout);
m_pbus_dma.m_words_left = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4+1]; m_pbus_dma.m_cur_ptr = space.read_dword(m_pbus_dma.m_desc_ptr);
m_pbus_dma.m_next_ptr = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4+2]; m_pbus_dma.m_words_left = space.read_dword(m_pbus_dma.m_desc_ptr + 4);
m_pbus_dma.m_next_ptr = space.read_dword(m_pbus_dma.m_desc_ptr + 8);
logerror("Next PBUS_DMA_CurPtr = %08x\n", m_pbus_dma.m_cur_ptr); fflush(stdout);
logerror("Next PBUS_DMA_WordsLeft = %08x\n", m_pbus_dma.m_words_left); fflush(stdout);
logerror("Next PBUS_DMA_NextPtr = %08x\n", m_pbus_dma.m_next_ptr); fflush(stdout);
} }
else else
{ {
@ -88,9 +97,8 @@ TIMER_CALLBACK_MEMBER(hpc3_device::do_dma)
return; return;
} }
} }
timer_set(attotime::from_hz(44100), TIMER_DMA); m_pbus_dma_timer->adjust(attotime::from_hz(44100));
} }
#endif
} }
READ32_MEMBER(hpc3_device::hd_enet_r) READ32_MEMBER(hpc3_device::hd_enet_r)
@ -98,19 +106,19 @@ READ32_MEMBER(hpc3_device::hd_enet_r)
switch (offset) switch (offset)
{ {
case 0x0004/4: case 0x0004/4:
//verboselog((machine, 0, "HPC3 SCSI0DESC Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, m_scsi0_desc ); //verboselog(machine, 0, "HPC3 SCSI0DESC Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, m_scsi0_desc);
return m_scsi0_desc; return m_scsi0_desc;
case 0x1004/4: case 0x1004/4:
//verboselog((machine, 0, "HPC3 SCSI0DMACTRL Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, m_scsi0_dma_ctrl ); //verboselog(machine, 0, "HPC3 SCSI0DMACTRL Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, m_scsi0_dma_ctrl);
return m_scsi0_dma_ctrl; return m_scsi0_dma_ctrl;
case 0x4000/4: case 0x4000/4:
//verboselog((machine, 2, "HPC3 ENETR CBP Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, m_enetr_nbdp ); //verboselog(machine, 2, "HPC3 ENETR CBP Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, m_enetr_nbdp);
return m_enetr_cbp; return m_enetr_cbp;
case 0x4004/4: case 0x4004/4:
//verboselog((machine, 2, "HPC3 ENETR NBDP Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, m_enetr_nbdp ); //verboselog(machine, 2, "HPC3 ENETR NBDP Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, m_enetr_nbdp);
return m_enetr_nbdp; return m_enetr_nbdp;
default: default:
//verboselog((machine, 0, "Unknown HPC3 ENET/HDx Read: %08x (%08x)\n", 0x1fb90000 + ( offset << 2 ), mem_mask ); //verboselog(machine, 0, "Unknown HPC3 ENET/HDx Read: %08x (%08x)\n", 0x1fb90000 + (offset << 2), mem_mask);
return 0; return 0;
} }
} }
@ -120,23 +128,23 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w)
switch (offset) switch (offset)
{ {
case 0x0004/4: case 0x0004/4:
//verboselog((machine, 2, "HPC3 SCSI0DESC Write: %08x\n", data ); //verboselog(machine, 2, "HPC3 SCSI0DESC Write: %08x\n", data);
m_scsi0_desc = data; m_scsi0_desc = data;
break; break;
case 0x1004/4: case 0x1004/4:
//verboselog((machine, 2, "HPC3 SCSI0DMACTRL Write: %08x\n", data ); //verboselog(machine, 2, "HPC3 SCSI0DMACTRL Write: %08x\n", data);
m_scsi0_dma_ctrl = data; m_scsi0_dma_ctrl = data;
break; break;
case 0x4000/4: case 0x4000/4:
//verboselog((machine, 2, "HPC3 ENETR CBP Write: %08x\n", data ); //verboselog(machine, 2, "HPC3 ENETR CBP Write: %08x\n", data);
m_enetr_cbp = data; m_enetr_cbp = data;
break; break;
case 0x4004/4: case 0x4004/4:
//verboselog((machine, 2, "HPC3 ENETR NBDP Write: %08x\n", data ); //verboselog(machine, 2, "HPC3 ENETR NBDP Write: %08x\n", data);
m_enetr_nbdp = data; m_enetr_nbdp = data;
break; break;
default: default:
//verboselog((machine, 0, "Unknown HPC3 ENET/HDx write: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2 ), mem_mask, data ); //verboselog(machine, 0, "Unknown HPC3 ENET/HDx write: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, data);
break; break;
} }
} }
@ -147,7 +155,7 @@ READ32_MEMBER(hpc3_device::hd0_r)
{ {
case 0x0000/4: case 0x0000/4:
case 0x4000/4: case 0x4000/4:
// //verboselog((machine, 2, "HPC3 HD0 Status Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, nHPC3_hd0_regs[0x17] ); // //verboselog(machine, 2, "HPC3 HD0 Status Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, nHPC3_hd0_regs[0x17]);
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
{ {
return m_wd33c93->read(space, 0); return m_wd33c93->read(space, 0);
@ -158,7 +166,7 @@ READ32_MEMBER(hpc3_device::hd0_r)
} }
case 0x0004/4: case 0x0004/4:
case 0x4004/4: case 0x4004/4:
// //verboselog((machine, 2, "HPC3 HD0 Register Read: %08x (%08x): %08x\n", 0x1fb90000 + ( offset << 2), mem_mask, nHPC3_hd0_regs[nHPC3_hd0_register] ); // //verboselog(machine, 2, "HPC3 HD0 Register Read: %08x (%08x): %08x\n", 0x1fb90000 + (offset << 2), mem_mask, nHPC3_hd0_regs[nHPC3_hd0_register]);
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
{ {
return m_wd33c93->read(space, 1); return m_wd33c93->read(space, 1);
@ -168,7 +176,7 @@ READ32_MEMBER(hpc3_device::hd0_r)
return 0; return 0;
} }
default: default:
//verboselog((machine, 0, "Unknown HPC3 HD0 Read: %08x (%08x) [%x] PC=%x\n", 0x1fbc0000 + ( offset << 2 ), mem_mask, offset, m_maincpu->pc() ); //verboselog(machine, 0, "Unknown HPC3 HD0 Read: %08x (%08x) [%x] PC=%x\n", 0x1fbc0000 + (offset << 2), mem_mask, offset, m_maincpu->pc());
return 0; return 0;
} }
} }
@ -179,7 +187,7 @@ WRITE32_MEMBER(hpc3_device::hd0_w)
{ {
case 0x0000/4: case 0x0000/4:
case 0x4000/4: case 0x4000/4:
// //verboselog((machine, 2, "HPC3 HD0 Register Select Write: %08x\n", data ); // //verboselog(machine, 2, "HPC3 HD0 Register Select Write: %08x\n", data);
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
{ {
m_wd33c93->write(space, 0, data & 0x000000ff); m_wd33c93->write(space, 0, data & 0x000000ff);
@ -187,14 +195,14 @@ WRITE32_MEMBER(hpc3_device::hd0_w)
break; break;
case 0x0004/4: case 0x0004/4:
case 0x4004/4: case 0x4004/4:
// //verboselog((machine, 2, "HPC3 HD0 Register %d Write: %08x\n", nHPC3_hd0_register, data ); // //verboselog(machine, 2, "HPC3 HD0 Register %d Write: %08x\n", nHPC3_hd0_register, data);
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
{ {
m_wd33c93->write(space, 1, data & 0x000000ff); m_wd33c93->write(space, 1, data & 0x000000ff);
} }
break; break;
default: default:
//verboselog((machine, 0, "Unknown HPC3 HD0 Write: %08x (%08x): %08x\n", 0x1fbc0000 + ( offset << 2 ), mem_mask, data ); //verboselog(machine, 0, "Unknown HPC3 HD0 Write: %08x (%08x): %08x\n", 0x1fbc0000 + (offset << 2), mem_mask, data);
break; break;
} }
} }
@ -205,16 +213,16 @@ READ32_MEMBER(hpc3_device::pbus4_r)
switch (offset) switch (offset)
{ {
case 0x0004/4: case 0x0004/4:
//verboselog((machine, 2, "HPC3 PBUS4 Unknown 0 Read: (%08x): %08x\n", mem_mask, m_unk0 ); //verboselog(machine, 2, "HPC3 PBUS4 Unknown 0 Read: (%08x): %08x\n", mem_mask, m_unk0);
return m_unk0; return m_unk0;
case 0x000c/4: case 0x000c/4:
//verboselog((machine, 2, "Interrupt Controller(?) Read: (%08x): %08x\n", mem_mask, m_ic_unk0 ); //verboselog(machine, 2, "Interrupt Controller(?) Read: (%08x): %08x\n", mem_mask, m_ic_unk0);
return m_ic_unk0; return m_ic_unk0;
case 0x0014/4: case 0x0014/4:
//verboselog((machine, 2, "HPC3 PBUS4 Unknown 1 Read: (%08x): %08x\n", mem_mask, m_unk1 ); //verboselog(machine, 2, "HPC3 PBUS4 Unknown 1 Read: (%08x): %08x\n", mem_mask, m_unk1);
return m_unk1; return m_unk1;
default: default:
//verboselog((machine, 0, "Unknown HPC3 PBUS4 Read: %08x (%08x)\n", 0x1fbd9000 + ( offset << 2 ), mem_mask ); //verboselog(machine, 0, "Unknown HPC3 PBUS4 Read: %08x (%08x)\n", 0x1fbd9000 + (offset << 2), mem_mask);
return 0; return 0;
} }
} }
@ -224,19 +232,19 @@ WRITE32_MEMBER(hpc3_device::pbus4_w)
switch (offset) switch (offset)
{ {
case 0x0004/4: case 0x0004/4:
//verboselog((machine, 2, "HPC3 PBUS4 Unknown 0 Write: %08x (%08x)\n", data, mem_mask ); //verboselog(machine, 2, "HPC3 PBUS4 Unknown 0 Write: %08x (%08x)\n", data, mem_mask);
m_unk0 = data; m_unk0 = data;
break; break;
case 0x000c/4: case 0x000c/4:
//verboselog((machine, 2, "Interrupt Controller(?) Write: (%08x): %08x\n", mem_mask, data ); //verboselog(machine, 2, "Interrupt Controller(?) Write: (%08x): %08x\n", mem_mask, data);
m_ic_unk0 = data; m_ic_unk0 = data;
break; break;
case 0x0014/4: case 0x0014/4:
//verboselog((machine, 2, "HPC3 PBUS4 Unknown 1 Write: %08x (%08x)\n", data, mem_mask ); //verboselog(machine, 2, "HPC3 PBUS4 Unknown 1 Write: %08x (%08x)\n", data, mem_mask);
m_unk1 = data; m_unk1 = data;
break; break;
default: default:
//verboselog((machine, 0, "Unknown HPC3 PBUS4 Write: %08x (%08x): %08x\n", 0x1fbd9000 + ( offset << 2 ), mem_mask, data ); //verboselog(machine, 0, "Unknown HPC3 PBUS4 Write: %08x (%08x): %08x\n", 0x1fbd9000 + (offset << 2), mem_mask, data);
break; break;
} }
} }
@ -244,7 +252,7 @@ WRITE32_MEMBER(hpc3_device::pbus4_w)
READ32_MEMBER(hpc3_device::pbusdma_r) READ32_MEMBER(hpc3_device::pbusdma_r)
{ {
//uint32_t channel = offset / (0x2000/4); //uint32_t channel = offset / (0x2000/4);
//verboselog((machine(), 0, "PBUS DMA Channel %d Read: 0x%08x (%08x)\n", channel, 0x1fb80000 + offset*4, mem_mask ); //verboselog(machine(), 0, "PBUS DMA Channel %d Read: 0x%08x (%08x)\n", channel, 0x1fb80000 + offset*4, mem_mask);
return 0; return 0;
} }
@ -255,75 +263,75 @@ WRITE32_MEMBER(hpc3_device::pbusdma_w)
switch (offset & 0x07ff) switch (offset & 0x07ff)
{ {
case 0x0000/4: case 0x0000/4:
//verboselog((machine, 0, "PBUS DMA Channel %d Buffer Pointer Write: 0x%08x\n", channel, data ); //verboselog(machine, 0, "PBUS DMA Channel %d Buffer Pointer Write: 0x%08x\n", channel, data);
return; return;
case 0x0004/4: case 0x0004/4:
//verboselog((machine, 0, "PBUS DMA Channel %d Descriptor Pointer Write: 0x%08x\n", channel, data ); //verboselog(machine, 0, "PBUS DMA Channel %d Descriptor Pointer Write: 0x%08x\n", channel, data);
if (channel == 1) if (channel == 1)
{ {
m_pbus_dma.m_desc_ptr = data; m_pbus_dma.m_desc_ptr = data;
m_pbus_dma.m_cur_ptr = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4]; logerror("PBUS_DMA_DescPtr = %08x\n", m_pbus_dma.m_desc_ptr); fflush(stdout);
m_pbus_dma.m_words_left = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4+1]; m_pbus_dma.m_cur_ptr = space.read_dword(m_pbus_dma.m_desc_ptr);
m_pbus_dma.m_next_ptr = m_mainram[(m_pbus_dma.m_desc_ptr - 0x08000000)/4+2]; m_pbus_dma.m_words_left = space.read_dword(m_pbus_dma.m_desc_ptr + 4);
//verboselog((machine, 0, "nPBUS_DMA_DescPtr = %08x\n", m_pbus_dma.m_desc_ptr ); m_pbus_dma.m_next_ptr = space.read_dword(m_pbus_dma.m_desc_ptr + 8);
//verboselog((machine, 0, "nPBUS_DMA_CurPtr = %08x\n", m_pbus_dma.m_cur_ptr ); logerror("PBUS_DMA_CurPtr = %08x\n", m_pbus_dma.m_cur_ptr); fflush(stdout);
//verboselog((machine, 0, "nPBUS_DMA_WordsLeft = %08x\n", m_pbus_dma.m_words_left ); logerror("PBUS_DMA_WordsLeft = %08x\n", m_pbus_dma.m_words_left); fflush(stdout);
//verboselog((machine, 0, "nPBUS_DMA_NextPtr = %08x\n", m_pbus_dma.m_next_ptr ); logerror("PBUS_DMA_NextPtr = %08x\n", m_pbus_dma.m_next_ptr); fflush(stdout);
} }
return; return;
case 0x1000/4: case 0x1000/4:
//verboselog((machine, 0, "PBUS DMA Channel %d Control Register Write: 0x%08x\n", channel, data ); logerror("PBUS DMA Channel %d Control Register Write: 0x%08x\n", channel, data);
if (data & PBUS_CTRL_ENDIAN) if (data & PBUS_CTRL_ENDIAN)
{ {
//verboselog((machine, 0, " Little Endian\n" ); logerror(" Little Endian\n");
} }
else else
{ {
//verboselog((machine, 0, " Big Endian\n" ); logerror(" Big Endian\n");
} }
if (data & PBUS_CTRL_RECV) if (data & PBUS_CTRL_RECV)
{ {
//verboselog((machine, 0, " RX DMA\n" ); logerror(" RX DMA\n");
} }
else else
{ {
//verboselog((machine, 0, " TX DMA\n" ); logerror(" TX DMA\n");
} }
if (data & PBUS_CTRL_FLUSH) if (data & PBUS_CTRL_FLUSH)
{ {
//verboselog((machine, 0, " Flush for RX\n" ); logerror(" Flush for RX\n");
} }
if (data & PBUS_CTRL_DMASTART) if (data & PBUS_CTRL_DMASTART)
{ {
//verboselog((machine, 0, " Start DMA\n" ); logerror(" Start DMA\n");
} }
if (data & PBUS_CTRL_LOAD_EN) if (data & PBUS_CTRL_LOAD_EN)
{ {
//verboselog((machine, 0, " Load Enable\n" ); logerror(" Load Enable\n");
} }
//verboselog((machine, 0, " High Water Mark: %04x bytes\n", ( data & PBUS_CTRL_HIGHWATER ) >> 8 ); logerror(" High Water Mark: %04x bytes\n", (data & PBUS_CTRL_HIGHWATER) >> 8);
//verboselog((machine, 0, " FIFO Begin: Row %04x\n", ( data & PBUS_CTRL_FIFO_BEG ) >> 16 ); logerror(" FIFO Begin: Row %04x\n", (data & PBUS_CTRL_FIFO_BEG) >> 16);
//verboselog((machine, 0, " FIFO End: Rowe %04x\n", ( data & PBUS_CTRL_FIFO_END ) >> 24 ); logerror(" FIFO End: Rowe %04x\n", (data & PBUS_CTRL_FIFO_END) >> 24);
if ((data & PBUS_CTRL_DMASTART) || (data & PBUS_CTRL_LOAD_EN)) if ((data & PBUS_CTRL_DMASTART) || (data & PBUS_CTRL_LOAD_EN))
{ {
timer_set(attotime::from_hz(44100), TIMER_DMA); m_pbus_dma_timer->adjust(attotime::from_hz(44100));
m_pbus_dma.m_active = 1; m_pbus_dma.m_active = 1;
} }
return; return;
} }
//verboselog((machine, 0, "Unknown PBUS DMA Channel %d Write: 0x%08x: 0x%08x (%08x)\n", channel, 0x1fb80000 + offset*4, data, mem_mask ); logerror("Unknown PBUS DMA Channel %d Write: 0x%08x: 0x%08x (%08x)\n", channel, 0x1fb80000 + offset*4, data, mem_mask);
} }
READ32_MEMBER(hpc3_device::unkpbus0_r) READ32_MEMBER(hpc3_device::unkpbus0_r)
{ {
return 0; return 0;
////verboselog((machine(), 0, "Unknown PBUS Read: 0x%08x (%08x)\n", 0x1fbc8000 + offset*4, mem_mask ); //logerror("Unknown PBUS Read: 0x%08x (%08x)\n", 0x1fbc8000 + offset*4, mem_mask);
//return m_unkpbus0[offset]; //return m_unkpbus0[offset];
} }
WRITE32_MEMBER(hpc3_device::unkpbus0_w) WRITE32_MEMBER(hpc3_device::unkpbus0_w)
{ {
////verboselog((machine(), 0, "Unknown PBUS Write: 0x%08x = 0x%08x (%08x)\n", 0x1fbc8000 + offset*4, data, mem_mask ); //logerror("Unknown PBUS Write: 0x%08x = 0x%08x (%08x)\n", 0x1fbc8000 + offset*4, data, mem_mask);
//COMBINE_DATA(&m_unkpbus0[offset]); //COMBINE_DATA(&m_unkpbus0[offset]);
} }
@ -337,6 +345,30 @@ void hpc3_device::dump_chain(address_space &space, uint32_t ch_base)
} }
} }
void hpc3_device::fetch_chain(address_space &space)
{
m_scsi0_addr = space.read_dword(m_scsi0_desc);
m_scsi0_flags = space.read_dword(m_scsi0_desc+4);
m_scsi0_byte_count = m_scsi0_flags & 0x3fff;
m_scsi0_next_addr = space.read_dword(m_scsi0_desc+8);
//logerror("Fetching chain from %08x: %08x %08x %08x (length %04x)\n", m_scsi0_desc, m_scsi0_addr, m_scsi0_flags, m_scsi0_next_addr, m_scsi0_byte_count);
}
bool hpc3_device::decrement_chain(address_space &space)
{
m_scsi0_byte_count--;
if (m_scsi0_byte_count == 0)
{
if (BIT(m_scsi0_flags, 31))
{
return false;
}
m_scsi0_desc = m_scsi0_next_addr;
fetch_chain(space);
}
return true;
}
WRITE_LINE_MEMBER(hpc3_device::scsi_irq) WRITE_LINE_MEMBER(hpc3_device::scsi_irq)
{ {
address_space &space = m_maincpu->space(AS_PROGRAM); address_space &space = m_maincpu->space(AS_PROGRAM);
@ -345,219 +377,95 @@ WRITE_LINE_MEMBER(hpc3_device::scsi_irq)
{ {
if (m_wd33c93->get_dma_count()) if (m_wd33c93->get_dma_count())
{ {
logerror("m_wd33c93->get_dma_count() is %d\n", m_wd33c93->get_dma_count() ); //logerror("m_wd33c93->get_dma_count() is %d\n", m_wd33c93->get_dma_count());
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE) if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE)
{ {
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_IRQ) if (m_scsi0_dma_ctrl & HPC3_DMACTRL_IRQ)
logerror("IP22: Unhandled SCSI DMA IRQ\n"); logerror("IP22: Unhandled SCSI DMA IRQ\n");
} }
bool big_endian = (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN);
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE) if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE)
{ {
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_DIR) if (m_scsi0_dma_ctrl & HPC3_DMACTRL_DIR)
{ {
// HPC3 DMA: host to device // HPC3 DMA: host to device
int words = (m_wd33c93->get_dma_count() + 3) / 4; int byte_count = m_wd33c93->get_dma_count();
//dump_chain(space, m_scsi0_desc);
fetch_chain(space);
uint32_t srcoffs = space.read_dword(m_scsi0_desc); //logerror("DMA to device: %d bytes @ %x\n", byte_count, m_scsi0_addr);
m_scsi0_desc += words * 4;
logerror("DMA to device: %d words @ %x\n", words, srcoffs); if (byte_count <= 512)
{
for (int i = 0; i < byte_count; i++)
{
m_dma_buffer[big_endian ? BYTE4_XOR_BE(i) : BYTE4_XOR_LE(i)] = space.read_byte(m_scsi0_addr+i);
if (!decrement_chain(space))
break;
}
dump_chain(space, m_scsi0_desc); m_wd33c93->dma_write_data(byte_count, m_dma_buffer);
}
if (words <= (512/4)) else
{ {
int dstoffs = 0; int dstoffs = 0;
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN) while (byte_count)
{ {
for (int i = 0; i < words; i++) int sub_count = std::min(512, byte_count);
for (int i = 0; i < sub_count; i++)
{ {
uint32_t tmpword = space.read_dword(srcoffs); m_dma_buffer[big_endian ? BYTE4_XOR_BE(dstoffs+i) : BYTE4_XOR_LE(dstoffs+i)] = space.read_byte(m_scsi0_addr);
m_dma_buffer[dstoffs+3] = (tmpword >> 24) & 0xff; m_scsi0_addr++;
m_dma_buffer[dstoffs+2] = (tmpword >> 16) & 0xff; if (!decrement_chain(space))
m_dma_buffer[dstoffs+1] = (tmpword >> 8) & 0xff; break;
m_dma_buffer[dstoffs] = tmpword & 0xff;
srcoffs += 4;
dstoffs += 4;
}
}
else
{
for (int i = 0; i < words; i++)
{
uint32_t tmpword = space.read_dword(srcoffs);
m_dma_buffer[dstoffs] = (tmpword >> 24) & 0xff;
m_dma_buffer[dstoffs+1] = (tmpword >> 16) & 0xff;
m_dma_buffer[dstoffs+2] = (tmpword >> 8) & 0xff;
m_dma_buffer[dstoffs+3] = tmpword & 0xff;
srcoffs += 4;
dstoffs += 4;
}
} }
m_wd33c93->dma_write_data(m_wd33c93->get_dma_count(), m_dma_buffer); m_wd33c93->dma_write_data(sub_count, m_dma_buffer);
}
else
{
while (words)
{
int twords = std::min(512/4, words);
m_scsi0_desc += twords*4;
int dstoffs = 0; byte_count -= sub_count;
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN)
{
for (int i = 0; i < twords; i++)
{
uint32_t tmpword = space.read_dword(srcoffs);
m_dma_buffer[dstoffs+3] = (tmpword >> 24) & 0xff;
m_dma_buffer[dstoffs+2] = (tmpword >> 16) & 0xff;
m_dma_buffer[dstoffs+1] = (tmpword >> 8) & 0xff;
m_dma_buffer[dstoffs] = tmpword & 0xff;
dstoffs += 4;
srcoffs += 4;
}
}
else
{
for (int i = 0; i < twords; i++)
{
uint32_t tmpword = space.read_dword(srcoffs);
m_dma_buffer[dstoffs] = (tmpword >> 24) & 0xff;
m_dma_buffer[dstoffs+1] = (tmpword >> 16) & 0xff;
m_dma_buffer[dstoffs+2] = (tmpword >> 8) & 0xff;
m_dma_buffer[dstoffs+3] = tmpword & 0xff;
dstoffs += 4;
srcoffs += 4;
}
}
m_wd33c93->dma_write_data(512, m_dma_buffer);
words -= (512/4);
} }
} }
// clear DMA on the controller too // clear DMA on the controller too
m_wd33c93->clear_dma(); m_wd33c93->clear_dma();
#if 0
uint32_t dptr, tmpword;
uint32_t bc = space.read_dword(m_scsi0_desc + 4);
uint32_t rptr = space.read_dword(m_scsi0_desc);
int length = bc & 0x3fff;
int xie = (bc & 0x20000000) ? 1 : 0;
int eox = (bc & 0x80000000) ? 1 : 0;
dump_chain(space, m_scsi0_desc);
logerror("%s DMA to device: length %x xie %d eox %d\n", machine().describe_context().c_str(), length, xie, eox);
if (length <= 0x4000)
{
dptr = 0;
while (length > 0)
{
tmpword = space.read_dword(rptr);
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN)
{
m_dma_buffer[dptr+3] = (tmpword>>24)&0xff;
m_dma_buffer[dptr+2] = (tmpword>>16)&0xff;
m_dma_buffer[dptr+1] = (tmpword>>8)&0xff;
m_dma_buffer[dptr] = tmpword&0xff;
}
else
{
m_dma_buffer[dptr] = (tmpword>>24)&0xff;
m_dma_buffer[dptr+1] = (tmpword>>16)&0xff;
m_dma_buffer[dptr+2] = (tmpword>>8)&0xff;
m_dma_buffer[dptr+3] = tmpword&0xff;
}
dptr += 4;
rptr += 4;
length -= 4;
}
length = space.read_dword(m_scsi0_desc+4) & 0x3fff;
m_wd33c93->write_data(length, m_dma_buffer);
// clear DMA on the controller too
m_wd33c93->clear_dma();
}
else
{
logerror("IP22: overly large host to device transfer, can't handle!\n");
}
#endif
} }
else else
{ {
// HPC3 DMA: device to host // HPC3 DMA: device to host
int words = (m_wd33c93->get_dma_count() + 3) / 4; int byte_count = m_wd33c93->get_dma_count();
//dump_chain(space, m_scsi0_desc);
uint32_t dstoffs = space.read_dword(m_scsi0_desc); fetch_chain(space);
// logerror("DMA from device: %d words @ %x\n", words, dstoffs); // logerror("DMA from device: %d words @ %x\n", words, dstoffs);
dump_chain(space, m_scsi0_desc); if (byte_count < 512)
{
m_wd33c93->dma_read_data(byte_count, m_dma_buffer);
if (words < (512/4)) for (int i = 0; i < byte_count; i++)
{ {
// one-shot space.write_byte(big_endian ? BYTE4_XOR_BE(m_scsi0_addr+i) : BYTE4_XOR_LE(m_scsi0_addr+i), m_dma_buffer[i]);
m_wd33c93->dma_read_data(m_wd33c93->get_dma_count(), m_dma_buffer); if (!decrement_chain(space))
break;
int srcoffs = 0;
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN)
{
for (int i = 0; i < words; i++)
{
uint32_t tmpword = m_dma_buffer[srcoffs+3]<<24 | m_dma_buffer[srcoffs+2]<<16 | m_dma_buffer[srcoffs+1]<<8 | m_dma_buffer[srcoffs];
space.write_dword(dstoffs, tmpword);
dstoffs += 4;
srcoffs += 4;
} }
} }
else else
{ {
for (int i = 0; i < words; i++) while (byte_count)
{ {
uint32_t tmpword = m_dma_buffer[srcoffs]<<24 | m_dma_buffer[srcoffs+1]<<16 | m_dma_buffer[srcoffs+2]<<8 | m_dma_buffer[srcoffs+3]; int sub_count = m_wd33c93->dma_read_data(512, m_dma_buffer);
space.write_dword(dstoffs, tmpword);
dstoffs += 4;
srcoffs += 4;
}
}
}
else
{
while (words)
{
int length = (m_wd33c93->dma_read_data(512, m_dma_buffer) + 3) / 4;
int srcoffs = 0; for (int i = 0; i < sub_count; i++)
if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN)
{ {
for (uint32_t i = 0; i < length; i++) space.write_byte(big_endian ? BYTE4_XOR_BE(m_scsi0_addr) : BYTE4_XOR_LE(m_scsi0_addr), m_dma_buffer[i]);
{ m_scsi0_addr++;
uint32_t tmpword = m_dma_buffer[srcoffs+3]<<24 | m_dma_buffer[srcoffs+2]<<16 | m_dma_buffer[srcoffs+1]<<8 | m_dma_buffer[srcoffs]; if (!decrement_chain(space))
space.write_dword(dstoffs, tmpword); break;
dstoffs += 4;
srcoffs += 4;
}
}
else
{
for (uint32_t i = 0; i < length; i++)
{
uint32_t tmpword = m_dma_buffer[srcoffs]<<24 | m_dma_buffer[srcoffs+1]<<16 | m_dma_buffer[srcoffs+2]<<8 | m_dma_buffer[srcoffs+3];
space.write_dword(dstoffs, tmpword);
dstoffs += 4;
srcoffs += 4;
}
} }
words -= (512/4); byte_count -= sub_count;
} }
} }

View File

@ -14,17 +14,19 @@
#include "cpu/mips/mips3.h" #include "cpu/mips/mips3.h"
#include "machine/ioc2.h" #include "machine/ioc2.h"
#include "machine/wd33c93.h" #include "machine/wd33c93.h"
#include "sound/dac.h"
class hpc3_device : public device_t class hpc3_device : public device_t
{ {
public: public:
template <typename T, typename U, typename V> template <typename T, typename U, typename V, typename W>
hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag, U &&scsi_tag, V &&ioc2_tag) hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag, U &&scsi_tag, V &&ioc2_tag, W &&dac_tag)
: hpc3_device(mconfig, tag, owner, (uint32_t)0) : hpc3_device(mconfig, tag, owner, (uint32_t)0)
{ {
m_maincpu.set_tag(std::forward<T>(cpu_tag)); m_maincpu.set_tag(std::forward<T>(cpu_tag));
m_wd33c93.set_tag(std::forward<U>(scsi_tag)); m_wd33c93.set_tag(std::forward<U>(scsi_tag));
m_ioc2.set_tag(std::forward<V>(ioc2_tag)); m_ioc2.set_tag(std::forward<V>(ioc2_tag));
m_dac.set_tag(std::forward<W>(dac_tag));
} }
hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -50,6 +52,10 @@ protected:
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
void dump_chain(address_space &space, uint32_t ch_base); void dump_chain(address_space &space, uint32_t ch_base);
void fetch_chain(address_space &space);
bool decrement_chain(address_space &space);
static const device_timer_id TIMER_PBUS_DMA = 0;
struct pbus_dma_t struct pbus_dma_t
{ {
@ -60,11 +66,6 @@ protected:
uint32_t m_words_left; uint32_t m_words_left;
}; };
enum
{
TIMER_DMA
};
enum enum
{ {
PBUS_CTRL_ENDIAN = 0x00000002, PBUS_CTRL_ENDIAN = 0x00000002,
@ -99,6 +100,7 @@ protected:
required_device<mips3_device> m_maincpu; required_device<mips3_device> m_maincpu;
required_device<wd33c93_device> m_wd33c93; required_device<wd33c93_device> m_wd33c93;
required_device<ioc2_device> m_ioc2; required_device<ioc2_device> m_ioc2;
required_device<dac_16bit_r2r_twos_complement_device> m_dac;
required_shared_ptr<uint32_t> m_mainram; required_shared_ptr<uint32_t> m_mainram;
required_shared_ptr<uint32_t> m_unkpbus0; required_shared_ptr<uint32_t> m_unkpbus0;
@ -108,8 +110,13 @@ protected:
uint32_t m_unk1; uint32_t m_unk1;
uint32_t m_ic_unk0; uint32_t m_ic_unk0;
uint32_t m_scsi0_desc; uint32_t m_scsi0_desc;
uint32_t m_scsi0_addr;
uint32_t m_scsi0_flags;
uint32_t m_scsi0_byte_count;
uint32_t m_scsi0_next_addr;
uint32_t m_scsi0_dma_ctrl; uint32_t m_scsi0_dma_ctrl;
pbus_dma_t m_pbus_dma; pbus_dma_t m_pbus_dma;
emu_timer *m_pbus_dma_timer;
uint8_t m_dma_buffer[4096]; uint8_t m_dma_buffer[4096];