From f8118baec7055b2d6bc6adc95a917fbe33245725 Mon Sep 17 00:00:00 2001 From: cracyc Date: Fri, 29 Sep 2017 17:19:25 -0500 Subject: i8089: fix odd byte count and mismatched bus size (nw) altos8600: hdd support (nw) --- src/devices/cpu/i8089/i8089_channel.cpp | 59 ++++++---- src/devices/cpu/i8089/i8089_channel.h | 2 +- src/mame/drivers/altos8600.cpp | 199 +++++++++++++++++++++++++++++++- 3 files changed, 237 insertions(+), 23 deletions(-) diff --git a/src/devices/cpu/i8089/i8089_channel.cpp b/src/devices/cpu/i8089/i8089_channel.cpp index aaae170de3a..99547fb20f8 100644 --- a/src/devices/cpu/i8089/i8089_channel.cpp +++ b/src/devices/cpu/i8089/i8089_channel.cpp @@ -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; diff --git a/src/devices/cpu/i8089/i8089_channel.h b/src/devices/cpu/i8089/i8089_channel.h index e6418eb2f48..c4d64d776ed 100644 --- a/src/devices/cpu/i8089/i8089_channel.h +++ b/src/devices/cpu/i8089/i8089_channel.h @@ -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 diff --git a/src/mame/drivers/altos8600.cpp b/src/mame/drivers/altos8600.cpp index 73a86c23d00..c9145a75d78 100644 --- a/src/mame/drivers/altos8600.cpp +++ b/src/mame/drivers/altos8600.cpp @@ -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 m_maincpu; required_device m_dmac; required_device m_pic1; @@ -78,10 +86,18 @@ private: required_device m_fdc; required_device m_ram; required_device m_ics; + required_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) -- cgit v1.2.3