diff --git a/src/devices/machine/t10sbc.cpp b/src/devices/machine/t10sbc.cpp index 036917bbbbe..e0a08688a91 100644 --- a/src/devices/machine/t10sbc.cpp +++ b/src/devices/machine/t10sbc.cpp @@ -163,22 +163,119 @@ void t10sbc::ReadData( uint8_t *data, int dataLength ) break; case T10SPC_CMD_MODE_SENSE_6: - // special Apple ID page. this is a vendor-specific page, - // so unless collisions occur there should be no need - // to change it. - if ((command[2] & 0x3f) == 0x30) + { + const uint8_t page = command[2] & 0x3f; + const uint8_t subpage = command[3]; + + switch (page) { - memset(data, 0, 40); - data[0] = 0x14; - strcpy((char *)&data[14], "APPLE COMPUTER, INC."); + case 0x03: + { + // Format Parameters + if (subpage != 0) + { + m_device->logerror("T10SBC: Unsupported MODE SENSE subpage for Format Parameters page: %02x\n", subpage); + break; + } + + const size_t fullSize = sizeof(format_page_t) + 12; + if (dataLength < fullSize) + { + m_device->logerror("T10SBC: Insufficient MODE SENSE buffer room for Format Parameters page: Need %d, given %d\n", fullSize, dataLength); + break; + } + + m_device->logerror("T10SBC: MODE SENSE (6), Format Parameters page\n"); + memset(data, 0, (uint8_t)fullSize); + data[0] = fullSize; + data[3] = 8; + + ReadCapacity(&data[4]); + + format_page_t format; + GetFormatPage(&format); + memcpy(&data[12], &format, sizeof(format_page_t)); + break; + } + case 0x04: + { + // Rigid Drive Geometry Parameters + if (subpage != 0) + { + m_device->logerror("T10SBC: Unsupported MODE SENSE subpage for Geometry Parameters page: %02x\n", subpage); + break; + } + + const size_t fullSize = sizeof(geometry_page_t) + 12; + if (dataLength < fullSize) + { + m_device->logerror("T10SBC: Insufficient MODE SENSE buffer room for Geometry Parameters page: Need %d, given %d\n", fullSize, dataLength); + break; + } + + m_device->logerror("T10SBC: MODE SENSE (6), Geometry Parameters page\n"); + memset(data, 0, fullSize); + data[0] = (uint8_t)fullSize; + data[3] = 8; + + ReadCapacity(&data[4]); + + geometry_page_t geometry; + GetGeometryPage(&geometry); + memcpy(&data[12], &geometry, sizeof(geometry_page_t)); + break; + } + case 0x30: + // special Apple ID page. this is a vendor-specific page, + // so unless collisions occur there should be no need + // to change it. + memset(data, 0, 40); + data[0] = 0x14; + strcpy((char *)&data[14], "APPLE COMPUTER, INC."); + break; + case 0x3f: + if (subpage == 0) + { + const size_t fullSize = sizeof(format_page_t) + sizeof(geometry_page_t) + 12; + if (dataLength < fullSize) + { + m_device->logerror("T10SBC: Insufficient MODE SENSE buffer room for Return All Pages: Need %d, given %d\n", fullSize, dataLength); + break; + } + + m_device->logerror("T10SBC: MODE SENSE (6), Return All Pages\n"); + memset(data, 0, (uint8_t)fullSize); + data[0] = (uint8_t)fullSize; + data[3] = (uint8_t)8; + + ReadCapacity(&data[4]); + + format_page_t format; + GetFormatPage(&format); + memcpy(&data[12], &format, sizeof(format_page_t)); + + geometry_page_t geometry; + GetGeometryPage(&geometry); + memcpy(&data[12 + sizeof(format_page_t)], &geometry, sizeof(geometry_page_t)); + } + else + { + m_device->logerror("T10SBC: Unsupported MODE SENSE subpage for Return All Pages: %02x\n", subpage); + } + break; + default: + m_device->logerror("T10SBC: Unknown MODE SENSE page: %02x\n", page); + break; } break; + } case T10SBC_CMD_READ_6: case T10SBC_CMD_READ_10: case T10SBC_CMD_READ_12: if ((m_disk) && (m_blocks)) { + m_device->logerror("T10SBC: Reading %d bytes from HD\n", dataLength); while (dataLength > 0) { if (!hard_disk_read(m_disk, m_lba, data)) @@ -194,27 +291,8 @@ void t10sbc::ReadData( uint8_t *data, int dataLength ) break; case T10SBC_CMD_READ_CAPACITY: // READ CAPACITY - { - hard_disk_info *info; - uint32_t temp; - - info = hard_disk_get_info(m_disk); - - m_device->logerror("T10SBC: READ CAPACITY\n"); - - // get # of sectors - temp = info->cylinders * info->heads * info->sectors; - temp--; - - data[0] = (temp>>24) & 0xff; - data[1] = (temp>>16) & 0xff; - data[2] = (temp>>8) & 0xff; - data[3] = (temp & 0xff); - data[4] = (info->sectorbytes>>24)&0xff; - data[5] = (info->sectorbytes>>16)&0xff; - data[6] = (info->sectorbytes>>8)&0xff; - data[7] = (info->sectorbytes & 0xff); - } + m_device->logerror("T10SBC: READ CAPACITY\n"); + ReadCapacity(&data[0]); break; default: @@ -239,6 +317,7 @@ void t10sbc::WriteData( uint8_t *data, int dataLength ) case T10SBC_CMD_WRITE_10: if ((m_disk) && (m_blocks)) { + m_device->logerror("T10SBC: Writing %d bytes to HD\n", dataLength); while (dataLength > 0) { if (!hard_disk_write(m_disk, m_lba, data)) @@ -268,3 +347,49 @@ void t10sbc::SetDevice( void *_disk ) { m_disk = (hard_disk_file *)_disk; } + +void t10sbc::GetFormatPage( format_page_t *page ) +{ + hard_disk_info *info = hard_disk_get_info(m_disk); + + memset(page, 0, sizeof(format_page_t)); + page->m_page_code = 0x03; + page->m_page_length = 0x16; + page->m_sectors_per_track_msb = (uint8_t)(info->sectors >> 8); + page->m_sectors_per_track_lsb = (uint8_t)info->sectors; + page->m_bytes_per_sector_msb = (uint8_t)(info->sectorbytes >> 8); + page->m_bytes_per_sector_lsb = (uint8_t)info->sectorbytes; + page->m_format = 0x80; // SSEC, Soft-Sectored +} + +void t10sbc::GetGeometryPage( geometry_page_t *page ) +{ + hard_disk_info *info = hard_disk_get_info(m_disk); + + memset(page, 0, sizeof(geometry_page_t)); + page->m_page_code = 0x04; + page->m_page_length = 0x16; + page->m_num_cylinders_msb = (uint8_t)(info->cylinders >> 16); + page->m_num_cylinders_2nd = (uint8_t)(info->cylinders >> 8); + page->m_num_cylinders_lsb = (uint8_t)info->cylinders; + page->m_num_heads = (uint8_t)info->heads; + page->m_rot_rate_msb = (uint8_t)(3600 >> 8); + page->m_rot_rate_lsb = (uint8_t)3600; +} + +void t10sbc::ReadCapacity( uint8_t *data ) +{ + hard_disk_info *info = hard_disk_get_info(m_disk); + + // get # of sectors + uint32_t temp = info->cylinders * info->heads * info->sectors - 1; + + data[0] = (temp>>24) & 0xff; + data[1] = (temp>>16) & 0xff; + data[2] = (temp>>8) & 0xff; + data[3] = (temp & 0xff); + data[4] = (info->sectorbytes>>24)&0xff; + data[5] = (info->sectorbytes>>16)&0xff; + data[6] = (info->sectorbytes>>8)&0xff; + data[7] = (info->sectorbytes & 0xff); +} \ No newline at end of file diff --git a/src/devices/machine/t10sbc.h b/src/devices/machine/t10sbc.h index fa0053e74f7..e9a3ce0cec9 100644 --- a/src/devices/machine/t10sbc.h +++ b/src/devices/machine/t10sbc.h @@ -32,6 +32,63 @@ protected: virtual void t10_start(device_t &device) override; virtual void t10_reset() override; + struct format_page_t + { + uint8_t m_page_code; + uint8_t m_page_length; + uint8_t m_tracks_per_zone_msb; + uint8_t m_tracks_per_zone_lsb; + uint8_t m_alt_sectors_per_zone_msb; + uint8_t m_alt_sectors_per_zone_lsb; + uint8_t m_alt_tracks_per_zone_msb; + uint8_t m_alt_tracks_per_zone_lsb; + uint8_t m_alt_tracks_per_volume_msb; + uint8_t m_alt_tracks_per_volume_lsb; + uint8_t m_sectors_per_track_msb; + uint8_t m_sectors_per_track_lsb; + uint8_t m_bytes_per_sector_msb; + uint8_t m_bytes_per_sector_lsb; + uint8_t m_interleave_msb; + uint8_t m_interleave_lsb; + uint8_t m_track_skew_msb; + uint8_t m_track_skew_lsb; + uint8_t m_cylinder_skew_msb; + uint8_t m_cylinder_skew_lsb; + uint8_t m_format; + uint8_t m_reserved[3]; + }; + + struct geometry_page_t + { + uint8_t m_page_code; + uint8_t m_page_length; + uint8_t m_num_cylinders_msb; + uint8_t m_num_cylinders_2nd; + uint8_t m_num_cylinders_lsb; + uint8_t m_num_heads; + uint8_t m_start_cylinder_msb; + uint8_t m_start_cylinder_2nd; + uint8_t m_start_cylinder_lsb; + uint8_t m_start_cylinder_rwc_msb; + uint8_t m_start_cylinder_rwc_2nd; + uint8_t m_start_cylinder_rwc_lsb; + uint8_t m_step_rate_msb; + uint8_t m_step_rate_lsb; + uint8_t m_lz_cylinder_msb; + uint8_t m_lz_cylinder_2nd; + uint8_t m_lz_cylinder_lsb; + uint8_t m_rot_pos_locking; + uint8_t m_rot_offset; + uint8_t m_reserved0; + uint8_t m_rot_rate_msb; + uint8_t m_rot_rate_lsb; + uint8_t m_reserved1[2]; + }; + + virtual void GetFormatPage( format_page_t *page ); + virtual void GetGeometryPage( geometry_page_t *page ); + virtual void ReadCapacity( uint8_t *data ); + harddisk_image_device *m_image; uint32_t m_lba; diff --git a/src/mame/drivers/indy_indigo2.cpp b/src/mame/drivers/indy_indigo2.cpp index ff20c6d8549..e2aab916944 100644 --- a/src/mame/drivers/indy_indigo2.cpp +++ b/src/mame/drivers/indy_indigo2.cpp @@ -323,7 +323,8 @@ void ip22_state::ip22_base(machine_config &config) WD33C93(config, m_scsi_ctrl); m_scsi_ctrl->set_scsi_port("scsi"); - m_scsi_ctrl->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi_irq)); + m_scsi_ctrl->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi0_irq)); + //m_scsi_ctrl->drq_cb().set(m_hpc3, FUNC(hpc3_device::scsi0_drq)); SGI_HAL2(config, m_hal2); SGI_IOC2_GUINNESS(config, m_ioc2, m_maincpu); @@ -368,7 +369,8 @@ void ip24_state::ip244415(machine_config &config) WD33C93(config, m_scsi_ctrl2); m_scsi_ctrl2->set_scsi_port("scsi2"); - m_scsi_ctrl2->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi_irq)); + m_scsi_ctrl->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi1_irq)); + //m_scsi_ctrl->drq_cb().set(m_hpc3, FUNC(hpc3_device::scsi1_drq)); SGI_HPC3(config, m_hpc3, m_maincpu, m_scsi_ctrl, m_scsi_ctrl2, m_ioc2, m_ldac, m_rdac); } diff --git a/src/mame/machine/hpc3.cpp b/src/mame/machine/hpc3.cpp index aa32407afa6..d45d2d5ed20 100644 --- a/src/mame/machine/hpc3.cpp +++ b/src/mame/machine/hpc3.cpp @@ -12,11 +12,12 @@ #define LOG_UNKNOWN (1 << 0) #define LOG_PBUS_DMA (1 << 1) #define LOG_SCSI (1 << 2) -#define LOG_ETHERNET (1 << 3) -#define LOG_PBUS4 (1 << 4) -#define LOG_CHAIN (1 << 5) +#define LOG_SCSI_DMA (1 << 3) +#define LOG_ETHERNET (1 << 4) +#define LOG_PBUS4 (1 << 5) +#define LOG_CHAIN (1 << 6) -#define VERBOSE (LOG_PBUS_DMA | LOG_PBUS4 | LOG_UNKNOWN | LOG_ETHERNET) +#define VERBOSE (LOG_SCSI_DMA) #include "logmacro.h" DEFINE_DEVICE_TYPE(SGI_HPC3, hpc3_device, "hpc3", "SGI HPC3") @@ -37,15 +38,21 @@ void hpc3_device::device_start() { save_item(NAME(m_enetr_nbdp)); save_item(NAME(m_enetr_cbp)); - - save_item(NAME(m_scsi0_desc)); - save_item(NAME(m_scsi0_addr)); - save_item(NAME(m_scsi0_flags)); - save_item(NAME(m_scsi0_byte_count)); - save_item(NAME(m_scsi0_next_addr)); - save_item(NAME(m_scsi0_dma_ctrl)); save_item(NAME(m_pio_config)); + for (uint32_t i = 0; i < 2; i++) + { + save_item(NAME(m_scsi_dma[i].m_desc), i); + save_item(NAME(m_scsi_dma[i].m_addr), i); + save_item(NAME(m_scsi_dma[i].m_ctrl), i); + save_item(NAME(m_scsi_dma[i].m_length), i); + save_item(NAME(m_scsi_dma[i].m_next), i); + save_item(NAME(m_scsi_dma[i].m_irq), i); + save_item(NAME(m_scsi_dma[i].m_big_endian), i); + save_item(NAME(m_scsi_dma[i].m_to_device), i); + save_item(NAME(m_scsi_dma[i].m_active), i); + } + for (uint32_t i = 0; i < 8; i++) { save_item(NAME(m_pbus_dma[i].m_active), i); @@ -67,12 +74,7 @@ void hpc3_device::device_reset() m_enetr_nbdp = 0x80000000; m_enetr_cbp = 0x80000000; - m_scsi0_desc = 0; - m_scsi0_addr = 0; - m_scsi0_flags = 0; - m_scsi0_byte_count = 0; - m_scsi0_next_addr = 0; - m_scsi0_dma_ctrl = 0; + memset(m_scsi_dma, 0, sizeof(scsi_dma_t) * 2); for (uint32_t i = 0; i < 8; i++) { @@ -88,6 +90,8 @@ void hpc3_device::device_reset() m_pbus_dma[i].m_active = false; m_pbus_dma[i].m_timer->adjust(attotime::never); } + + m_cpu_space = &m_maincpu->space(AS_PROGRAM); } void hpc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) @@ -117,8 +121,7 @@ void hpc3_device::do_pbus_dma(uint32_t channel) if (dma.m_active && (channel == 1 || channel == 2)) { - address_space &space = m_maincpu->space(AS_PROGRAM); - uint16_t temp16 = space.read_dword(dma.m_cur_ptr) >> 16; + uint16_t temp16 = m_cpu_space->read_dword(dma.m_cur_ptr) >> 16; int16_t stemp16 = (int16_t)((temp16 >> 8) | (temp16 << 8)); if (channel == 1) @@ -135,10 +138,10 @@ void hpc3_device::do_pbus_dma(uint32_t channel) { dma.m_desc_ptr = dma.m_next_ptr; LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_DescPtr = %08x\n", channel, dma.m_desc_ptr); fflush(stdout); - dma.m_cur_ptr = space.read_dword(dma.m_desc_ptr); - dma.m_desc_flags = space.read_dword(dma.m_desc_ptr + 4); + dma.m_cur_ptr = m_cpu_space->read_dword(dma.m_desc_ptr); + dma.m_desc_flags = m_cpu_space->read_dword(dma.m_desc_ptr + 4); dma.m_bytes_left = dma.m_desc_flags & 0x7fffffff; - dma.m_next_ptr = space.read_dword(dma.m_desc_ptr + 8); + dma.m_next_ptr = m_cpu_space->read_dword(dma.m_desc_ptr + 8); LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_CurPtr = %08x\n", channel, dma.m_cur_ptr); fflush(stdout); LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_BytesLeft = %08x\n", channel, dma.m_bytes_left); fflush(stdout); LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_NextPtr = %08x\n", channel, dma.m_next_ptr); fflush(stdout); @@ -163,11 +166,11 @@ READ32_MEMBER(hpc3_device::hd_enet_r) switch (offset) { case 0x0004/4: - LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 Desc Address Read: %08x & %08x\n", machine().describe_context(), m_scsi0_desc, mem_mask); - return m_scsi0_desc; + LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 Desc Address Read: %08x & %08x\n", machine().describe_context(), m_scsi_dma[0].m_desc, mem_mask); + return m_scsi_dma[0].m_desc; case 0x1004/4: - LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 DMA Control Read: %08x & %08x\n", machine().describe_context(), m_scsi0_dma_ctrl, mem_mask); - return m_scsi0_dma_ctrl; + LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 DMA Control Read: %08x & %08x\n", machine().describe_context(), m_scsi_dma[0].m_ctrl, mem_mask); + return m_scsi_dma[0].m_ctrl; case 0x4000/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet CBP Read: %08x & %08x\n", machine().describe_context(), m_enetr_nbdp, mem_mask); return m_enetr_cbp; @@ -186,11 +189,16 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) { case 0x0004/4: LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 Desc Address Write: %08x\n", machine().describe_context(), data); - m_scsi0_desc = data; + m_scsi_dma[0].m_desc = data; + fetch_chain(0); break; case 0x1004/4: LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI0 DMA Control Write: %08x\n", machine().describe_context(), data); - m_scsi0_dma_ctrl = data; + m_scsi_dma[0].m_ctrl = data; + m_scsi_dma[0].m_to_device = (m_scsi_dma[0].m_ctrl & HPC3_DMACTRL_DIR); + m_scsi_dma[0].m_big_endian = (m_scsi_dma[0].m_ctrl & HPC3_DMACTRL_ENDIAN); + m_scsi_dma[0].m_active = (m_scsi_dma[0].m_ctrl & HPC3_DMACTRL_ENABLE); + m_scsi_dma[0].m_irq = (m_scsi_dma[0].m_ctrl & HPC3_DMACTRL_IRQ); break; case 0x4000/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet CBP Write: %08x\n", machine().describe_context(), data); @@ -529,151 +537,212 @@ WRITE32_MEMBER(hpc3_device::unkpbus0_w) LOGMASKED(LOG_UNKNOWN, "%s: Unknown PBUS Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbc8000 + offset*4, data, mem_mask); } -void hpc3_device::dump_chain(address_space &space, uint32_t ch_base) +void hpc3_device::dump_chain(uint32_t base) { - LOGMASKED(LOG_CHAIN, "node: %08x %08x %08x (len = %x)\n", space.read_dword(ch_base), space.read_dword(ch_base+4), space.read_dword(ch_base+8), space.read_dword(ch_base+4) & 0x3fff); + const uint32_t addr = m_cpu_space->read_dword(base); + const uint32_t ctrl = m_cpu_space->read_dword(base+4); + const uint32_t next = m_cpu_space->read_dword(base+8); - if ((space.read_dword(ch_base+8) != 0) && !(space.read_dword(ch_base+4) & 0x80000000)) + LOGMASKED(LOG_CHAIN, "Chain Node:\n"); + LOGMASKED(LOG_CHAIN, " Addr: %08x\n", addr); + LOGMASKED(LOG_CHAIN, " Ctrl: %08x\n", ctrl); + LOGMASKED(LOG_CHAIN, " Next: %08x\n", next); + + if (next != 0 && !BIT(ctrl, 31)) { - dump_chain(space, space.read_dword(ch_base+8)); + dump_chain(next); } } -void hpc3_device::fetch_chain(address_space &space) +void hpc3_device::fetch_chain(int channel) { - 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); - LOGMASKED(LOG_CHAIN, "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); + scsi_dma_t &dma = m_scsi_dma[channel]; + dma.m_addr = m_cpu_space->read_dword(dma.m_desc); + dma.m_ctrl = m_cpu_space->read_dword(dma.m_desc+4); + dma.m_next = m_cpu_space->read_dword(dma.m_desc+8); + dma.m_length = dma.m_ctrl & 0x3fff; + + LOGMASKED(LOG_CHAIN, "Fetching chain from %08x:\n", dma.m_desc); + LOGMASKED(LOG_CHAIN, " Addr: %08x\n", dma.m_addr); + LOGMASKED(LOG_CHAIN, " Ctrl: %08x\n", dma.m_ctrl); + LOGMASKED(LOG_CHAIN, " Next: %08x\n", dma.m_next); } -bool hpc3_device::decrement_chain(address_space &space) +void hpc3_device::decrement_chain(int channel) { - m_scsi0_byte_count--; - if (m_scsi0_byte_count == 0) + scsi_dma_t &dma = m_scsi_dma[channel]; + dma.m_length--; + if (dma.m_length == 0) { - if (BIT(m_scsi0_flags, 31)) + if (BIT(dma.m_ctrl, 31)) { - return false; + dma.m_active = false; + dma.m_ctrl &= ~HPC3_DMACTRL_ENABLE; + return; } - m_scsi0_desc = m_scsi0_next_addr; - fetch_chain(space); + dma.m_desc = dma.m_next; + fetch_chain(channel); } - return true; } -WRITE_LINE_MEMBER(hpc3_device::scsi_irq) +void hpc3_device::scsi_drq(bool state, int channel) { - address_space &space = m_maincpu->space(AS_PROGRAM); +#if 0 + scsi_dma_t &dma = m_scsi_dma[channel]; - if (state) + if (!dma.m_active) { - uint8_t dma_buffer[4096]; - if (m_wd33c93->get_dma_count()) + LOGMASKED(LOG_SCSI_DMA, "HPC3: SCSI%d DRQ set while no active SCSI DMA!\n", channel); + return; + } + + if (dma.m_to_device) + m_wd33c93->dma_w(m_cpu_space->read_byte(dma.m_big_endian ? BYTE4_XOR_BE(dma.m_addr) : BYTE4_XOR_LE(dma.m_addr))); + else + m_cpu_space->write_byte(dma.m_big_endian ? BYTE4_XOR_BE(dma.m_addr) : BYTE4_XOR_LE(dma.m_addr), m_wd33c93->dma_r()); + + dma.m_addr++; + decrement_chain(channel); + + if (!dma.m_active) + { + // clear HPC3 DMA active flag + dma.m_ctrl &= ~HPC3_DMACTRL_ENABLE; + } +#endif +} + +WRITE_LINE_MEMBER(hpc3_device::scsi0_drq) +{ + scsi_drq(state, 0); +} + +WRITE_LINE_MEMBER(hpc3_device::scsi1_drq) +{ + scsi_drq(state, 1); +} + +void hpc3_device::scsi_dma(int channel) +{ + int byte_count = channel ? m_wd33c93_2->get_dma_count() : m_wd33c93->get_dma_count(); + scsi_dma_t &dma = m_scsi_dma[channel]; + + LOGMASKED(LOG_SCSI_DMA, "HPC3: Transferring %d bytes %s %08x %s SCSI0\n", + byte_count, dma.m_to_device ? "from" : "to", dma.m_addr, dma.m_to_device ? "to" : "from"); + + if (dma.m_irq) + LOGMASKED(LOG_SCSI_DMA, "HPC3: Not yet implemented: SCSI DMA IRQ\n"); + + uint8_t dma_buffer[512]; + memset(dma_buffer, 0, 512); + if (dma.m_to_device) + { + // HPC3 DMA: host to device + if (byte_count <= 512) { - LOGMASKED(LOG_SCSI, "m_wd33c93->get_dma_count() is %d\n", m_wd33c93->get_dma_count()); - if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE) + for (int i = 0; i < byte_count; i++) { - if (m_scsi0_dma_ctrl & HPC3_DMACTRL_IRQ) - LOGMASKED(LOG_SCSI, "IP22: Unhandled SCSI DMA IRQ\n"); + dma_buffer[dma.m_big_endian ? BYTE4_XOR_BE(i) : BYTE4_XOR_LE(i)] = m_cpu_space->read_byte(dma.m_addr); + dma.m_addr++; + decrement_chain(channel); + if (!dma.m_active) + break; } - bool big_endian = (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENDIAN); - if (m_scsi0_dma_ctrl & HPC3_DMACTRL_ENABLE) + if (channel) + m_wd33c93_2->dma_write_data(byte_count, dma_buffer); + else + m_wd33c93->dma_write_data(byte_count, dma_buffer); + } + else + { + while (byte_count) { - if (m_scsi0_dma_ctrl & HPC3_DMACTRL_DIR) + int sub_count = std::min(512, byte_count); + + for (int i = 0; i < sub_count; i++) { - // HPC3 DMA: host to device - int byte_count = m_wd33c93->get_dma_count(); - //dump_chain(space, m_scsi0_desc); - fetch_chain(space); + dma_buffer[dma.m_big_endian ? BYTE4_XOR_BE(i) : BYTE4_XOR_LE(i)] = m_cpu_space->read_byte(dma.m_addr); + dma.m_addr++; + decrement_chain(channel); + if (!dma.m_active) + break; + } - LOGMASKED(LOG_SCSI, "DMA to SCSI device: %d bytes from %08x\n", byte_count, m_scsi0_addr); + if (channel) + m_wd33c93_2->dma_write_data(sub_count, dma_buffer); + else + m_wd33c93->dma_write_data(sub_count, dma_buffer); - if (byte_count <= 512) - { - for (int i = 0; i < byte_count; i++) - { - dma_buffer[big_endian ? BYTE4_XOR_BE(i) : BYTE4_XOR_LE(i)] = space.read_byte(m_scsi0_addr+i); - if (!decrement_chain(space)) - break; - } - - m_wd33c93->dma_write_data(byte_count, dma_buffer); - } - else - { - int dstoffs = 0; - while (byte_count) - { - int sub_count = std::min(512, byte_count); - - for (int i = 0; i < sub_count; i++) - { - dma_buffer[big_endian ? BYTE4_XOR_BE(dstoffs+i) : BYTE4_XOR_LE(dstoffs+i)] = space.read_byte(m_scsi0_addr); - m_scsi0_addr++; - if (!decrement_chain(space)) - break; - } - - m_wd33c93->dma_write_data(sub_count, dma_buffer); - - byte_count -= sub_count; - } - } - - // clear DMA on the controller too - m_wd33c93->clear_dma(); + if (!dma.m_active) + { + break; } else { - // HPC3 DMA: device to host - int byte_count = m_wd33c93->get_dma_count(); - //dump_chain(space, m_scsi0_desc); - fetch_chain(space); - - LOGMASKED(LOG_SCSI, "DMA from SCSI device: %d bytes to %08x\n", byte_count, m_scsi0_addr); - - if (byte_count < 512) - { - m_wd33c93->dma_read_data(byte_count, dma_buffer); - - for (int i = 0; i < byte_count; i++) - { - space.write_byte(big_endian ? BYTE4_XOR_BE(m_scsi0_addr+i) : BYTE4_XOR_LE(m_scsi0_addr+i), dma_buffer[i]); - if (!decrement_chain(space)) - break; - } - } - else - { - while (byte_count) - { - int sub_count = m_wd33c93->dma_read_data(512, dma_buffer); - - for (int i = 0; i < sub_count; i++) - { - space.write_byte(big_endian ? BYTE4_XOR_BE(m_scsi0_addr) : BYTE4_XOR_LE(m_scsi0_addr), dma_buffer[i]); - m_scsi0_addr++; - if (!decrement_chain(space)) - break; - } - - byte_count -= sub_count; - } - } - - // clear DMA on the controller too - m_wd33c93->clear_dma(); + memset(dma_buffer, 0, sub_count); + byte_count -= sub_count; } } } + } + else + { + // HPC3 DMA: device to host + if (byte_count <= 512) + { + if (channel) + m_wd33c93_2->dma_read_data(byte_count, dma_buffer); + else + m_wd33c93->dma_read_data(byte_count, dma_buffer); - // clear HPC3 DMA active flag - m_scsi0_dma_ctrl &= ~HPC3_DMACTRL_ENABLE; + for (int i = 0; i < byte_count; i++) + { + m_cpu_space->write_byte(dma.m_big_endian ? BYTE4_XOR_BE(dma.m_addr) : BYTE4_XOR_LE(dma.m_addr), dma_buffer[i]); + dma.m_addr++; + decrement_chain(channel); + if (!dma.m_active) + break; + } + } + else + { + while (byte_count) + { + int sub_count; + if (channel) + sub_count = m_wd33c93_2->dma_read_data(512, dma_buffer); + else + sub_count = m_wd33c93->dma_read_data(512, dma_buffer); + + for (int i = 0; i < sub_count; i++) + { + m_cpu_space->write_byte(dma.m_big_endian ? BYTE4_XOR_BE(dma.m_addr) : BYTE4_XOR_LE(dma.m_addr), dma_buffer[i]); + dma.m_addr++; + decrement_chain(channel); + if (!dma.m_active) + break; + } + + if (!dma.m_active) + break; + else + byte_count -= sub_count; + } + } + } + + // clear DMA on the controller + m_wd33c93->clear_dma(); +} + +WRITE_LINE_MEMBER(hpc3_device::scsi0_irq) +{ + if (state) + { + if (m_wd33c93->get_dma_count() && m_scsi_dma[0].m_active) + scsi_dma(0); - // set the interrupt m_ioc2->raise_local0_irq(ioc2_device::INT3_LOCAL0_SCSI0); } else @@ -681,3 +750,18 @@ WRITE_LINE_MEMBER(hpc3_device::scsi_irq) m_ioc2->lower_local0_irq(ioc2_device::INT3_LOCAL0_SCSI0); } } + +WRITE_LINE_MEMBER(hpc3_device::scsi1_irq) +{ + if (state) + { + if (m_wd33c93_2->get_dma_count() && m_scsi_dma[1].m_active) + scsi_dma(1); + + m_ioc2->raise_local0_irq(ioc2_device::INT3_LOCAL0_SCSI1); + } + else + { + m_ioc2->lower_local0_irq(ioc2_device::INT3_LOCAL0_SCSI1); + } +} diff --git a/src/mame/machine/hpc3.h b/src/mame/machine/hpc3.h index a7e9a596b5d..a26ecd9d1e1 100644 --- a/src/mame/machine/hpc3.h +++ b/src/mame/machine/hpc3.h @@ -58,7 +58,10 @@ public: DECLARE_READ32_MEMBER(pio_config_r); DECLARE_WRITE32_MEMBER(pio_config_w); - DECLARE_WRITE_LINE_MEMBER(scsi_irq); + DECLARE_WRITE_LINE_MEMBER(scsi0_irq); + DECLARE_WRITE_LINE_MEMBER(scsi0_drq); + DECLARE_WRITE_LINE_MEMBER(scsi1_irq); + DECLARE_WRITE_LINE_MEMBER(scsi1_drq); protected: void device_start() override; @@ -67,9 +70,11 @@ protected: void do_pbus_dma(uint32_t channel); - void dump_chain(address_space &space, uint32_t ch_base); - void fetch_chain(address_space &space); - bool decrement_chain(address_space &space); + void dump_chain(uint32_t base); + void fetch_chain(int channel); + void decrement_chain(int channel); + void scsi_drq(bool state, int channel); + void scsi_dma(int channel); static const device_timer_id TIMER_PBUS_DMA = 0; @@ -127,15 +132,26 @@ protected: uint32_t m_enetr_nbdp; uint32_t m_enetr_cbp; - 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; + + struct scsi_dma_t + { + uint32_t m_desc; + uint32_t m_addr; + uint32_t m_ctrl; + uint32_t m_length; + uint32_t m_next; + bool m_irq; + bool m_big_endian; + bool m_to_device; + bool m_active; + }; + + scsi_dma_t m_scsi_dma[2]; pbus_dma_t m_pbus_dma[8]; uint32_t m_pio_config[10]; + address_space *m_cpu_space; + inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ... ); };