-t10sbc.cpp: Added support for Format Parameters and Geometry Parameters pages. [Ryan Holtz]
-hpc3.cpp: Added support for single-byte SCSI DRQ functionality. [Ryan Holtz]
This commit is contained in:
parent
9a06a7d23a
commit
9a5a4d491f
@ -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);
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, ... );
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user