summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/t10spc.cpp
blob: e5f636edf74abe6f67a043ef4440e5f97dd5dc4d (plain) (tree)
1
2
3
4
5
6
7
8
9

                        
                

                   

                      

                                        
                           

                                              
                                                  




                                                    




                                      
                                              











                                                                  





                              
                                        
                                            
                                                      


                                      
                                    
                                            
                                                      


                                      
                                      
                                            
                                                      











                                                         

                      





                                                      
                                        
                                             
                                                      



                                                                      
                                                                                     
                                                      




                                      
                                                      


                              
                                      


                                                     
                                                                            





                                                    
                                                                 













                                                                                 
                      
 
                
                                                                                  



                      
                                                       


                              
                                        


                      
                                                                                   



                      
                                                                











                                                    
// license:BSD-3-Clause
// copyright-holders:smf
#include "emu.h"
#include "t10spc.h"

#include "multibyte.h"

void t10spc::t10_start(device_t &device)
{
	m_device = &device;
	device.save_item(NAME(command));
	device.save_item(NAME(commandLength));
	device.save_item(NAME(m_transfer_length));
	device.save_item(NAME(m_phase));
	device.save_item(NAME(m_sense_key));
	device.save_item(NAME(m_sense_asc));
	device.save_item(NAME(m_sense_ascq));
	device.save_item(NAME(m_sense_information));
}

void t10spc::t10_reset()
{
	m_phase = SCSI_PHASE_BUS_FREE;
	m_status_code = SCSI_STATUS_CODE_GOOD;
	m_sense_key = 0;
	m_sense_asc = 0;
	m_sense_ascq = 0;
	m_sense_information = 0;
}

void t10spc::set_sense(sense_key_t key, sense_asc_ascq_t asc_ascq)
{
	m_sense_key = key;
	m_sense_asc = (asc_ascq >> 8) & 0xff;
	m_sense_ascq = asc_ascq & 0xff;
	m_sense_information = 0;
}

void t10spc::ExecCommand()
{
	switch( command[ 0 ] )
	{
	case T10SPC_CMD_TEST_UNIT_READY:
		m_phase = SCSI_PHASE_STATUS;
		m_status_code = SCSI_STATUS_CODE_GOOD;
		m_transfer_length = 0;
		break;

	case T10SPC_CMD_RECALIBRATE:
		m_phase = SCSI_PHASE_STATUS;
		m_status_code = SCSI_STATUS_CODE_GOOD;
		m_transfer_length = 0;
		break;

	case T10SPC_CMD_REQUEST_SENSE:
		m_phase = SCSI_PHASE_DATAIN;
		m_status_code = SCSI_STATUS_CODE_GOOD;
		if (command[4] == 0)
		{
			m_transfer_length = 4;
		}
		else if (command[4] > 18)
		{
			m_transfer_length = 18;
		}
		else
		{
			m_transfer_length = command[ 4 ];
		}
		break;

	case T10SPC_CMD_START_STOP_UNIT:
		m_phase = SCSI_PHASE_STATUS;
		m_status_code = SCSI_STATUS_CODE_GOOD;
		m_transfer_length = 0;
		break;

	case T10SPC_CMD_SEND_DIAGNOSTIC:
		m_phase = SCSI_PHASE_DATAOUT;
		m_status_code = SCSI_STATUS_CODE_GOOD;
		m_transfer_length = SCSILengthFromUINT16(&command[3]);
		break;

	default:
		m_device->logerror( "SCSIDEV unknown command %02x\n", command[ 0 ] );
		m_status_code = SCSI_STATUS_CODE_GOOD;
		m_transfer_length = 0;
		break;
	}
}

void t10spc::ReadData( uint8_t *data, int dataLength )
{
	switch( command[ 0 ] )
	{
	case T10SPC_CMD_REQUEST_SENSE:
		if (command[4] == 0)
		{
			data[0] = m_sense_asc & 0x7f;
			put_u24be(&data[1], m_sense_information & 0x1fffff);
		}
		else
		{
			data[0] = 0x70;
			data[1] = 0;
			data[2] = m_sense_key & 0xf;
			put_u32be(&data[3], m_sense_information);
			data[7] = 10;
			data[8] = 0;
			data[9] = 0;
			data[10] = 0;
			data[11] = 0;
			data[12] = m_sense_asc;
			data[13] = m_sense_ascq;
			data[14] = 0;
			data[15] = 0;
			data[16] = 0;
			data[17] = 0;
		}

		set_sense(SCSI_SENSE_KEY_NO_SENSE, SCSI_SENSE_ASC_ASCQ_NO_SENSE);
		break;

	default:
		m_device->logerror( "SCSIDEV unknown read %02x\n", command[ 0 ] );
		break;
	}
}

void t10spc::WriteData( uint8_t *data, int dataLength )
{
	switch( command[ 0 ] )
	{
	case T10SPC_CMD_SEND_DIAGNOSTIC:
		break;

	default:
		m_device->logerror( "SCSIDEV unknown write %02x\n", command[ 0 ] );
		break;
	}
}

void t10spc::SetCommand( uint8_t *_command, int _commandLength )
{
	if( _commandLength > sizeof( command ) )
	{
		/// TODO: output an error.
		return;
	}

	memcpy( command, _command, _commandLength );
	commandLength = _commandLength;

	m_phase = SCSI_PHASE_COMMAND;
}