-newport: Added Display Control Bus timeout. Prevents Presenter board from being erroneously detected. [Ryan Holtz]

-sgi_mc: Fixed VDMA TLB which caused corrupt bitmap transfers. [Ryan Holtz]
This commit is contained in:
mooglyguy 2019-05-27 22:53:54 +02:00 committed by MooglyGuy
parent bef9f293b6
commit a7e4e9b676
4 changed files with 202 additions and 97 deletions

View File

@ -40,7 +40,7 @@
#define LOG_REJECTS (1 << 8)
#define LOG_ALL (LOG_UNKNOWN | LOG_VC2 | LOG_CMAP0 | LOG_CMAP1 | LOG_XMAP0 | LOG_XMAP1 | LOG_REX3 | LOG_COMMANDS | LOG_REJECTS)
#define VERBOSE (0)
#define VERBOSE (0)//(LOG_REX3 | LOG_COMMANDS)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(GIO_XL8, gio_xl8_device, "gio_xl8", "SGI 8-bit XL board")
@ -79,6 +79,8 @@ void newport_base_device::device_start()
m_cid = make_unique_clear<uint32_t[]>((1280+64) * (1024+64));
m_vt_table = make_unique_clear<uint32_t[]>(2048 * 2048);
m_dcb_timeout_timer = timer_alloc(DCB_TIMEOUT);
save_pointer(NAME(m_rgbci), (1280+64) * (1024+64));
save_pointer(NAME(m_olay), (1280+64) * (1024+64));
save_pointer(NAME(m_pup), (1280+64) * (1024+64));
@ -283,6 +285,14 @@ void newport_base_device::stop_logging()
}
#endif
void newport_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
if (id == DCB_TIMEOUT)
{
m_rex3.m_status &= ~STATUS_BACKBUSY;
}
}
uint8_t newport_base_device::get_cursor_pixel(int x, int y)
{
if (x < 0 || y < 0)
@ -1302,7 +1312,7 @@ WRITE_LINE_MEMBER(newport_base_device::vblank_w)
{
if (BIT(m_vc2.m_display_ctrl, 0))
{
m_rex3.m_status |= 0x20;
m_rex3.m_status |= STATUS_VRINT;
m_gio->get_hpc3()->raise_local_irq(1, ioc2_device::INT3_LOCAL1_RETRACE);
}
}
@ -1612,21 +1622,36 @@ READ64_MEMBER(newport_base_device::rex3_r)
{
switch (m_rex3.m_dcb_slave_select)
{
case 0x00:
case DCB_ADDR_VC2:
ret |= (uint64_t)vc2_read() << 32;
break;
case 0x02:
case DCB_ADDR_CMAP0:
ret |= (uint64_t)cmap0_read() << 32;
break;
case 0x03:
case DCB_ADDR_CMAP1:
ret |= (uint64_t)cmap1_read() << 32;
break;
case 0x05:
case DCB_ADDR_XMAP0:
ret |= (uint64_t)xmap0_read() << 32;
break;
case 0x06:
case DCB_ADDR_XMAP1:
ret |= (uint64_t)xmap1_read() << 32;
break;
case DCB_ADDR_RAMDAC:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Read from RAMDAC (not yet implemented)\n");
break;
case DCB_ADDR_CC1:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Read from CC1 (not yet implemented)\n");
break;
case DCB_ADDR_AB1:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Read from AB1 (not yet implemented)\n");
break;
case DCB_ADDR_PCD:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Read from PCD (not yet implemented)\n");
// Presenter not connected; simulate a bus timeout
m_rex3.m_status |= STATUS_BACKBUSY;
m_dcb_timeout_timer->adjust(attotime::from_msec(1));
break;
default:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Read: %08x\n", m_rex3.m_dcb_data_msw);
ret |= (uint64_t)m_rex3.m_dcb_data_msw << 32;
@ -1723,7 +1748,7 @@ READ64_MEMBER(newport_base_device::rex3_r)
{
LOGMASKED(LOG_REX3, "REX3 Status Read: %08x\n", m_rex3.m_status);
uint32_t old_status = m_rex3.m_status;
m_rex3.m_status = 0;
m_rex3.m_status &= ~STATUS_VRINT;
m_gio->get_hpc3()->lower_local_irq(1, ioc2_device::INT3_LOCAL1_RETRACE);
ret |= (uint64_t)(old_status | 3) << 32;
}
@ -3727,22 +3752,44 @@ WRITE64_MEMBER(newport_base_device::rex3_w)
m_rex3.m_dcb_data_msw = data32;
switch (m_rex3.m_dcb_slave_select)
{
case 0x00:
case DCB_ADDR_VC2:
vc2_write(data32);
break;
case 0x01:
case DCB_ADDR_CMAP01:
cmap0_write(data32);
//cmap1_write(data32);
break;
case DCB_ADDR_CMAP0:
cmap0_write(data32);
break;
case 0x04:
case DCB_ADDR_CMAP1:
//cmap1_write(data32);
break;
case DCB_ADDR_XMAP01:
xmap0_write(data32);
xmap1_write(data32);
break;
case 0x05:
case DCB_ADDR_XMAP0:
xmap0_write(data32);
break;
case 0x06:
case DCB_ADDR_XMAP1:
xmap1_write(data32);
break;
case DCB_ADDR_RAMDAC:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Write to RAMDAC (not yet implemented): %08x\n", data32);
break;
case DCB_ADDR_CC1:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Write to CC1 (not yet implemented): %08x\n", data32);
break;
case DCB_ADDR_AB1:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Write to AB1 (not yet implemented): %08x\n", data32);
break;
case DCB_ADDR_PCD:
LOGMASKED(LOG_REX3, "REX3 Display Control Bus Data MSW Write to PCD (not yet implemented): %08x\n", data32);
// Presenter not connected; simulate a bus timeout
m_rex3.m_status |= STATUS_BACKBUSY;
m_dcb_timeout_timer->adjust(attotime::from_msec(1));
break;
default:
LOGMASKED(LOG_REX3 | LOG_UNKNOWN, "REX3 Display Control Bus Data MSW Write: %08x\n", data32);
break;

View File

@ -32,6 +32,7 @@ public:
DECLARE_WRITE_LINE_MEMBER(vblank_w);
protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual void device_add_mconfig(machine_config &config) override;
virtual uint32_t palette_entries() const override { return 0x2000; }
virtual void device_start() override;
@ -39,6 +40,8 @@ protected:
void mem_map(address_map &map) override;
static constexpr device_timer_id DCB_TIMEOUT = 0;
enum
{
DCR_CURSOR_FUNC_ENABLE_BIT = 4,
@ -53,6 +56,35 @@ protected:
DCR_CURSOR_SIZE_64 = 1
};
enum
{
DCB_ADDR_VC2,
DCB_ADDR_CMAP01,
DCB_ADDR_CMAP0,
DCB_ADDR_CMAP1,
DCB_ADDR_XMAP01,
DCB_ADDR_XMAP0,
DCB_ADDR_XMAP1,
DCB_ADDR_RAMDAC,
DCB_ADDR_CC1,
DCB_ADDR_AB1,
DCB_ADDR_PCD = 12
};
enum
{
STATUS_GFXBUSY = (1 << 3),
STATUS_BACKBUSY = (1 << 4),
STATUS_VRINT = (1 << 5),
STATUS_VIDEOINT = (1 << 6),
STATUS_GFIFOLEVEL_SHIFT = 7,
STATUS_GFIFOLEVEL_MASK = (0x3f << STATUS_GFIFOLEVEL_SHIFT),
STATUS_BFIFOLEVEL_SHIFT = 13,
STATUS_BFIFOLEVEL_MASK = (0x1f << STATUS_BFIFOLEVEL_SHIFT),
STATUS_BFIFO_INT = 18,
STATUS_GFIFO_INT = 19
};
struct vc2_t
{
uint16_t m_vid_entry;
@ -268,6 +300,7 @@ protected:
std::unique_ptr<uint32_t[]> m_vt_table;
cmap_t m_cmap0;
uint32_t m_global_mask;
emu_timer *m_dcb_timeout_timer;
int m_readout_x0;
int m_readout_y0;

View File

@ -23,7 +23,7 @@
#define LOG_DMA (1 << 8)
#define LOG_DEFAULT (LOG_READS | LOG_WRITES | LOG_RPSS | LOG_WATCHDOG | LOG_UNKNOWN)
#define VERBOSE (0)
#define VERBOSE (LOG_DMA)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(SGI_MC, sgi_mc_device, "sgi_mc", "SGI Memory Controller")
@ -196,9 +196,9 @@ uint32_t sgi_mc_device::dma_translate(uint32_t address)
{
for (int entry = 0; entry < 4; entry++)
{
if ((address & 0xffe00000) == (m_dma_tlb_entry_hi[entry] & 0xffe00000))
if ((address & 0xffc00000) == (m_dma_tlb_entry_hi[entry] & 0xffc00000))
{
const uint32_t vpn_lo = (address & 0x001ff000) >> 12;
const uint32_t vpn_lo = (address & 0x003ff000) >> 12;
const uint32_t pte = m_space->read_dword(((m_dma_tlb_entry_lo[entry] & 0x003fffc0) << 6) + (vpn_lo << 2));
const uint32_t offset = address & 0xfff;
return ((pte & 0x03ffffc0) << 6) + offset;
@ -207,91 +207,103 @@ uint32_t sgi_mc_device::dma_translate(uint32_t address)
return 0;
}
void sgi_mc_device::dma_tick()
void sgi_mc_device::dma_immediate()
{
uint32_t addr = m_dma_mem_addr;
if (m_dma_control & (1 << 8))
{ // Enable virtual address translation
addr = dma_translate(addr);
}
if (m_dma_mode & (1 << 1))
{ // Graphics to host
if (m_dma_mode & (1 << 3))
{ // Fill mode
m_space->write_dword(addr, m_dma_gio64_addr);
m_dma_mem_addr += 4;
m_dma_count -= 4;
}
else
uint32_t memory_addr = m_dma_mem_addr;
uint32_t linecount = get_line_count();
uint32_t zoomcount = get_zoom_count();
uint32_t bytecount = get_byte_count();
const uint32_t gio_addr = m_dma_gio64_addr;
const uint32_t linewidth = get_line_width();
const uint32_t linezoom = get_line_zoom();
const uint32_t stride = get_stride();
m_dma_size &= 0x0000ffff;
m_dma_count = 0;
while (linecount > 0)
{
linecount--;
while (zoomcount > 0)
{
const uint32_t remaining = m_dma_count & 0x0000ffff;
uint32_t length = 8;
uint64_t shift = 56;
if (remaining < 8)
length = remaining;
uint64_t data = m_space->read_qword(m_dma_gio64_addr);
for (uint32_t i = 0; i < length; i++)
zoomcount--;
while (bytecount > 0)
{
m_space->write_byte(addr, (uint8_t)(data >> shift));
addr++;
shift -= 8;
}
m_dma_mem_addr += length;
m_dma_count -= length;
}
}
else
{ // Host to graphics
const uint32_t remaining = m_dma_count & 0x0000ffff;
uint32_t length = 8;
uint64_t shift = 56;
if (remaining < 8)
length = remaining;
uint64_t data = 0;
for (uint32_t i = 0; i < length; i++)
{
data |= (uint64_t)m_space->read_byte(addr) << shift;
addr++;
shift -= 8;
}
m_space->write_qword(m_dma_gio64_addr, data);
m_dma_mem_addr += length;
m_dma_count -= length;
}
if ((m_dma_count & 0x0000ffff) == 0)
{ // If remaining byte count is 0, deduct zoom count
m_dma_count -= 0x00010000;
if (m_dma_count == 0)
{ // If remaining zoom count is also 0, move to next line
m_dma_mem_addr += m_dma_stride & 0x0000ffff;
m_dma_size -= 0x00010000;
if ((m_dma_size & 0xffff0000) == 0)
{ // If no remaining lines, DMA is done.
m_dma_timer->adjust(attotime::never);
m_dma_run |= (1 << 3);
m_dma_run &= ~(1 << 6);
if (BIT(m_dma_control, 4))
if (m_dma_mode & MODE_TO_HOST)
{
m_dma_int_cause |= (1 << 3);
m_hpc3->raise_local_irq(0, ioc2_device::INT3_LOCAL0_MC_DMA);
if (m_dma_mode & MODE_FILL)
{ // Fill mode
m_space->write_dword(dma_translate(memory_addr), m_dma_gio64_addr);
if (m_dma_mode & MODE_DIR)
memory_addr += 4;
else
memory_addr -= 4;
bytecount -= 4;
}
else
{
uint32_t length = 8;
uint64_t shift = 56;
if (bytecount < 8)
length = bytecount;
uint64_t data = m_space->read_qword(gio_addr);
for (uint32_t i = 0; i < length; i++)
{
m_space->write_byte(dma_translate(memory_addr), (uint8_t)(data >> shift));
if (m_dma_mode & MODE_DIR)
memory_addr++;
else
memory_addr--;
shift -= 8;
}
bytecount -= length;
}
}
else
{
uint32_t length = 8;
uint64_t shift = 56;
if (bytecount < 8)
length = bytecount;
uint64_t data = 0;
for (uint32_t i = 0; i < length; i++)
{
data |= (uint64_t)m_space->read_byte(dma_translate(memory_addr)) << shift;
if (m_dma_mode & MODE_DIR)
memory_addr++;
else
memory_addr--;
shift -= 8;
}
m_space->write_qword(gio_addr, data);
bytecount -= length;
}
}
else
bytecount = linewidth;
if (zoomcount > 0)
{
m_dma_count = (m_dma_stride & 0x03ff0000) | (m_dma_size & 0x0000ffff);
if (m_dma_mode & MODE_DIR)
memory_addr -= linewidth;
else
memory_addr += linewidth;
}
}
else
{ // If remaining zoom count is non-zero, reload byte count and return source address to the beginning of the line.
m_dma_count |= m_dma_size & 0x0000ffff;
m_dma_mem_addr -= m_dma_size & 0x0000ffff;
}
zoomcount = linezoom;
memory_addr += stride;
}
m_dma_mem_addr = memory_addr;
m_dma_timer->adjust(attotime::never);
m_dma_run |= (1 << 3);
m_dma_run &= ~(1 << 6);
if (BIT(m_dma_control, 4))
{
m_dma_int_cause |= (1 << 3);
m_hpc3->raise_local_irq(0, ioc2_device::INT3_LOCAL0_MC_DMA);
}
}
@ -720,9 +732,6 @@ void sgi_mc_device::device_timer(emu_timer &timer, device_timer_id id, int param
}
else if (id == TIMER_DMA)
{
while (m_dma_run & (1 << 6))
{
dma_tick();
}
dma_immediate();
}
}

View File

@ -52,8 +52,24 @@ protected:
static const device_timer_id TIMER_DMA = 1;
private:
enum
{
MODE_TO_HOST = (1 << 1),
MODE_SYNC = (1 << 2),
MODE_FILL = (1 << 3),
MODE_DIR = (1 << 4),
MODE_SNOOP = (1 << 5)
};
uint32_t dma_translate(uint32_t address);
void dma_tick();
void dma_immediate();
uint32_t get_line_count() { return m_dma_size >> 16; }
uint32_t get_line_width() { return (uint16_t)m_dma_size; }
uint32_t get_line_zoom() { return (m_dma_stride >> 16) & 0x3ff; }
int16_t get_stride() { return (int16_t)m_dma_stride; }
uint32_t get_zoom_count() { return (m_dma_count >> 16) & 0x3ff; }
uint32_t get_byte_count() { return (uint16_t)m_dma_count; }
required_device<cpu_device> m_maincpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;