i8089: fix odd byte count and mismatched bus size (nw)

altos8600: hdd support (nw)
This commit is contained in:
cracyc 2017-09-29 17:19:25 -05:00
parent 3603b85686
commit f8118baec7
3 changed files with 237 additions and 23 deletions

View File

@ -105,6 +105,8 @@ void i8089_channel_device::device_reset()
elem.t = 0;
}
m_prio = PRIO_IDLE;
m_load_hi = false;
m_store_hi = false;
}
@ -230,6 +232,8 @@ int i8089_channel_device::execute_run()
// we are no longer executing task blocks
m_r[PSW].w &= ~(1 << 2);
m_xfer_pending = false;
m_load_hi = false;
m_store_hi = false;
if (VERBOSE)
{
@ -269,21 +273,23 @@ int i8089_channel_device::execute_run()
m_r[GA + CC_SOURCE].w += 2;
m_r[BC].w -= 2;
}
// destination is 16-bit, byte count is even
else if (BIT(m_r[PSW].w, 0) && !(m_r[BC].w & 1))
// destination is 16-bit, low byte
else if (BIT(m_r[PSW].w, 0) && !m_load_hi)
{
m_dma_value = m_iop->read_byte(m_r[GA + CC_SOURCE].t, m_r[GA + CC_SOURCE].w);
if(CC_FUNC & 1)
m_r[GA + CC_SOURCE].w++;
m_r[BC].w--;
if(--m_r[BC].w)
m_load_hi = true;
}
// destination is 16-bit, byte count is odd
else if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
// destination is 16-bit, high byte
else if (BIT(m_r[PSW].w, 0) && m_load_hi)
{
m_dma_value |= m_iop->read_byte(m_r[GA + CC_SOURCE].t, m_r[GA + CC_SOURCE].w) << 8;
if(CC_FUNC & 1)
m_r[GA + CC_SOURCE].w++;
m_r[BC].w--;
m_load_hi = false;
}
// 8-bit transfer
else
@ -300,7 +306,7 @@ int i8089_channel_device::execute_run()
if (VERBOSE_DMA)
logerror("[ %04x ]\n", m_dma_value);
if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
if (BIT(m_r[PSW].w, 0) && m_load_hi)
m_dma_state = DMA_FETCH;
else if (CC_TRANS)
m_dma_state = DMA_TRANSLATE;
@ -316,7 +322,12 @@ int i8089_channel_device::execute_run()
case DMA_WAIT_FOR_DEST_DRQ:
if (m_drq)
m_dma_state = DMA_STORE;
{
if(m_store_hi)
m_dma_state = DMA_STORE_BYTE_HIGH;
else
m_dma_state = DMA_STORE;
}
break;
case DMA_STORE:
@ -360,8 +371,20 @@ int i8089_channel_device::execute_run()
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_TERMINATE\n", shortname(), tag());
// do we need to read another byte?
if (BIT(m_r[PSW].w, 1) && !BIT(m_r[PSW].w, 0) && !m_store_hi)
{
if (CC_SYNC == 0x02)
{
m_store_hi = true;
m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
}
else
m_dma_state = DMA_STORE_BYTE_HIGH;
}
// terminate on masked compare?
if (CC_TMC & 0x03)
else if (CC_TMC & 0x03)
fatalerror("%s('%s'): terminate on masked compare not supported\n", shortname(), tag());
// terminate on byte count?
@ -372,18 +395,11 @@ int i8089_channel_device::execute_run()
else if (CC_TS)
fatalerror("%s('%s'): terminate on single transfer not supported\n", shortname(), tag());
// not terminated, continue transfer
else
// do we need to read another byte?
if (BIT(m_r[PSW].w, 1) && !BIT(m_r[PSW].w, 0))
if (CC_SYNC == 0x02)
m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
else
m_dma_state = DMA_STORE_BYTE_HIGH;
// transfer done
else
m_dma_state = DMA_IDLE;
{
m_store_hi = false;
m_dma_state = DMA_IDLE;
}
break;
@ -391,8 +407,9 @@ int i8089_channel_device::execute_run()
if (VERBOSE_DMA)
logerror("%s('%s'): entering state: DMA_STORE_BYTE_HIGH[ %02x ]\n", shortname(), tag(), (m_dma_value >> 8) & 0xff);
m_iop->write_byte(m_r[GA - CC_SOURCE].t, m_r[GB - CC_SOURCE].w, (m_dma_value >> 8) & 0xff);
m_r[GB - CC_SOURCE].w++;
m_iop->write_byte(m_r[GB - CC_SOURCE].t, m_r[GB - CC_SOURCE].w, (m_dma_value >> 8) & 0xff);
if(CC_FUNC & 2)
m_r[GB - CC_SOURCE].w++;
m_dma_state = DMA_TERMINATE;
break;

View File

@ -183,7 +183,7 @@ private:
bool m_xfer_pending;
uint16_t m_dma_value;
int m_dma_state;
bool m_drq;
bool m_drq, m_store_hi, m_load_hi;
// dma state
enum

View File

@ -11,6 +11,7 @@
#include "machine/z80sio.h"
#include "machine/wd_fdc.h"
#include "machine/acs8600_ics.h"
#include "imagedev/harddriv.h"
#include "bus/rs232/rs232.h"
class altos8600_state : public driver_device
@ -27,6 +28,7 @@ public:
m_fdc(*this, "fd1797"),
m_ram(*this, RAM_TAG),
m_ics(*this, "ics"),
m_hdd(*this, "hdd"),
m_bios(*this, "bios")
{}
DECLARE_READ16_MEMBER(cpuram_r);
@ -53,6 +55,8 @@ public:
DECLARE_READ16_MEMBER(errhi_r);
DECLARE_WRITE16_MEMBER(clear_w);
DECLARE_WRITE8_MEMBER(cattn_w);
DECLARE_READ8_MEMBER(hd_r);
DECLARE_WRITE8_MEMBER(hd_w);
DECLARE_READ8_MEMBER(romport_r);
DECLARE_WRITE8_MEMBER(romport_w);
DECLARE_WRITE8_MEMBER(clrsys_w);
@ -69,6 +73,10 @@ private:
u16 xlate_r(address_space &space, offs_t offset, u16 mem_mask, int permbit);
void xlate_w(address_space &space, offs_t offset, u16 data, u16 mem_mask, int permbit);
void seterr(offs_t offset, u16 mem_mask, u16 err_mask);
bool find_sector();
bool write_sector(u8 data);
u8 read_sector();
void format_sector();
required_device<i8086_cpu_device> m_maincpu;
required_device<i8089_device> m_dmac;
required_device<pic8259_device> m_pic1;
@ -78,10 +86,18 @@ private:
required_device<fd1797_device> m_fdc;
required_device<ram_device> m_ram;
required_device<acs8600_ics_device> m_ics;
required_device<harddisk_image_device> m_hdd;
required_memory_region m_bios;
u8 m_mmuaddr[256], m_romport[4], m_dmamplex;
u16 m_mmuflags[256], m_mmuerr, m_mode, m_mmueaddr[2];
bool m_cpuif, m_user, m_nmiinh, m_nmistat;
u32 m_lba;
u16 m_head, m_sect, m_cyl, m_curcyl;
int m_secoff;
u8 m_cmd, m_stat;
bool m_cylhi, m_sechi;
const struct hard_disk_info* m_geom;
u8 m_sector[512];
};
void altos8600_state::machine_start()
@ -96,6 +112,184 @@ void altos8600_state::machine_reset()
m_user = false;
m_nmiinh = true;
m_nmistat = false;
m_cylhi = m_sechi = false;
m_stat = 0;
if(m_hdd->get_hard_disk_file())
m_geom = hard_disk_get_info(m_hdd->get_hard_disk_file());
else
m_geom = nullptr;
}
bool altos8600_state::find_sector()
{
u8 head = m_head >> 4;
logerror("head %d cyl %d curcyl %d sect %d", head, m_cyl, m_curcyl, m_sect);
if(!m_geom)
return false;
if(m_cyl != m_curcyl)
return false;
if(m_curcyl > m_geom->cylinders)
return false;
if(head > m_geom->heads)
return false;
if(m_sect > m_geom->sectors)
return false;
m_lba = (m_cyl * m_geom->heads + head) * m_geom->sectors + m_sect;
return true;
}
u8 altos8600_state::read_sector()
{
int secoff = m_secoff;
m_secoff++;
if(m_cmd == 1)
{
switch(secoff)
{
case 0:
return m_curcyl;
case 1:
return (m_head & 0xf0) | (m_curcyl >> 8);
case 2:
return m_sect;
}
secoff -= 3;
}
if(!secoff)
hard_disk_read(m_hdd->get_hard_disk_file(), m_lba, m_sector);
if(secoff >= 511)
{
m_dmac->drq1_w(CLEAR_LINE);
m_stat &= ~1;
m_stat |= 2;
}
if(secoff >= 512)
return 0;
return m_sector[secoff];
}
bool altos8600_state::write_sector(u8 data)
{
if(m_secoff >= 512)
return true;
m_sector[m_secoff++] = data;
logerror("secoff %d", m_secoff);
if(m_secoff == 512)
{
m_stat &= ~1;
m_stat |= 2;
hard_disk_write(m_hdd->get_hard_disk_file(), m_lba, m_sector);
m_dmac->drq1_w(CLEAR_LINE);
return true;
}
return false;
}
READ8_MEMBER(altos8600_state::hd_r)
{
switch(offset)
{
case 1:
if(BIT(m_stat, 0) && (m_cmd & 1))
return read_sector();
break;
case 3:
m_pic1->ir3_w(CLEAR_LINE);
return m_stat;
}
return 0;
}
WRITE8_MEMBER(altos8600_state::hd_w)
{
switch(offset)
{
case 0:
m_head = data;
if((m_head & 3) == 1)
m_stat |= 0x80;
else
m_stat &= ~0x80;
break;
case 1:
if(BIT(m_stat, 0))
{
switch(m_cmd)
{
case 2:
write_sector(data);
break;
case 4:
m_secoff++;
if(m_secoff == 4)
{
m_dmac->drq1_w(CLEAR_LINE);
m_stat &= ~1;
m_stat |= 2;
}
break;
}
break;
}
if(m_sechi)
m_sect |= (data & 7) << 8;
else
{
m_sechi = true;
m_sect = data;
}
break;
case 2:
if(m_cylhi)
m_cyl |= (data & 7) << 8;
else
{
m_cylhi = true;
m_cyl = data;
}
break;
case 3:
logerror("cmd %02x stat %04x\n", data, m_stat);
m_cmd = data;
m_cylhi = false;
m_sechi = false;
m_dmac->drq1_w(CLEAR_LINE);
if(!BIT(m_stat, 7))
break;
m_stat &= 0x80;
switch(m_cmd)
{
case 0x10:
m_curcyl = m_cyl;
m_stat |= 2;
break;
case 0x11:
m_curcyl = 0;
m_stat |= 2;
break;
case 0x1:
case 0x2:
case 0x9:
if(!find_sector())
{
m_stat |= 0xa;
break;
}
case 0x4:
m_secoff = 0;
m_stat |= 1;
m_dmac->drq1_w(ASSERT_LINE);
break;
}
m_pic2->ir0_w(ASSERT_LINE);
break;
}
}
WRITE_LINE_MEMBER(altos8600_state::cpuif_w)
@ -440,6 +634,7 @@ static ADDRESS_MAP_START(dmac_io, AS_IO, 16, altos8600_state)
AM_RANGE(0x0008, 0x000f) AM_WRITE(clear_w)
AM_RANGE(0x0010, 0x0017) AM_READ(errlo_r)
AM_RANGE(0x0018, 0x001f) AM_READ(errhi_r)
AM_RANGE(0x0020, 0x0027) AM_READWRITE8(hd_r, hd_w, 0x00ff)
AM_RANGE(0x0030, 0x0037) AM_WRITE(mode_w)
AM_RANGE(0x0038, 0x003f) AM_WRITE8(cattn_w, 0xffff)
AM_RANGE(0x0040, 0x0047) AM_DEVREADWRITE8("ppi", i8255_device, read, write, 0x00ff)
@ -536,9 +731,11 @@ static MACHINE_CONFIG_START(altos8600)
MCFG_FLOPPY_DRIVE_ADD("fd1797:3", altos8600_floppies, "8dd", floppy_image_device::default_floppy_formats)
MCFG_DEVICE_ADD("ics", ACS8600_ICS, 0)
MCFG_ACS8600_ICS_MAINCPU(":maincpu")
MCFG_ACS8600_ICS_MAINCPU(":dmac") // TODO: fixme
MCFG_ACS8600_ICS_IRQ1(DEVWRITELINE("pic8259_1", pic8259_device, ir5_w))
MCFG_ACS8600_ICS_IRQ2(DEVWRITELINE("pic8259_1", pic8259_device, ir6_w))
MCFG_HARDDISK_ADD("hdd")
MACHINE_CONFIG_END
ROM_START(altos8600)