scsi devices are now proper mame devices.

This commit is contained in:
smf- 2012-05-31 19:19:13 +00:00
parent 4dd00ac350
commit 86e540adf2
27 changed files with 950 additions and 1303 deletions

View File

@ -2,11 +2,12 @@
#include "emu.h"
#include "53c810.h"
#include "machine/scsidev.h"
#define DMA_MAX_ICOUNT 512 /* Maximum number of DMA Scripts opcodes to run */
#define DASM_OPCODES 0
static SCSIInstance *devices[8]; /* SCSI IDs 0-7 */
static scsidev_device *devices[8]; /* SCSI IDs 0-7 */
static const struct LSI53C810interface *intf;
static UINT8 last_id;
@ -707,17 +708,7 @@ void lsi53c810_init(running_machine &machine, const struct LSI53C810interface *i
// try to open the devices
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
}
}
void lsi53c810_exit(const struct LSI53C810interface *interface)
{
int i;
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
devices[interface->scsidevs->devices[i].scsiID] = machine.device<scsidev_device>( interface->scsidevs->devices[i].tag );
}
}
@ -725,7 +716,7 @@ void lsi53c810_read_data(int bytes, UINT8 *pData)
{
if (devices[last_id])
{
SCSIReadData( devices[last_id], pData, bytes);
devices[last_id]->ReadData( pData, bytes);
}
else
{
@ -737,7 +728,7 @@ void lsi53c810_write_data(int bytes, UINT8 *pData)
{
if (devices[last_id])
{
SCSIWriteData( devices[last_id], pData, bytes );
devices[last_id]->WriteData( pData, bytes );
}
else
{
@ -752,7 +743,7 @@ void *lsi53c810_get_device(int id)
if (devices[id])
{
logerror("lsi53c810: fetching dev pointer for SCSI ID %d\n", id);
SCSIGetDevice( devices[id], &ret );
devices[id]->GetDevice( &ret );
return ret;
}

View File

@ -12,7 +12,6 @@ struct LSI53C810interface
};
extern void lsi53c810_init(running_machine &machine, const struct LSI53C810interface *interface);
extern void lsi53c810_exit(const struct LSI53C810interface *interface);
extern void lsi53c810_read_data(int bytes, UINT8 *pData);
extern void lsi53c810_write_data(int bytes, UINT8 *pData);

View File

@ -11,11 +11,12 @@
#include "emu.h"
#include "am53cf96.h"
#include "machine/scsidev.h"
static UINT8 scsi_regs[32], fifo[16], fptr = 0, xfer_state, last_id;
static const struct AM53CF96interface *intf;
static SCSIInstance *devices[8]; // SCSI IDs 0-7
static scsidev_device *devices[8]; // SCSI IDs 0-7
// 53CF96 register set
enum
@ -147,7 +148,7 @@ WRITE32_HANDLER( am53cf96_w )
logerror("53cf96: reset target ID = %d (PC = %x)\n", last_id, cpu_get_pc(&space->device()));
if (devices[last_id])
{
SCSIReset( devices[last_id] );
devices[last_id]->reset();
}
else
{
@ -177,8 +178,8 @@ WRITE32_HANDLER( am53cf96_w )
{
int length;
SCSISetCommand( devices[last_id], &fifo[1], 12 );
SCSIExecCommand( devices[last_id], &length );
devices[last_id]->SetCommand( &fifo[1], 12 );
devices[last_id]->ExecCommand( &length );
}
else
{
@ -221,7 +222,7 @@ void am53cf96_init( running_machine &machine, const struct AM53CF96interface *in
// try to open the devices
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
devices[interface->scsidevs->devices[i].scsiID] = machine.device<scsidev_device>( interface->scsidevs->devices[i].tag );
}
state_save_register_global_array(machine, scsi_regs);
@ -231,16 +232,6 @@ void am53cf96_init( running_machine &machine, const struct AM53CF96interface *in
state_save_register_global(machine, last_id);
}
void am53cf96_exit( const struct AM53CF96interface *interface )
{
int i;
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
}
}
// retrieve data from the SCSI controller
void am53cf96_read_data(int bytes, UINT8 *pData)
{
@ -248,7 +239,7 @@ void am53cf96_read_data(int bytes, UINT8 *pData)
if (devices[last_id])
{
SCSIReadData( devices[last_id], pData, bytes );
devices[last_id]->ReadData( pData, bytes );
}
else
{
@ -265,7 +256,7 @@ void am53cf96_write_data(int bytes, UINT8 *pData)
if (devices[last_id])
{
SCSIWriteData( devices[last_id], pData, bytes );
devices[last_id]->WriteData( pData, bytes );
}
else
{
@ -281,7 +272,7 @@ void *am53cf96_get_device(int id)
if (devices[id])
{
logerror("53cf96: fetching dev pointer for SCSI ID %d\n", id);
SCSIGetDevice( devices[id], &ret );
devices[id]->GetDevice( &ret );
return ret;
}

View File

@ -15,7 +15,6 @@ struct AM53CF96interface
};
extern void am53cf96_init( running_machine &machine, const struct AM53CF96interface *interface );
extern void am53cf96_exit( const struct AM53CF96interface *interface );
extern void am53cf96_read_data(int bytes, UINT8 *pData);
void am53cf96_write_data(int bytes, UINT8 *pData);
void *am53cf96_get_device(int id);

View File

@ -4,153 +4,119 @@
*/
#include "emu.h"
#include "cr589.h"
#include "machine/cr589.h"
typedef struct
// device type definition
const device_type CR589 = &device_creator<cr589_device>;
cr589_device::cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsicd_device(mconfig, CR589, "CR589", tag, owner, clock)
{
int download;
UINT8 buffer[ 65536 ];
int bufferOffset;
} SCSICr589;
}
static const int identity_offset = 0x3ab;
static const char download_identity[] = "MATSHITA CD98Q4 DOWNLOADGS0N";
static int cr589_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
void cr589_device::device_start()
{
scsicd_device::device_start();
download = 0;
memcpy( &buffer[ identity_offset ], "MATSHITACD-ROM CR-589 GS0N", 28 );
save_item(NAME(download));
save_item(NAME(buffer));
save_item(NAME(bufferOffset));
}
void cr589_device::ExecCommand( int *transferLength )
{
UINT8 *command;
int commandLength;
SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
case 0x3b: // WRITE BUFFER
our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
break;
case 0x3c: // READ BUFFER
our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
break;
case 0xcc: // FIRMWARE DOWNLOAD ENABLE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT16( &command[7] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT16( &command[7] );
break;
default:
return SCSIBase( &SCSIClassCr589, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
scsicd_device::ExecCommand( transferLength );
}
}
static void cr589_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void cr589_device::ReadData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
case 0x12: // INQUIRY
SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
scsicd_device::ReadData( data, dataLength );
if( our_this->download )
if( download )
{
memcpy( &data[ 8 ], download_identity, 28 );
}
else
{
memcpy( &data[ 8 ], &our_this->buffer[ identity_offset ], 28 );
memcpy( &data[ 8 ], &buffer[ identity_offset ], 28 );
}
break;
case 0x3c: // READ BUFFER
memcpy( data, &our_this->buffer[ our_this->bufferOffset ], dataLength );
our_this->bufferOffset += dataLength;
memcpy( data, &buffer[ bufferOffset ], dataLength );
bufferOffset += dataLength;
break;
default:
SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
scsicd_device::ReadData( data, dataLength );
break;
}
}
static void cr589_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void cr589_device::WriteData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
case 0x3b: // WRITE BUFFER
memcpy( &our_this->buffer[ our_this->bufferOffset ], data + 32, dataLength - 32 );
our_this->bufferOffset += dataLength;
memcpy( &buffer[ bufferOffset ], data + 32, dataLength - 32 );
bufferOffset += dataLength;
break;
case 0xcc: // FIRMWARE DOWNLOAD ENABLE
if( memcmp( data, &our_this->buffer[ identity_offset ], 28 ) == 0 )
if( memcmp( data, &buffer[ identity_offset ], 28 ) == 0 )
{
our_this->download = 1;
download = 1;
}
else if( memcmp( data, download_identity, 28 ) == 0 )
{
our_this->download = 0;
download = 0;
}
break;
default:
SCSIBase( &SCSIClassCr589, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
scsicd_device::WriteData( data, dataLength );
break;
}
}
static void cr589_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
{
running_machine &machine = scsiInstance->machine();
SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
our_this->download = 0;
memcpy( &our_this->buffer[ identity_offset ], "MATSHITACD-ROM CR-589 GS0N", 28 );
state_save_register_item( machine, "cr589", diskregion, 0, our_this->download );
state_save_register_item_array( machine, "cr589", diskregion, 0, our_this->buffer );
state_save_register_item( machine, "cr589", diskregion, 0, our_this->bufferOffset );
}
static int cr589_dispatch( int operation, void *file, INT64 intparm, void *ptrparm )
{
SCSIAllocInstanceParams *params;
switch( operation )
{
case SCSIOP_EXEC_COMMAND:
return cr589_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
cr589_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_WRITE_DATA:
cr589_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
SCSIBase( &SCSIClassCr589, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
cr589_alloc_instance( params->instance, params->diskregion );
return 0;
}
return SCSIBase( &SCSIClassCr589, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
}
const SCSIClass SCSIClassCr589 =
{
&SCSIClassCDROM,
cr589_dispatch,
sizeof( SCSICr589 )
};

View File

@ -1,3 +1,24 @@
#include "scsi.h"
#include "scsicd.h"
extern const SCSIClass SCSIClassCr589;
class cr589_device : public scsicd_device
{
public:
// construction/destruction
cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void ExecCommand( int *transferLength );
virtual void WriteData( UINT8 *data, int dataLength );
virtual void ReadData( UINT8 *data, int dataLength );
protected:
// device-level overrides
virtual void device_start();
private:
int download;
UINT8 buffer[ 65536 ];
int bufferOffset;
};
// device type definition
extern const device_type CR589;

View File

@ -160,10 +160,8 @@ void ncr539x_device::device_start()
// try to open the devices
for (i = 0; i < scsidevs->devs_present; i++)
{
SCSIAllocInstance( machine(),
scsidevs->devices[i].scsiClass,
&m_scsi_devices[scsidevs->devices[i].scsiID],
scsidevs->devices[i].diskregion );
m_scsi_devices[scsidevs->devices[i].scsiID] = machine().device<scsidev_device>( scsidevs->devices[i].tag );
assert( m_scsi_devices[scsidevs->devices[i].scsiID] != NULL );
}
m_operation_timer = timer_alloc(0, NULL);
@ -197,27 +195,13 @@ void ncr539x_device::device_reset()
scan_devices();
}
//-------------------------------------------------
// device_stop - device-specific stop/shutdown
//-------------------------------------------------
void ncr539x_device::device_stop()
{
int i;
// clean up the devices
for (i = 0; i < scsidevs->devs_present; i++)
{
SCSIDeleteInstance( m_scsi_devices[scsidevs->devices[i].scsiID] );
}
}
void ncr539x_device::dma_read_data(int bytes, UINT8 *pData)
{
if (m_scsi_devices[m_last_id])
{
if (VERBOSE)
logerror("NCR539x: issuing read for %d bytes\n", bytes);
SCSIReadData(m_scsi_devices[m_last_id], pData, bytes);
m_scsi_devices[m_last_id]->ReadData(pData, bytes);
}
else
{
@ -232,7 +216,7 @@ void ncr539x_device::dma_write_data(int bytes, UINT8 *pData)
{
if (m_scsi_devices[m_last_id])
{
SCSIWriteData(m_scsi_devices[m_last_id], pData, bytes);
m_scsi_devices[m_last_id]->WriteData(pData, bytes);
}
else
{
@ -251,10 +235,7 @@ void ncr539x_device::scan_devices()
// if a device wasn't already allocated
if (!m_scsi_devices[scsidevs->devices[i].scsiID])
{
SCSIAllocInstance( machine(),
scsidevs->devices[i].scsiClass,
&m_scsi_devices[scsidevs->devices[i].scsiID],
scsidevs->devices[i].diskregion );
m_scsi_devices[scsidevs->devices[i].scsiID] = machine().device<scsidev_device>( scsidevs->devices[i].tag );
}
}
}
@ -589,7 +570,7 @@ WRITE8_MEMBER( ncr539x_device::write )
m_irq_status = IRQ_STATUS_SUCCESS;
int phase;
SCSIGetPhase( m_scsi_devices[m_last_id], &phase );
m_scsi_devices[m_last_id]->GetPhase( &phase );
#if VERBOSE
printf("Information transfer: phase %d buffer remaining %x\n", phase, m_buffer_remaining);
@ -613,7 +594,7 @@ WRITE8_MEMBER( ncr539x_device::write )
if (amtToGet > 0)
{
SCSIReadData(m_scsi_devices[m_last_id], m_buffer, amtToGet);
m_scsi_devices[m_last_id]->ReadData(m_buffer, amtToGet);
m_total_data -= amtToGet;
m_buffer_offset = 0;
@ -811,9 +792,9 @@ void ncr539x_device::exec_fifo()
{
int length, phase;
SCSISetCommand(m_scsi_devices[m_last_id], &m_fifo[0], 12);
SCSIExecCommand(m_scsi_devices[m_last_id], &length);
SCSIGetPhase(m_scsi_devices[m_last_id], &phase);
m_scsi_devices[m_last_id]->SetCommand(&m_fifo[0], 12);
m_scsi_devices[m_last_id]->ExecCommand(&length);
m_scsi_devices[m_last_id]->GetPhase(&phase);
#if VERBOSE
printf("Command executed (id %d), new phase %d, length %x\n", m_last_id, phase, length);
@ -874,7 +855,7 @@ void ncr539x_device::fifo_write(UINT8 data)
#if VERBOSE
printf("Flushing buffer to device, %x bytes left in buffer (%x total)\n", m_xfer_count, m_total_data);
#endif
SCSIWriteData(m_scsi_devices[m_last_id], m_buffer, flush_size);
m_scsi_devices[m_last_id]->WriteData(m_buffer, flush_size);
m_buffer_offset = 0;
// need a service request here too

View File

@ -6,6 +6,7 @@
#ifndef _NCR539x_H_
#define _NCR539x_H_
#include "machine/scsi.h"
#include "machine/scsidev.h"
struct NCR539Xinterface
@ -46,7 +47,6 @@ protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_stop();
virtual void device_config_complete();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
@ -56,7 +56,7 @@ private:
void exec_fifo();
void update_fifo_internal_state(int bytes);
SCSIInstance *m_scsi_devices[8];
scsidev_device *m_scsi_devices[8];
UINT32 m_xfer_count;
UINT32 m_dma_size;

View File

@ -1,147 +1,4 @@
#include "emu.h"
#include "scsi.h"
void SCSIAllocInstance( running_machine &machine, const SCSIClass *scsiClass, SCSIInstance **instance, const char *diskregion )
{
SCSIAllocInstanceParams params;
params.instance = NULL;
params.diskregion = diskregion;
params.m_machine = &machine;
scsiClass->dispatch( SCSIOP_ALLOC_INSTANCE, (void *)scsiClass, 0, &params );
*instance = params.instance;
}
void SCSIDeleteInstance( SCSIInstance *instance )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_DELETE_INSTANCE, instance, 0, NULL );
}
}
void SCSISetDevice( SCSIInstance *instance, void *device )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_SET_DEVICE, instance, 0, device );
}
}
void SCSIGetDevice( SCSIInstance *instance, void **device )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_GET_DEVICE, instance, 0, device );
}
}
void SCSIReset( SCSIInstance *instance )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_RESET_DEVICE, instance, 0, NULL );
}
}
void SCSIExecCommand( SCSIInstance *instance, int *resultLength )
{
if (instance)
{
*resultLength = instance->scsiClass->dispatch( SCSIOP_EXEC_COMMAND, instance, 0, NULL );
}
}
void SCSISetCommand( SCSIInstance *instance, UINT8 *command, int commandLength )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_SET_COMMAND, instance, commandLength, command );
}
}
void SCSIGetCommand( SCSIInstance *instance, UINT8 **command, int *commandLength )
{
if (instance)
{
*commandLength = instance->scsiClass->dispatch( SCSIOP_GET_COMMAND, instance, 0, command );
}
}
void SCSIWriteData( SCSIInstance *instance, void *data, int dataLength )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_WRITE_DATA, instance, dataLength, data );
}
}
void SCSIReadData( SCSIInstance *instance, void *data, int dataLength )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_READ_DATA, instance, dataLength, data );
}
}
void SCSISetPhase( SCSIInstance *instance, int phase )
{
if (instance)
{
instance->scsiClass->dispatch( SCSIOP_SET_PHASE, instance, phase, NULL );
}
}
void SCSIGetPhase( SCSIInstance *instance, int *phase )
{
if (instance)
{
*phase = instance->scsiClass->dispatch( SCSIOP_GET_PHASE, instance, 0, NULL );
}
}
int SCSIBase( const SCSIClass *scsiClass, int operation, void *file, INT64 intparm, UINT8 *ptrparm )
{
return scsiClass->baseClass->dispatch( operation, file, intparm, ptrparm );
}
SCSIInstance *SCSIMalloc( running_machine &machine, const SCSIClass *scsiClass )
{
SCSIInstance *scsiInstance = (SCSIInstance *)auto_alloc_array(machine, UINT8, SCSISizeof( scsiClass ));
scsiInstance->scsiClass = scsiClass;
scsiInstance->m_machine = &machine;
return scsiInstance;
}
void *SCSIThis( const SCSIClass *scsiClass, SCSIInstance *instance )
{
if( instance != NULL )
{
int sizeofBase = sizeof( SCSIInstance );
while( scsiClass->baseClass != NULL )
{
scsiClass = scsiClass->baseClass;
sizeofBase += scsiClass->sizeofData;
}
return ( (UINT8*)instance ) + sizeofBase;
}
return NULL;
}
int SCSISizeof( const SCSIClass *scsiClass )
{
int sizeofData = sizeof( SCSIInstance );
while( scsiClass != NULL )
{
sizeofData += scsiClass->sizeofData;
scsiClass = scsiClass->baseClass;
}
return sizeofData;
}
int SCSILengthFromUINT8( UINT8 *length )
{

View File

@ -8,53 +8,10 @@
#ifndef _SCSI_H_
#define _SCSI_H_
typedef int (*pSCSIDispatch)( int operation, void *file, INT64 intparm, void *ptrparm );
typedef struct _SCSIClass
{
const struct _SCSIClass *baseClass;
pSCSIDispatch dispatch;
int sizeofData;
} SCSIClass;
typedef struct
{
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
const SCSIClass *scsiClass;
running_machine *m_machine;
} SCSIInstance;
typedef struct
{
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
SCSIInstance *instance;
const char *diskregion;
running_machine *m_machine;
} SCSIAllocInstanceParams;
// commands accepted by a SCSI device's dispatch handler
enum
{
SCSIOP_EXEC_COMMAND = 0, // execute a command packet
SCSIOP_SET_COMMAND, // set a command packet
SCSIOP_GET_COMMAND, // get a command packet
SCSIOP_READ_DATA, // data transfer from the device
SCSIOP_WRITE_DATA, // data transfer to the device
SCSIOP_ALLOC_INSTANCE, // allocate an instance of the device
SCSIOP_DELETE_INSTANCE, // delete an instance of the device
SCSIOP_GET_DEVICE, // get the device's internal device (CDROM or HDD pointer)
SCSIOP_SET_DEVICE, // set the device's internal device (CDROM or HDD pointer)
SCSIOP_RESET_DEVICE, // reset the device
SCSIOP_SET_PHASE,
SCSIOP_GET_PHASE,
};
typedef struct scsiconfigitem
{
int scsiID;
const char *diskregion;
const SCSIClass *scsiClass;
const char *tag;
} SCSIConfigItem;
#define SCSI_MAX_DEVICES (16)
@ -78,36 +35,4 @@ enum
SCSI_ID_7
};
#define SCSI_PHASE_DATAOUT ( 0 )
#define SCSI_PHASE_DATAIN ( 1 )
#define SCSI_PHASE_COMMAND ( 2 )
#define SCSI_PHASE_STATUS ( 3 )
#define SCSI_PHASE_MESSAGE_OUT ( 6 )
#define SCSI_PHASE_MESSAGE_IN ( 7 )
extern void SCSIAllocInstance( running_machine &machine, const SCSIClass *scsiClass, SCSIInstance **instance, const char *diskregion );
extern void SCSIDeleteInstance( SCSIInstance *instance );
extern void SCSISetDevice( SCSIInstance *instance, void *device );
extern void SCSIGetDevice( SCSIInstance *instance, void **device );
extern void SCSIReset( SCSIInstance *instance );
extern void SCSISetCommand( SCSIInstance *instance, UINT8 *command, int commandLength );
extern void SCSIGetCommand( SCSIInstance *instance, UINT8 **command, int *commandLength );
extern void SCSIExecCommand( SCSIInstance *instance, int *resultLength );
extern void SCSIWriteData( SCSIInstance *instance, void *data, int dataLength );
extern void SCSIReadData( SCSIInstance *instance, void *data, int dataLength );
extern void SCSISetPhase( SCSIInstance *instance, int phase );
extern void SCSIGetPhase( SCSIInstance *instance, int *phase );
extern SCSIInstance *SCSIMalloc( running_machine &machine, const SCSIClass *scsiClass );
extern int SCSIBase( const SCSIClass *scsiClass, int operation, void *file, INT64 intparm, UINT8 *ptrparm );
extern void *SCSIThis( const SCSIClass *scsiClass, SCSIInstance *instance );
extern int SCSISizeof( const SCSIClass *scsiClass );
extern int SCSILengthFromUINT8( UINT8 *length );
extern int SCSILengthFromUINT16( UINT8 *length );
#endif
// include these here to avoid changing the drivers.
#include "machine/scsicd.h"
#include "machine/scsihd.h"

View File

@ -11,19 +11,6 @@
#include "imagedev/chd_cd.h"
#include "scsicd.h"
typedef struct
{
UINT32 lba;
UINT32 blocks;
UINT32 last_lba;
UINT32 bytes_per_sector;
UINT32 num_subblocks;
UINT32 cur_subblock;
UINT32 play_err_flag;
cdrom_file *cdrom;
bool is_file;
} SCSICd;
static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
{
*m = phys_frame / (60*75);
@ -32,90 +19,172 @@ static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
*f = phys_frame % 75;
}
// device type definition
const device_type SCSICD = &device_creator<scsicd_device>;
scsicd_device::scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsidev_device(mconfig, SCSICD, "SCSICD", tag, owner, clock)
{
}
scsicd_device::scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
scsidev_device(mconfig, type, name, tag, owner, clock)
{
}
void scsicd_device::device_start()
{
save_item( NAME( lba ) );
save_item( NAME( blocks ) );
save_item( NAME( last_lba ) );
save_item( NAME( bytes_per_sector ) );
save_item( NAME( num_subblocks ) );
save_item( NAME( cur_subblock ) );
save_item( NAME( play_err_flag ) );
}
void scsicd_device::device_reset()
{
scsidev_device::device_reset();
is_file = TRUE;
cdrom = subdevice<cdrom_image_device>("image")->get_cdrom_file();
if( !cdrom )
{
// try to locate the CHD from a DISK_REGION
chd_file *chd = get_disk_handle( machine(), tag() );
if( chd != NULL )
{
is_file = FALSE;
cdrom = cdrom_open( chd );
}
}
if( !cdrom )
{
logerror( "SCSICD %s: no CD found!\n", tag() );
}
lba = 0;
blocks = 0;
last_lba = 0;
bytes_per_sector = 2048;
num_subblocks = 1;
cur_subblock = 0;
play_err_flag = 0;
}
void scsicd_device::device_stop()
{
if (!is_file)
{
if( cdrom )
{
cdrom_close( cdrom );
}
}
}
cdrom_interface scsicd_device::cd_intf = { 0, 0 };
static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
MCFG_CDROM_ADD("image", scsicd_device::cd_intf)
MACHINE_CONFIG_END
machine_config_constructor scsicd_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(scsi_cdrom);
}
// scsicd_exec_command
//
// Execute a SCSI command.
static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
void scsicd_device::ExecCommand( int *transferLength )
{
UINT8 *command;
int commandLength;
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
cdrom_file *cdrom = our_this->cdrom;
device_t *cdda;
int trk;
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch ( command[0] )
{
case 0x03: // REQUEST SENSE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x12: // INQUIRY
logerror("SCSICD: REQUEST SENSE\n");
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x15: // MODE SELECT(6)
logerror("SCSICD: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x1a: // MODE SENSE(6)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x1b: // START STOP UNIT
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x25: // READ CAPACITY
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return 8;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = 8;
break;
case 0x28: // READ(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
logerror("SCSICD: READ(10) at LBA %x for %d blocks (%d bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
logerror("SCSICD: READ(10) at LBA %x for %d blocks (%d bytes)\n", lba, blocks, blocks * bytes_per_sector);
if (our_this->num_subblocks > 1)
if (num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
cur_subblock = lba % num_subblocks;
lba /= num_subblocks;
}
else
{
our_this->cur_subblock = 0;
cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * bytes_per_sector;
break;
case 0x42: // READ SUB-CHANNEL
// logerror("SCSICD: READ SUB-CHANNEL type %d\n", command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0x43: // READ TOC
{
@ -143,161 +212,170 @@ static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
length = 4;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return length;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = length;
break;
}
case 0x45: // PLAY AUDIO(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
if (lba == 0)
{
our_this->lba = 150;
lba = 150;
}
else if (our_this->lba == 0xffffffff)
else if (lba == 0xffffffff)
{
logerror("SCSICD: play audio from current not implemented!\n");
}
logerror("SCSICD: PLAY AUDIO(10) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSICD: PLAY AUDIO(10) at LBA %x for %x blocks\n", lba, blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
trk = cdrom_get_track(cdrom, lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
play_err_flag = 0;
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
else
{
logerror("SCSICD: track is NOT audio!\n");
our_this->play_err_flag = 1;
play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x48: // PLAY AUDIO TRACK/INDEX
// be careful: tracks here are zero-based, but the SCSI command
// uses the real CD track number which is 1-based!
our_this->lba = cdrom_get_track_start(cdrom, command[4]-1);
our_this->blocks = cdrom_get_track_start(cdrom, command[7]-1) - our_this->lba;
lba = cdrom_get_track_start(cdrom, command[4]-1);
blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
if (command[4] > command[7])
{
our_this->blocks = 0;
blocks = 0;
}
if (command[4] == command[7])
{
our_this->blocks = cdrom_get_track_start(cdrom, command[4]) - our_this->lba;
blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
}
if (our_this->blocks && cdrom)
if (blocks && cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
logerror("SCSICD: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], our_this->blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
logerror("SCSICD: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x4b: // PAUSE/RESUME
if (cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_pause_audio(cdda, (command[8] & 0x01) ^ 0x01);
}
logerror("SCSICD: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x55: // MODE SELECT(10)
logerror("SCSICD: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0x5a: // MODE SENSE(10)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0xa5: // PLAY AUDIO(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
if (lba == 0)
{
our_this->lba = 150;
lba = 150;
}
else if (our_this->lba == 0xffffffff)
else if (lba == 0xffffffff)
{
logerror("SCSICD: play audio from current not implemented!\n");
}
logerror("SCSICD: PLAY AUDIO(12) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSICD: PLAY AUDIO(12) at LBA %x for %x blocks\n", lba, blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
trk = cdrom_get_track(cdrom, lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
play_err_flag = 0;
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
else
{
logerror("SCSICD: track is NOT audio!\n");
our_this->play_err_flag = 1;
play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0xa8: // READ(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[7]<<16 | command[8]<<8 | command[9];
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = command[7]<<16 | command[8]<<8 | command[9];
logerror("SCSICD: READ(12) at LBA %x for %x blocks (%x bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
logerror("SCSICD: READ(12) at LBA %x for %x blocks (%x bytes)\n", lba, blocks, blocks * bytes_per_sector);
if (our_this->num_subblocks > 1)
if (num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
cur_subblock = lba % num_subblocks;
lba /= num_subblocks;
}
else
{
our_this->cur_subblock = 0;
cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * bytes_per_sector;
break;
case 0xbb: // SET CD SPEED
logerror("SCSICD: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
default:
return SCSIBase( &SCSIClassCDROM, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
scsidev_device::ExecCommand( transferLength );
}
}
@ -305,20 +383,18 @@ static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
//
// Read data from the device resulting from the execution of a command
static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void scsicd_device::ReadData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
int i;
UINT32 last_phys_frame;
cdrom_file *cdrom = our_this->cdrom;
UINT32 temp;
UINT8 tmp_buffer[2048];
device_t *cdda;
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch ( command[0] )
{
@ -329,15 +405,15 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
data[0] = 0x71; // deferred error
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL && cdda_audio_active(cdda))
{
data[12] = 0x00;
data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS
}
else if (our_this->play_err_flag)
else if (play_err_flag)
{
our_this->play_err_flag = 0;
play_err_flag = 0;
data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK
data[13] = 0x00;
}
@ -369,38 +445,38 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
data[3] = (temp & 0xff);
data[4] = 0;
data[5] = 0;
data[6] = (our_this->bytes_per_sector>>8)&0xff;
data[7] = (our_this->bytes_per_sector & 0xff);
data[6] = (bytes_per_sector>>8)&0xff;
data[7] = (bytes_per_sector & 0xff);
break;
case 0x28: // READ(10)
case 0xa8: // READ(12)
logerror("SCSICD: read %x dataLength, \n", dataLength);
if ((our_this->cdrom) && (our_this->blocks))
if ((cdrom) && (blocks))
{
while (dataLength > 0)
{
if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
{
logerror("SCSICD: CD read error!\n");
}
logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
our_this->cur_subblock++;
if (our_this->cur_subblock >= our_this->num_subblocks)
cur_subblock++;
if (cur_subblock >= num_subblocks)
{
our_this->cur_subblock = 0;
cur_subblock = 0;
our_this->lba++;
our_this->blocks--;
lba++;
blocks--;
}
our_this->last_lba = our_this->lba;
dataLength -= our_this->bytes_per_sector;
data += our_this->bytes_per_sector;
last_lba = lba;
dataLength -= bytes_per_sector;
data += bytes_per_sector;
}
}
break;
@ -422,7 +498,7 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
msf = command[1] & 0x2;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
audio_active = cdda != NULL && cdda_audio_active(cdda);
if (audio_active)
{
@ -451,21 +527,21 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
// if audio is playing, get the latest LBA from the CDROM layer
if (audio_active)
{
our_this->last_lba = cdda_get_audio_lba(cdda);
last_lba = cdda_get_audio_lba(cdda);
}
else
{
our_this->last_lba = 0;
last_lba = 0;
}
data[2] = 0;
data[3] = 12; // data length
data[4] = 0x01; // sub-channel format code
data[5] = 0x10 | (audio_active ? 0 : 4);
data[6] = cdrom_get_track(cdrom, our_this->last_lba) + 1; // track
data[6] = cdrom_get_track(cdrom, last_lba) + 1; // track
data[7] = 0; // index
last_phys_frame = our_this->last_lba;
last_phys_frame = last_lba;
if (msf)
{
@ -635,7 +711,7 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
break;
default:
SCSIBase( &SCSIClassCDROM, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
scsidev_device::ReadData( data, dataLength );
break;
}
}
@ -644,12 +720,11 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
//
// Write data to the CD-ROM device as part of the execution of a command
static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void scsicd_device::WriteData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch (command[ 0 ])
{
@ -665,8 +740,8 @@ static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int data
{
logerror("SCSICD: Experimental SGI 512-byte block extension enabled\n");
our_this->bytes_per_sector = 512;
our_this->num_subblocks = 4;
bytes_per_sector = 512;
num_subblocks = 4;
}
else
{
@ -684,112 +759,17 @@ static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int data
break;
default:
SCSIBase( &SCSIClassCDROM, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
scsidev_device::WriteData( data, dataLength );
break;
}
}
static void scsicd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
void scsicd_device::GetDevice( void **_cdrom )
{
running_machine &machine = scsiInstance->machine();
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
our_this->lba = 0;
our_this->blocks = 0;
our_this->last_lba = 0;
our_this->bytes_per_sector = 2048;
our_this->num_subblocks = 1;
our_this->cur_subblock = 0;
our_this->play_err_flag = 0;
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->blocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->last_lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->bytes_per_sector );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->num_subblocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->cur_subblock );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->play_err_flag );
if (machine.device( diskregion )) {
our_this->is_file = TRUE;
cdrom_image_device *cdrom = machine.device<cdrom_image_device>(diskregion);
our_this->cdrom = cdrom->get_cdrom_file();
} else {
our_this->is_file = FALSE;
our_this->cdrom = cdrom_open(get_disk_handle( machine, diskregion ));
}
if (!our_this->cdrom)
{
logerror("SCSICD: no CD found!\n");
}
*(cdrom_file **)_cdrom = cdrom;
}
static void scsicd_delete_instance( SCSIInstance *scsiInstance )
void scsicd_device::SetDevice( void *_cdrom )
{
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
if (!our_this->is_file) {
if( our_this->cdrom )
{
cdrom_close( our_this->cdrom );
}
}
cdrom = (cdrom_file *)_cdrom;
}
static void scsicd_get_device( SCSIInstance *scsiInstance, cdrom_file **cdrom )
{
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
*cdrom = our_this->cdrom;
}
static void scsicd_set_device( SCSIInstance *scsiInstance, cdrom_file *cdrom )
{
SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
our_this->cdrom = cdrom;
}
static int scsicd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
{
SCSIAllocInstanceParams *params;
switch (operation)
{
case SCSIOP_EXEC_COMMAND:
return scsicd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
scsicd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_WRITE_DATA:
scsicd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
SCSIBase( &SCSIClassCDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
scsicd_alloc_instance( params->instance, params->diskregion );
return 0;
case SCSIOP_DELETE_INSTANCE:
scsicd_delete_instance( (SCSIInstance *)file );
break;
case SCSIOP_GET_DEVICE:
scsicd_get_device( (SCSIInstance *)file, (cdrom_file **)ptrparm );
return 0;
case SCSIOP_SET_DEVICE:
scsicd_set_device( (SCSIInstance *)file, (cdrom_file *)ptrparm );
return 0;
}
return SCSIBase( &SCSIClassCDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
}
const SCSIClass SCSIClassCDROM =
{
&SCSIClassDevice,
scsicd_dispatch,
sizeof( SCSICd )
};

View File

@ -7,11 +7,44 @@
#ifndef _SCSICD_H_
#define _SCSICD_H_
#include "machine/scsi.h"
#include "machine/scsidev.h"
#include "cdrom.h"
// CD-ROM handler
extern const SCSIClass SCSIClassCDROM;
#define SCSI_DEVICE_CDROM &SCSIClassCDROM
class scsicd_device : public scsidev_device
{
public:
// construction/destruction
scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
virtual machine_config_constructor device_mconfig_additions() const;
virtual void SetDevice( void *device );
virtual void GetDevice( void **device );
virtual void ExecCommand( int *transferLength );
virtual void WriteData( UINT8 *data, int dataLength );
virtual void ReadData( UINT8 *data, int dataLength );
static struct cdrom_interface cd_intf;
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_stop();
private:
UINT32 lba;
UINT32 blocks;
UINT32 last_lba;
UINT32 bytes_per_sector;
UINT32 num_subblocks;
UINT32 cur_subblock;
UINT32 play_err_flag;
cdrom_file *cdrom;
bool is_file;
};
// device type definition
extern const device_type SCSICD;
#endif

View File

@ -5,156 +5,94 @@
***************************************************************************/
#include "emu.h"
#include "scsidev.h"
#include "scsidev.h"
typedef struct
scsidev_device::scsidev_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, type, name, tag, owner, clock)
{
UINT8 command[16];
int commandLength;
int phase;
} SCSIDev;
}
static int scsidev_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
void scsidev_device::device_start()
{
save_item( NAME( command ) );
save_item( NAME( commandLength ) );
save_item( NAME( phase ) );
}
void scsidev_device::ExecCommand( int *transferLength )
{
UINT8 *command;
int commandLength;
// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
case 0x00: // TEST UNIT READY
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
default:
logerror( "%s: SCSIDEV unknown command %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
return 0;
}
}
static void scsidev_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
switch( command[ 0 ] )
{
default:
logerror( "%s: SCSIDEV unknown read %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
logerror( "%s: SCSIDEV unknown command %02x\n", machine().describe_context(), command[ 0 ] );
*transferLength = 0;
break;
}
}
static void scsidev_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void scsidev_device::ReadData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
default:
logerror( "%s: SCSIDEV unknown write %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
logerror( "%s: SCSIDEV unknown read %02x\n", machine().describe_context(), command[ 0 ] );
break;
}
}
static void scsidev_set_phase( SCSIInstance *scsiInstance, int phase )
void scsidev_device::WriteData( UINT8 *data, int dataLength )
{
SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
our_this->phase = phase;
UINT8 *command;
int commandLength;
GetCommand( &command, &commandLength );
switch( command[ 0 ] )
{
default:
logerror( "%s: SCSIDEV unknown write %02x\n", machine().describe_context(), command[ 0 ] );
break;
}
}
static int scsidev_get_phase( SCSIInstance *scsiInstance )
void scsidev_device::SetPhase( int _phase )
{
SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
return our_this->phase;
phase = _phase;
}
static void scsidev_set_command( SCSIInstance *scsiInstance, void *command, int commandLength )
void scsidev_device::GetPhase( int *_phase)
{
SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
*_phase = phase;
}
if( commandLength > sizeof( our_this->command ) )
void scsidev_device::SetCommand( UINT8 *_command, int _commandLength )
{
if( _commandLength > sizeof( command ) )
{
/// TODO: output an error.
return;
}
memcpy( our_this->command, command, commandLength );
our_this->commandLength = commandLength;
memcpy( command, _command, _commandLength );
commandLength = _commandLength;
SCSISetPhase( scsiInstance, SCSI_PHASE_COMMAND );
SetPhase( SCSI_PHASE_COMMAND );
}
static int scsidev_get_command( SCSIInstance *scsiInstance, void **command )
void scsidev_device::GetCommand( UINT8 **_command, int *_commandLength )
{
SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
*command = our_this->command;
return our_this->commandLength;
*_command = command;
*_commandLength = commandLength;
}
static void scsidev_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
{
running_machine &machine = scsiInstance->machine();
SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
state_save_register_item_array( machine, "scsidev", diskregion, 0, our_this->command );
state_save_register_item( machine, "scsidev", diskregion, 0, our_this->commandLength );
state_save_register_item( machine, "scsidev", diskregion, 0, our_this->phase );
}
static int scsidev_dispatch( int operation, void *file, INT64 intparm, void *ptrparm )
{
SCSIAllocInstanceParams *params;
switch( operation )
{
case SCSIOP_EXEC_COMMAND:
return scsidev_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
scsidev_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
break;
case SCSIOP_WRITE_DATA:
scsidev_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
break;
case SCSIOP_SET_PHASE:
scsidev_set_phase( (SCSIInstance *)file, intparm );
return 0;
case SCSIOP_GET_PHASE:
return scsidev_get_phase( (SCSIInstance *)file );
case SCSIOP_SET_COMMAND:
scsidev_set_command( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_GET_COMMAND:
return scsidev_get_command( (SCSIInstance *)file, (void **)ptrparm );
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
params->instance = SCSIMalloc( params->machine(), (const SCSIClass *)file );
scsidev_alloc_instance( params->instance, params->diskregion );
return 0;
case SCSIOP_DELETE_INSTANCE:
auto_free( ((SCSIInstance *)file)->machine(), file );
return 0;
}
return 0;
}
const SCSIClass SCSIClassDevice =
{
NULL,
scsidev_dispatch,
sizeof( SCSIDev )
};

View File

@ -7,9 +7,41 @@
#ifndef _SCSIDEV_H_
#define _SCSIDEV_H_
#include "machine/scsi.h"
// base handler
extern const SCSIClass SCSIClassDevice;
class scsidev_device : public device_t
{
public:
// construction/destruction
scsidev_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
virtual void SetDevice( void *device ) = 0;
virtual void GetDevice( void **device ) = 0;
virtual void SetCommand( UINT8 *command, int commandLength );
virtual void GetCommand( UINT8 **command, int *commandLength );
virtual void ExecCommand( int *transferLength );
virtual void WriteData( UINT8 *data, int dataLength );
virtual void ReadData( UINT8 *data, int dataLength );
virtual void SetPhase( int phase );
virtual void GetPhase( int *phase );
protected:
// device-level overrides
virtual void device_start();
private:
UINT8 command[16];
int commandLength;
int phase;
};
extern int SCSILengthFromUINT8( UINT8 *length );
extern int SCSILengthFromUINT16( UINT8 *length );
#define SCSI_PHASE_DATAOUT ( 0 )
#define SCSI_PHASE_DATAIN ( 1 )
#define SCSI_PHASE_COMMAND ( 2 )
#define SCSI_PHASE_STATUS ( 3 )
#define SCSI_PHASE_MESSAGE_OUT ( 6 )
#define SCSI_PHASE_MESSAGE_IN ( 7 )
#endif

View File

@ -10,114 +10,179 @@
#include "imagedev/harddriv.h"
#include "scsihd.h"
typedef struct
{
UINT32 lba;
UINT32 blocks;
int sectorbytes;
chd_file *handle;
hard_disk_file *disk;
bool is_image_device;
} SCSIHd;
// device type definition
const device_type SCSIHD = &device_creator<scsihd_device>;
scsihd_device::scsihd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsidev_device(mconfig, SCSIHD, "SCSIHD", tag, owner, clock)
{
}
void scsihd_device::device_start()
{
save_item( NAME( lba ) );
save_item( NAME( blocks ) );
}
void scsihd_device::device_reset()
{
scsidev_device::device_reset();
is_image_device = true;
disk = subdevice<harddisk_image_device>("image")->get_hard_disk_file();
if( !disk )
{
// try to locate the CHD from a DISK_REGION
chd_file *handle = get_disk_handle(machine(), tag());
if (handle != NULL)
{
is_image_device = false;
disk = hard_disk_open(handle);
}
}
lba = 0;
blocks = 0;
sectorbytes = 512;
if (!disk)
{
logerror("SCSIHD: no HD found!\n");
}
else
{
// get hard disk sector size from CHD metadata
const hard_disk_info *hdinfo = hard_disk_get_info(disk);
sectorbytes = hdinfo->sectorbytes;
}
}
void scsihd_device::device_stop()
{
if (!is_image_device)
{
if( disk )
{
hard_disk_close( disk );
}
}
}
static MACHINE_CONFIG_FRAGMENT(scsi_harddisk)
MCFG_HARDDISK_ADD("image")
MACHINE_CONFIG_END
machine_config_constructor scsihd_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(scsi_harddisk);
}
// scsihd_exec_command
static int scsihd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
void scsihd_device::ExecCommand( int *transferLength )
{
UINT8 *command;
int commandLength;
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch ( command[0] )
{
case 0x03: // REQUEST SENSE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x04: // FORMAT UNIT
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x08: // READ(6)
our_this->lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
our_this->blocks = SCSILengthFromUINT8( &command[4] );
lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
blocks = SCSILengthFromUINT8( &command[4] );
logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->sectorbytes;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * sectorbytes;
break;
case 0x0a: // WRITE(6)
our_this->lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
our_this->blocks = SCSILengthFromUINT8( &command[4] );
lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
blocks = SCSILengthFromUINT8( &command[4] );
logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", lba, blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return our_this->blocks * our_this->sectorbytes;
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = blocks * sectorbytes;
break;
case 0x12: // INQUIRY
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x15: // MODE SELECT (used to set CDDA volume)
logerror("SCSIHD: MODE SELECT length %x control %x\n", command[4], command[5]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x1a: // MODE SENSE(6)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x25: // READ CAPACITY
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return 8;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = 8;
break;
case 0x28: // READ(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->sectorbytes;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * sectorbytes;
break;
case 0x2a: // WRITE (10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", lba, blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
SetPhase( SCSI_PHASE_DATAOUT );
return our_this->blocks * our_this->sectorbytes;
*transferLength = blocks * sectorbytes;
break;
case 0xa8: // READ(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->sectorbytes;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * sectorbytes;
break;
default:
return SCSIBase( &SCSIClassHARDDISK, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
scsidev_device::ExecCommand( transferLength );
break;
}
}
static void scsihd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void scsihd_device::ReadData( UINT8 *data, int dataLength )
{
int i;
UINT8 *command;
int commandLength;
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
// if we're a drive without a disk, return all zeroes
if (!our_this->disk)
if (!disk)
{
memset(data, 0, dataLength);
return;
@ -160,18 +225,18 @@ static void scsihd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
case 0x08: // READ(6)
case 0x28: // READ(10)
case 0xa8: // READ(12)
if ((our_this->disk) && (our_this->blocks))
if ((disk) && (blocks))
{
while (dataLength > 0)
{
if (!hard_disk_read(our_this->disk, our_this->lba, data))
if (!hard_disk_read(disk, lba, data))
{
logerror("SCSIHD: HD read error!\n");
}
our_this->lba++;
our_this->blocks--;
dataLength -= our_this->sectorbytes;
data += our_this->sectorbytes;
lba++;
blocks--;
dataLength -= sectorbytes;
data += sectorbytes;
}
}
break;
@ -182,7 +247,7 @@ static void scsihd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
hard_disk_info *info;
UINT32 temp;
info = hard_disk_get_info(our_this->disk);
info = hard_disk_get_info(disk);
logerror("SCSIHD: READ CAPACITY\n");
@ -202,19 +267,18 @@ static void scsihd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
break;
default:
SCSIBase( &SCSIClassHARDDISK, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
scsidev_device::ReadData( data, dataLength );
break;
}
}
static void scsihd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void scsihd_device::WriteData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
if (!our_this->disk)
if (!disk)
{
return;
}
@ -223,151 +287,35 @@ static void scsihd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int data
{
case 0x0a: // WRITE(6)
case 0x2a: // WRITE(10)
if ((our_this->disk) && (our_this->blocks))
if ((disk) && (blocks))
{
while (dataLength > 0)
{
if (!hard_disk_write(our_this->disk, our_this->lba, data))
if (!hard_disk_write(disk, lba, data))
{
logerror("SCSIHD: HD write error!\n");
}
our_this->lba++;
our_this->blocks--;
dataLength -= our_this->sectorbytes;
data += our_this->sectorbytes;
lba++;
blocks--;
dataLength -= sectorbytes;
data += sectorbytes;
}
}
break;
default:
SCSIBase( &SCSIClassHARDDISK, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
scsidev_device::WriteData( data, dataLength );
break;
}
}
static void scsihd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
void scsihd_device::GetDevice( void **_disk )
{
running_machine &machine = scsiInstance->machine();
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
our_this->lba = 0;
our_this->blocks = 0;
our_this->sectorbytes = 512;
// Attempt to register save state entry after state registration is closed!
state_save_register_item( machine, "scsihd", diskregion, 0, our_this->lba );
state_save_register_item( machine, "scsihd", diskregion, 0, our_this->blocks );
// try to locate the CHD from a DISK_REGION
our_this->handle = get_disk_handle(machine, diskregion);
our_this->disk = hard_disk_open(our_this->handle);
our_this->is_image_device = false;
if (our_this->disk == NULL)
{
// try to locate the CHD from an image device
harddisk_image_device *image_device = machine.device<harddisk_image_device>(diskregion);
if (image_device != NULL)
{
our_this->handle = image_device->get_chd_file();
our_this->disk = hard_disk_open(our_this->handle);
our_this->is_image_device = true;
}
}
if (our_this->disk == NULL)
{
// try to locate the CHD from an image subdevice
device_iterator iter(machine.root_device());
for (device_t *device = iter.first(); device != NULL; device = iter.next())
{
if (device->subdevice(diskregion) != NULL)
{
our_this->handle = device->subdevice<harddisk_image_device>(diskregion)->get_chd_file();
our_this->disk = hard_disk_open(our_this->handle);
our_this->is_image_device = true;
}
}
}
if (our_this->disk != NULL)
{
// get hard disk sector size from CHD metadata
const hard_disk_info *hdinfo = hard_disk_get_info(our_this->disk);
our_this->sectorbytes = hdinfo->sectorbytes;
}
else
{
logerror("SCSIHD: no HD found!\n");
}
*(hard_disk_file **)_disk = disk;
}
static void scsihd_delete_instance( SCSIInstance *scsiInstance )
void scsihd_device::SetDevice( void *_disk )
{
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
if (!our_this->is_image_device) {
if( our_this->disk )
{
hard_disk_close( our_this->disk );
}
}
disk = (hard_disk_file *)_disk;
}
static void scsihd_get_device( SCSIInstance *scsiInstance, hard_disk_file **disk )
{
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
*disk = our_this->disk;
}
static void scsihd_set_device( SCSIInstance *scsiInstance, hard_disk_file *disk )
{
SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
our_this->disk = disk;
}
static int scsihd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
{
SCSIAllocInstanceParams *params;
switch (operation)
{
case SCSIOP_EXEC_COMMAND:
return scsihd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
scsihd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_WRITE_DATA:
scsihd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
SCSIBase( &SCSIClassHARDDISK, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
scsihd_alloc_instance( params->instance, params->diskregion );
return 0;
case SCSIOP_DELETE_INSTANCE:
scsihd_delete_instance( (SCSIInstance *)file );
break;
case SCSIOP_GET_DEVICE:
scsihd_get_device( (SCSIInstance *)file, (hard_disk_file **)ptrparm );
return 0;
case SCSIOP_SET_DEVICE:
scsihd_set_device( (SCSIInstance *)file, (hard_disk_file *)ptrparm );
return 0;
}
return SCSIBase( &SCSIClassHARDDISK, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
}
const SCSIClass SCSIClassHARDDISK =
{
&SCSIClassDevice,
scsihd_dispatch,
sizeof( SCSIHd )
};

View File

@ -7,10 +7,37 @@
#ifndef _SCSIHD_H_
#define _SCSIHD_H_
#include "machine/scsi.h"
#include "machine/scsidev.h"
#include "harddisk.h"
// CD-ROM handler
extern const SCSIClass SCSIClassHARDDISK;
#define SCSI_DEVICE_HARDDISK &SCSIClassHARDDISK
class scsihd_device : public scsidev_device
{
public:
// construction/destruction
scsihd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual machine_config_constructor device_mconfig_additions() const;
virtual void SetDevice( void *device );
virtual void GetDevice( void **device );
virtual void ExecCommand( int *transferLength );
virtual void WriteData( UINT8 *data, int dataLength );
virtual void ReadData( UINT8 *data, int dataLength );
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_stop();
private:
UINT32 lba;
UINT32 blocks;
int sectorbytes;
hard_disk_file *disk;
bool is_image_device;
};
// device type definition
extern const device_type SCSIHD;
#endif

View File

@ -13,11 +13,12 @@
#include "emu.h"
#include "wd33c93.h"
#include "machine/scsidev.h"
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
static SCSIInstance *devices[8]; // SCSI IDs 0-7
static scsidev_device *devices[8]; // SCSI IDs 0-7
static const struct WD33C93interface *intf;
/* wd register names */
@ -227,7 +228,7 @@ static void wd33c93_read_data(int bytes, UINT8 *pData)
if ( devices[unit] )
{
SCSIReadData( devices[unit], pData, bytes );
devices[unit]->ReadData( pData, bytes );
}
else
{
@ -379,9 +380,9 @@ static CMD_HANDLER( wd33c93_selectxfer_cmd )
int phase;
/* do the request */
SCSISetCommand( devices[unit], &scsi_data.regs[WD_CDB_1], 12 );
SCSIExecCommand( devices[unit], &xfercount );
SCSIGetPhase( devices[unit], &phase );
devices[unit]->SetCommand( &scsi_data.regs[WD_CDB_1], 12 );
devices[unit]->ExecCommand( &xfercount );
devices[unit]->GetPhase( &phase );
/* set transfer count */
if ( wd33c93_get_xfer_count() > TEMP_INPUT_LEN )
@ -592,9 +593,9 @@ WRITE8_HANDLER(wd33c93_w)
int phase;
/* Execute the command. Depending on the command, we'll move to data in or out */
SCSISetCommand( devices[unit], &scsi_data.fifo[0], 12 );
SCSIExecCommand( devices[unit], &xfercount );
SCSIGetPhase( devices[unit], &phase );
devices[unit]->SetCommand( &scsi_data.fifo[0], 12 );
devices[unit]->ExecCommand( &xfercount );
devices[unit]->GetPhase( &phase );
/* reset fifo */
scsi_data.fifo_pos = 0;
@ -791,7 +792,7 @@ void wd33c93_init( running_machine &machine, const struct WD33C93interface *inte
// try to open the devices
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
devices[interface->scsidevs->devices[i].scsiID] = machine.device<scsidev_device>( interface->scsidevs->devices[i].tag );
}
/* allocate a timer for commands */
@ -802,16 +803,6 @@ void wd33c93_init( running_machine &machine, const struct WD33C93interface *inte
// state_save_register_item_array(machine, "wd33c93", NULL, 0, scsi_data);
}
void wd33c93_exit( const struct WD33C93interface *interface )
{
int i;
for (i = 0; i < interface->scsidevs->devs_present; i++)
{
SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
}
}
void wd33c93_get_dma_data( int bytes, UINT8 *pData )
{
int len = bytes;
@ -843,7 +834,7 @@ void wd33c93_write_data(int bytes, UINT8 *pData)
if (devices[unit])
{
SCSIWriteData( devices[unit], pData, bytes );
devices[unit]->WriteData( pData, bytes );
}
else
{
@ -857,7 +848,7 @@ void *wd33c93_get_device(int id)
if (devices[id])
{
SCSIGetDevice( devices[id], &ret );
devices[id]->GetDevice( &ret );
return ret;
}

View File

@ -15,7 +15,6 @@ struct WD33C93interface
};
extern void wd33c93_init( running_machine &machine, const struct WD33C93interface *interface );
extern void wd33c93_exit( const struct WD33C93interface *interface );
extern void wd33c93_get_dma_data(int bytes, UINT8 *pData);
extern void wd33c93_write_data(int bytes, UINT8 *pData);
extern void *wd33c93_get_device(int id);

View File

@ -389,6 +389,7 @@ Notes:
#include "machine/nvram.h"
#include "includes/cps3.h"
#include "machine/wd33c93.h"
#include "machine/scsicd.h"
#define MASTER_CLOCK 42954500
@ -2292,7 +2293,7 @@ static INTERRUPT_GEN(cps3_other_interrupt)
static const SCSIConfigTable dev_table =
{
1, /* 1 SCSI device */
{ { SCSI_ID_1, ":cdrom", SCSI_DEVICE_CDROM } } /* SCSI ID 2, using CD 0, and it's a CD-ROM */
{ { SCSI_ID_1, ":cdrom" } } /* SCSI ID 2, CD-ROM */
};
static const struct WD33C93interface scsi_intf =
@ -2301,15 +2302,9 @@ static const struct WD33C93interface scsi_intf =
NULL /* command completion IRQ */
};
static void cps3_exit(running_machine &machine)
{
wd33c93_exit(&scsi_intf);
}
static MACHINE_START( cps3 )
{
wd33c93_init(machine, &scsi_intf);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(cps3_exit), &machine));
}
static MACHINE_RESET( cps3 )
@ -2546,6 +2541,8 @@ static MACHINE_CONFIG_START( cps3, cps3_state )
MCFG_CPU_PERIODIC_INT(cps3_other_interrupt,80) /* ?source? */
MCFG_CPU_CONFIG(sh2_conf_cps3)
MCFG_DEVICE_ADD("cdrom", SCSICD, 0)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_RAW_PARAMS(XTAL_60MHz/8, 486, 0, 384, 259, 0, 224)
@ -3467,9 +3464,3 @@ GAME( 1999, jojobane, jojoba, jojoba, cps3_jojo, jojoba, ROT0, "Capcom",
GAME( 1999, jojobar1, jojoba, jojoba, cps3_jojo, jojoba, ROT0, "Capcom", "JoJo no Kimyouna Bouken: Miraie no Isan (Japan 990913)", GAME_IMPERFECT_GRAPHICS )
GAME( 1999, jojobanr1, jojoba, jojoba, cps3_jojo, jojoba, ROT0, "Capcom", "JoJo no Kimyouna Bouken: Miraie no Isan (Japan 990913, NO CD)", GAME_IMPERFECT_GRAPHICS )
GAME( 1999, jojobaner1,jojoba, jojoba, cps3_jojo, jojoba, ROT0, "Capcom", "JoJo's Bizarre Adventure (Euro 990913, NO CD)", GAME_IMPERFECT_GRAPHICS )

View File

@ -158,7 +158,7 @@ public:
int m_tick;
int m_layer;
UINT8 m_atapi_regs[16];
SCSIInstance *m_atapi_device_data[2];
scsidev_device *m_atapi_device_data[2];
UINT16 m_atapi_data[32*1024];
UINT8 m_atapi_scsi_packet[32*1024];
int m_atapi_data_ptr;
@ -912,13 +912,6 @@ static void atapi_clear_irq(running_machine &machine)
cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ4, CLEAR_LINE);
}
static void atapi_exit(running_machine& machine)
{
firebeat_state *state = machine.driver_data<firebeat_state>();
SCSIDeleteInstance(state->m_atapi_device_data[1]);
SCSIDeleteInstance(state->m_atapi_device_data[0]);
}
static void atapi_init(running_machine &machine)
{
firebeat_state *state = machine.driver_data<firebeat_state>();
@ -932,11 +925,8 @@ static void atapi_init(running_machine &machine)
state->m_atapi_data_ptr = 0;
state->m_atapi_cdata_wait = 0;
// allocate two SCSI CD-ROM devices
SCSIAllocInstance( machine, SCSI_DEVICE_CDROM, &state->m_atapi_device_data[0], "scsi0" );
// TODO: the slave drive can be either CD-ROM, DVD-ROM or HDD
SCSIAllocInstance( machine, SCSI_DEVICE_CDROM, &state->m_atapi_device_data[1], "scsi1" );
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(atapi_exit), &machine));
state->m_atapi_device_data[0] = machine.device<scsidev_device>( "scsi0" );
state->m_atapi_device_data[1] = machine.device<scsidev_device>( "scsi1" );
}
static void atapi_reset(running_machine &machine)
@ -972,7 +962,7 @@ static UINT16 atapi_command_reg_r(running_machine &machine, int reg)
state->m_atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
// get the data from the device
SCSIReadData( state->m_atapi_device_data[state->m_atapi_drivesel], state->m_temp_data, state->m_atapi_xferlen );
state->m_atapi_device_data[state->m_atapi_drivesel]->ReadData( state->m_temp_data, state->m_atapi_xferlen );
// fix it up in an endian-safe way
for (i = 0; i < state->m_atapi_xferlen; i += 2)
@ -1042,7 +1032,7 @@ static void atapi_command_reg_w(running_machine &machine, int reg, UINT16 data)
}
// send it to the device
SCSIWriteData( state->m_atapi_device_data[state->m_atapi_drivesel], state->m_atapi_scsi_packet, state->m_atapi_cdata_wait );
state->m_atapi_device_data[state->m_atapi_drivesel]->WriteData( state->m_atapi_scsi_packet, state->m_atapi_cdata_wait );
// assert IRQ
atapi_cause_irq(machine);
@ -1072,9 +1062,9 @@ static void atapi_command_reg_w(running_machine &machine, int reg, UINT16 data)
}
// send it to the SCSI device
SCSISetCommand( state->m_atapi_device_data[state->m_atapi_drivesel], state->m_atapi_scsi_packet, 12 );
SCSIExecCommand( state->m_atapi_device_data[state->m_atapi_drivesel], &state->m_atapi_xferlen );
SCSIGetPhase( state->m_atapi_device_data[state->m_atapi_drivesel], &phase );
state->m_atapi_device_data[state->m_atapi_drivesel]->SetCommand( state->m_atapi_scsi_packet, 12 );
state->m_atapi_device_data[state->m_atapi_drivesel]->ExecCommand( &state->m_atapi_xferlen );
state->m_atapi_device_data[state->m_atapi_drivesel]->GetPhase( &phase );
if (state->m_atapi_xferlen != -1)
{
@ -1964,7 +1954,7 @@ static MACHINE_RESET( firebeat )
sound[i+0x200000] = state->m_flash[2]->read(i);
}
SCSIGetDevice( state->m_atapi_device_data[1], &cd );
state->m_atapi_device_data[1]->GetDevice( &cd );
cdda_set_cdrom(machine.device("cdda"), cd);
}
@ -1989,6 +1979,9 @@ static MACHINE_CONFIG_START( firebeat, firebeat_state )
MCFG_FUJITSU_29F016A_ADD("flash1")
MCFG_FUJITSU_29F016A_ADD("flash2")
MCFG_DEVICE_ADD("scsi0", SCSICD, 0)
MCFG_DEVICE_ADD("scsi1", SCSICD, 0)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)

View File

@ -53,7 +53,7 @@
#include "includes/konamigx.h"
#include "machine/eeprom.h"
#include "machine/am53cf96.h"
#include "harddisk.h"
#include "machine/scsihd.h"
#include "sound/k054539.h"
class konamigq_state : public psx_state
@ -305,7 +305,7 @@ static const SCSIConfigTable dev_table =
{
1, /* 1 SCSI device */
{
{ SCSI_ID_0, ":disk", SCSI_DEVICE_HARDDISK } /* SCSI ID 0, using CHD 0, and it's a HDD */
{ SCSI_ID_0, ":disk" } /* SCSI ID 0, HDD */
}
};
@ -324,18 +324,12 @@ static DRIVER_INIT( konamigq )
state->m_p_n_pcmram = state->memregion( "shared" )->base() + 0x80000;
}
static void konamigq_exit(running_machine &machine)
{
am53cf96_exit(&scsi_intf);
}
static MACHINE_START( konamigq )
{
konamigq_state *state = machine.driver_data<konamigq_state>();
/* init the scsi controller and hook up it's DMA */
am53cf96_init(machine, &scsi_intf);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(konamigq_exit), &machine));
state->save_pointer(NAME(state->m_p_n_pcmram), 0x380000);
state->save_item(NAME(state->m_sndto000));
@ -364,6 +358,8 @@ static MACHINE_CONFIG_START( konamigq, konamigq_state )
MCFG_EEPROM_93C46_ADD("eeprom")
MCFG_EEPROM_DATA(konamigq_def_eeprom, 128)
MCFG_DEVICE_ADD("disk", SCSIHD, 0)
/* video hardware */
MCFG_PSXGPU_ADD( "maincpu", "gpu", CXD8538Q, 0x200000, XTAL_53_693175MHz )

View File

@ -125,6 +125,7 @@ Notes:
#include "machine/eeprom.h"
#include "machine/intelfsh.h"
#include "machine/am53cf96.h"
#include "machine/scsicd.h"
#include "sound/spu.h"
#include "sound/cdda.h"
@ -289,7 +290,7 @@ static const SCSIConfigTable dev_table =
{
1, /* 1 SCSI device */
{
{ SCSI_ID_4, ":cdrom", SCSI_DEVICE_CDROM } /* SCSI ID 4, using CHD 0, and it's a CD-ROM */
{ SCSI_ID_4, ":cdrom", } /* SCSI ID 4, CD-ROM */
}
};
@ -299,18 +300,12 @@ static const struct AM53CF96interface scsi_intf =
&scsi_irq, /* command completion IRQ */
};
static void konamigv_exit(running_machine &machine)
{
am53cf96_exit(&scsi_intf);
}
static DRIVER_INIT( konamigv )
{
psx_driver_init(machine);
/* init the scsi controller and hook up it's DMA */
am53cf96_init(machine, &scsi_intf);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(konamigv_exit), &machine));
}
static MACHINE_START( konamigv )
@ -352,6 +347,8 @@ static MACHINE_CONFIG_START( konamigv, konamigv_state )
MCFG_EEPROM_93C46_ADD("eeprom")
MCFG_DEVICE_ADD("cdrom", SCSICD, 0)
/* video hardware */
MCFG_PSXGPU_ADD( "maincpu", "gpu", CXD8514Q, 0x100000, XTAL_53_693175MHz )

View File

@ -488,8 +488,8 @@ public:
UINT32 m_control;
emu_timer *m_atapi_timer;
SCSIInstance *m_inserted_cdrom;
SCSIInstance *m_available_cdroms[ 2 ];
scsidev_device *m_inserted_cdrom;
scsidev_device *m_available_cdroms[ 2 ];
int m_atapi_data_ptr;
int m_atapi_data_len;
int m_atapi_xferlen;
@ -696,7 +696,7 @@ static TIMER_CALLBACK( atapi_xfer_end )
while( state->m_atapi_xferlen > 0 )
{
// get a sector from the SCSI device
SCSIReadData( state->m_inserted_cdrom, sector_buffer, 2048 );
state->m_inserted_cdrom->ReadData( sector_buffer, 2048 );
state->m_atapi_xferlen -= 2048;
@ -762,7 +762,7 @@ READ32_MEMBER(ksys573_state::atapi_r)
// get the data from the device
if( m_atapi_xferlen > 0 )
{
SCSIReadData( m_inserted_cdrom, m_atapi_data, m_atapi_xferlen );
m_inserted_cdrom->ReadData( m_atapi_data, m_atapi_xferlen );
m_atapi_data_len = m_atapi_xferlen;
}
@ -891,7 +891,7 @@ WRITE32_MEMBER(ksys573_state::atapi_w)
if (m_atapi_data_ptr == m_atapi_cdata_wait)
{
// send it to the device
SCSIWriteData( m_inserted_cdrom, atapi_data, m_atapi_cdata_wait );
m_inserted_cdrom->WriteData( atapi_data, m_atapi_cdata_wait );
// assert IRQ
psx_irq_set(machine(), 0x400);
@ -912,9 +912,9 @@ WRITE32_MEMBER(ksys573_state::atapi_w)
m_atapi_data_len = 0;
// send it to the SCSI device
SCSISetCommand( m_inserted_cdrom, m_atapi_data, 12 );
SCSIExecCommand( m_inserted_cdrom, &m_atapi_xferlen );
SCSIGetPhase( m_inserted_cdrom, &phase );
m_inserted_cdrom->SetCommand( m_atapi_data, 12 );
m_inserted_cdrom->ExecCommand( &m_atapi_xferlen );
m_inserted_cdrom->GetPhase( &phase );
if (m_atapi_xferlen != -1)
{
@ -1104,20 +1104,6 @@ WRITE32_MEMBER(ksys573_state::atapi_w)
}
}
static void atapi_exit(running_machine& machine)
{
ksys573_state *state = machine.driver_data<ksys573_state>();
int i;
for( i = 0; i < 2; i++ )
{
if( get_disk_handle( machine, diskregions[i] ) != NULL )
{
SCSIDeleteInstance( state->m_available_cdroms[ i ] );
}
}
}
static void atapi_init(running_machine &machine)
{
ksys573_state *state = machine.driver_data<ksys573_state>();
@ -1139,15 +1125,13 @@ static void atapi_init(running_machine &machine)
{
if( get_disk_handle( machine, diskregions[i] ) != NULL )
{
SCSIAllocInstance( machine, &SCSIClassCr589, &state->m_available_cdroms[ i ], diskregions[i] );
state->m_available_cdroms[ i ] = machine.device<scsidev_device>( diskregions[i] );
}
else
{
state->m_available_cdroms[ i ] = NULL;
}
}
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(atapi_exit), &machine));
state->save_item( NAME(state->m_atapi_regs) );
state->save_item( NAME(state->m_atapi_data) );
@ -1361,16 +1345,16 @@ static void *atapi_get_device(running_machine &machine)
{
ksys573_state *state = machine.driver_data<ksys573_state>();
void *ret;
SCSIGetDevice( state->m_inserted_cdrom, &ret );
state->m_inserted_cdrom->GetDevice( &ret );
return ret;
}
}
static void update_mode( running_machine &machine )
{
ksys573_state *state = machine.driver_data<ksys573_state>();
int cart = state->ioport("CART")->read();
int cd = state->ioport( "CD" )->read();
SCSIInstance *new_cdrom;
scsidev_device *new_cdrom;
if( state->machine().device<device_secure_serial_flash>("game_eeprom") )
{
@ -3067,6 +3051,10 @@ static MACHINE_CONFIG_START( konami573, ksys573_state )
MCFG_MACHINE_RESET( konami573 )
// multiple cd's are handled by switching drives instead of discs.
MCFG_DEVICE_ADD("cdrom0", CR589, 0)
MCFG_DEVICE_ADD("cdrom1", CR589, 0)
// onboard flash
MCFG_FUJITSU_29F016A_ADD("onboard.0")
MCFG_FUJITSU_29F016A_ADD("onboard.1")

View File

@ -1197,9 +1197,8 @@ static const eeprom_interface eeprom_intf =
static const SCSIConfigTable scsi_dev_table =
{
1, /* 1 SCSI device */
0, /* no SCSI device */
{
{ SCSI_ID_0, "disk", SCSI_DEVICE_HARDDISK } /* SCSI ID 0, using HD 0, HD */
}
};
@ -1211,11 +1210,6 @@ static const struct LSI53C810interface scsi_intf =
&scsi_fetch,
};
static void model3_exit(running_machine &machine)
{
lsi53c810_exit(&scsi_intf);
}
static void configure_fast_ram(running_machine &machine)
{
model3_state *state = machine.driver_data<model3_state>();
@ -1239,7 +1233,6 @@ static TIMER_CALLBACK(model3_sound_timer_tick)
static MACHINE_START(model3_10)
{
lsi53c810_init(machine, &scsi_intf);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_exit), &machine));
configure_fast_ram(machine);
model3_state *state = machine.driver_data<model3_state>();
@ -1248,7 +1241,6 @@ static MACHINE_START(model3_10)
static MACHINE_START(model3_15)
{
lsi53c810_init(machine, &scsi_intf);
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_exit), &machine));
configure_fast_ram(machine);
model3_state *state = machine.driver_data<model3_state>();

View File

@ -232,6 +232,7 @@ Notes:
#include "video/psx.h"
#include "includes/psx.h"
#include "machine/am53cf96.h"
#include "machine/scsicd.h"
#include "machine/rtc65271.h"
#include "machine/i2cmem.h"
#include "machine/idectrl.h"
@ -850,7 +851,7 @@ static const SCSIConfigTable dev_table =
{
1, /* 1 SCSI device */
{
{ SCSI_ID_4, "cdrom0", SCSI_DEVICE_CDROM } /* SCSI ID 4, using CHD 0, and it's a CD-ROM */
{ SCSI_ID_4, "cdrom0" } /* SCSI ID 4, CD-ROM */
}
};
@ -912,6 +913,8 @@ static MACHINE_CONFIG_START( twinkle, twinkle_state )
MCFG_MACHINE_RESET( twinkle )
MCFG_I2CMEM_ADD("security",i2cmem_interface)
MCFG_DEVICE_ADD("cdrom0", SCSICD, 0)
MCFG_IDE_CONTROLLER_ADD("ide", ide_interrupt, ide_devices, "hdd", NULL, true)
MCFG_RTC65271_ADD("rtc", twinkle_rtc)

View File

@ -11,21 +11,6 @@
#include "imagedev/chd_cd.h"
#include "gdrom.h"
typedef struct
{
UINT32 lba;
UINT32 blocks;
UINT32 last_lba;
UINT32 bytes_per_sector;
UINT32 num_subblocks;
UINT32 cur_subblock;
UINT32 play_err_flag;
UINT32 read_type; // for command 0x30 only
UINT32 data_select; // for command 0x30 only
cdrom_file *cdrom;
bool is_file;
} SCSIGd;
static const UINT8 GDROM_Cmd11_Reply[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x19, 0x00, 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
@ -40,147 +25,225 @@ static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
*f = phys_frame % 75;
}
// device type definition
const device_type GDROM = &device_creator<gdrom_device>;
gdrom_device::gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsidev_device(mconfig, GDROM, "GDROM", tag, owner, clock)
{
}
void gdrom_device::device_start()
{
save_item( NAME( lba ) );
save_item( NAME( blocks ) );
save_item( NAME( last_lba ) );
save_item( NAME( bytes_per_sector ) );
save_item( NAME( num_subblocks ) );
save_item( NAME( cur_subblock ) );
save_item( NAME( play_err_flag ) );
}
void gdrom_device::device_reset()
{
scsidev_device::device_reset();
is_file = TRUE;
cdrom = subdevice<cdrom_image_device>("image")->get_cdrom_file();
if( !cdrom )
{
// try to locate the CHD from a DISK_REGION
chd_file *chd = get_disk_handle( machine(), tag() );
if( chd != NULL )
{
is_file = FALSE;
cdrom = cdrom_open( chd );
}
}
if (!cdrom)
{
logerror("GDROM: no CD found!\n");
}
lba = 0;
blocks = 0;
last_lba = 0;
bytes_per_sector = 2048;
num_subblocks = 1;
cur_subblock = 0;
play_err_flag = 0;
}
void gdrom_device::device_stop()
{
if (!is_file)
{
if( cdrom )
{
cdrom_close( cdrom );
}
}
}
cdrom_interface gdrom_device::cd_intf = { 0, 0 };
static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
MCFG_CDROM_ADD("image", gdrom_device::cd_intf)
MACHINE_CONFIG_END
machine_config_constructor gdrom_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(scsi_cdrom);
}
// scsicd_exec_command
//
// Execute a SCSI command.
static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
void gdrom_device::ExecCommand( int *transferLength )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
cdrom_file *cdrom = our_this->cdrom;
device_t *cdda;
int trk;
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch ( command[0] )
{
case 0x03: // REQUEST SENSE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x11: // REQ_MODE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
SetPhase( SCSI_PHASE_DATAIN );
printf("REQ_MODE %02x %02x %02x %02x %02x %02x\n",
command[0], command[1],
command[2], command[3],
command[4], command[5]);
// if (SCSILengthFromUINT8( &command[ 4 ] ) < 32) return -1;
return 32; //SCSILengthFromUINT8( &command[ 4 ] );
*transferLength = 32; //SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x12: // INQUIRY
logerror("GDROM: REQUEST SENSE\n");
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x15: // MODE SELECT(6)
logerror("GDROM: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x1a: // MODE SENSE(6)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT8( &command[ 4 ] );
break;
case 0x1b: // START STOP UNIT
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom( machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x25: // READ CAPACITY
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return 8;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = 8;
break;
case 0x28: // READ(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
logerror("GDROM: READ(10) at LBA %x for %d blocks (%d bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
logerror("GDROM: READ(10) at LBA %x for %d blocks (%d bytes)\n", lba, blocks, blocks * bytes_per_sector);
if (our_this->num_subblocks > 1)
if (num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
cur_subblock = lba % num_subblocks;
lba /= num_subblocks;
}
else
{
our_this->cur_subblock = 0;
cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * bytes_per_sector;
break;
case 0x30: // CD_READ
if (command[1] & 1)
{
fatalerror("GDROM: MSF mode used for CD_READ, unsupported");
return 0;
*transferLength = 0;
}
else
{
our_this->lba = (command[2]<<16 | command[3]<<8 | command[4]) - 150;
our_this->blocks = command[8]<<16 | command[9]<<8 | command[10];
lba = (command[2]<<16 | command[3]<<8 | command[4]) - 150;
blocks = command[8]<<16 | command[9]<<8 | command[10];
our_this->read_type = (command[1] >> 1) & 7;
our_this->data_select = (command[1]>>4) & 0xf;
read_type = (command[1] >> 1) & 7;
data_select = (command[1]>>4) & 0xf;
if (our_this->read_type != 2) // mode 1
if (read_type != 2) // mode 1
{
fatalerror("GDROM: Unhandled read_type %d", our_this->read_type);
fatalerror("GDROM: Unhandled read_type %d", read_type);
}
if (our_this->data_select != 2) // just sector data
if (data_select != 2) // just sector data
{
fatalerror("GDROM: Unhandled data_select %d", our_this->data_select);
fatalerror("GDROM: Unhandled data_select %d", data_select);
}
printf("GDROM: CD_READ at LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector, our_this->read_type, our_this->data_select);
printf("GDROM: CD_READ at LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n", lba, blocks, blocks * bytes_per_sector, read_type, data_select);
if (our_this->num_subblocks > 1)
if (num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
cur_subblock = lba % num_subblocks;
lba /= num_subblocks;
}
else
{
our_this->cur_subblock = 0;
cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * bytes_per_sector;
}
break;
case 0x42: // READ SUB-CHANNEL
// logerror("GDROM: READ SUB-CHANNEL type %d\n", command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0x43: // READ TOC
{
@ -208,161 +271,171 @@ static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
length = 4;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return length;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = length;
break;
}
case 0x45: // PLAY AUDIO(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = SCSILengthFromUINT16( &command[7] );
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
if (lba == 0)
{
our_this->lba = 150;
lba = 150;
}
else if (our_this->lba == 0xffffffff)
else if (lba == 0xffffffff)
{
logerror("GDROM: play audio from current not implemented!\n");
}
logerror("GDROM: PLAY AUDIO(10) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("GDROM: PLAY AUDIO(10) at LBA %x for %x blocks\n", lba, blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
trk = cdrom_get_track(cdrom, lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
play_err_flag = 0;
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
else
{
logerror("GDROM: track is NOT audio!\n");
our_this->play_err_flag = 1;
play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x48: // PLAY AUDIO TRACK/INDEX
// be careful: tracks here are zero-based, but the SCSI command
// uses the real CD track number which is 1-based!
our_this->lba = cdrom_get_track_start(cdrom, command[4]-1);
our_this->blocks = cdrom_get_track_start(cdrom, command[7]-1) - our_this->lba;
lba = cdrom_get_track_start(cdrom, command[4]-1);
blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
if (command[4] > command[7])
{
our_this->blocks = 0;
blocks = 0;
}
if (command[4] == command[7])
{
our_this->blocks = cdrom_get_track_start(cdrom, command[4]) - our_this->lba;
blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
}
if (our_this->blocks && cdrom)
if (blocks && cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
logerror("GDROM: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], our_this->blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
logerror("GDROM: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x4b: // PAUSE/RESUME
if (cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_pause_audio(cdda, (command[8] & 0x01) ^ 0x01);
}
logerror("GDROM: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0x55: // MODE SELECT(10)
logerror("GDROM: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAOUT );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0x5a: // MODE SENSE(10)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = SCSILengthFromUINT16( &command[ 7 ] );
break;
case 0xa5: // PLAY AUDIO(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
if (lba == 0)
{
our_this->lba = 150;
lba = 150;
}
else if (our_this->lba == 0xffffffff)
else if (lba == 0xffffffff)
{
logerror("GDROM: play audio from current not implemented!\n");
}
logerror("GDROM: PLAY AUDIO(12) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
logerror("GDROM: PLAY AUDIO(12) at LBA %x for %x blocks\n", lba, blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
trk = cdrom_get_track(cdrom, lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
play_err_flag = 0;
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
cdda_start_audio(cdda, lba, blocks);
}
else
{
logerror("GDROM: track is NOT audio!\n");
our_this->play_err_flag = 1;
play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
case 0xa8: // READ(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[7]<<16 | command[8]<<8 | command[9];
lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
blocks = command[7]<<16 | command[8]<<8 | command[9];
logerror("GDROM: READ(12) at LBA %x for %x blocks (%x bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
logerror("GDROM: READ(12) at LBA %x for %x blocks (%x bytes)\n", lba, blocks, blocks * bytes_per_sector);
if (our_this->num_subblocks > 1)
if (num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
cur_subblock = lba % num_subblocks;
lba /= num_subblocks;
}
else
{
our_this->cur_subblock = 0;
cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
SetPhase( SCSI_PHASE_DATAIN );
*transferLength = blocks * bytes_per_sector;
break;
case 0xbb: // SET CD SPEED
logerror("GDROM: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
SetPhase( SCSI_PHASE_STATUS );
*transferLength = 0;
break;
default:
return SCSIBase( &SCSIClassGDROM, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
scsidev_device::ExecCommand( transferLength );
break;
}
}
@ -370,20 +443,18 @@ static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
//
// Read data from the device resulting from the execution of a command
static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void gdrom_device::ReadData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
int i;
UINT32 last_phys_frame;
cdrom_file *cdrom = our_this->cdrom;
UINT32 temp;
UINT8 tmp_buffer[2048];
device_t *cdda;
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch ( command[0] )
{
@ -394,15 +465,15 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
data[0] = 0x71; // deferred error
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
if (cdda != NULL && cdda_audio_active(cdda))
{
data[12] = 0x00;
data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS
}
else if (our_this->play_err_flag)
else if (play_err_flag)
{
our_this->play_err_flag = 0;
play_err_flag = 0;
data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK
data[13] = 0x00;
}
@ -439,69 +510,69 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
data[3] = (temp & 0xff);
data[4] = 0;
data[5] = 0;
data[6] = (our_this->bytes_per_sector>>8)&0xff;
data[7] = (our_this->bytes_per_sector & 0xff);
data[6] = (bytes_per_sector>>8)&0xff;
data[7] = (bytes_per_sector & 0xff);
break;
case 0x28: // READ(10)
case 0xa8: // READ(12)
logerror("GDROM: read %x dataLength, \n", dataLength);
if ((our_this->cdrom) && (our_this->blocks))
if ((cdrom) && (blocks))
{
while (dataLength > 0)
{
if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
{
logerror("GDROM: CD read error!\n");
}
logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
our_this->cur_subblock++;
if (our_this->cur_subblock >= our_this->num_subblocks)
cur_subblock++;
if (cur_subblock >= num_subblocks)
{
our_this->cur_subblock = 0;
cur_subblock = 0;
our_this->lba++;
our_this->blocks--;
lba++;
blocks--;
}
our_this->last_lba = our_this->lba;
dataLength -= our_this->bytes_per_sector;
data += our_this->bytes_per_sector;
last_lba = lba;
dataLength -= bytes_per_sector;
data += bytes_per_sector;
}
}
break;
case 0x30: // CD_READ
logerror("GDROM: read %x dataLength, \n", dataLength);
if ((our_this->cdrom) && (our_this->blocks))
if ((cdrom) && (blocks))
{
while (dataLength > 0)
{
if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
{
logerror("GDROM: CD read error!\n");
}
logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
our_this->cur_subblock++;
if (our_this->cur_subblock >= our_this->num_subblocks)
cur_subblock++;
if (cur_subblock >= num_subblocks)
{
our_this->cur_subblock = 0;
cur_subblock = 0;
our_this->lba++;
our_this->blocks--;
lba++;
blocks--;
}
our_this->last_lba = our_this->lba;
dataLength -= our_this->bytes_per_sector;
data += our_this->bytes_per_sector;
last_lba = lba;
dataLength -= bytes_per_sector;
data += bytes_per_sector;
}
}
@ -522,7 +593,7 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
msf = command[1] & 0x2;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
cdda = cdda_from_cdrom(machine(), cdrom);
audio_active = cdda != NULL && cdda_audio_active(cdda);
if (audio_active)
{
@ -551,21 +622,21 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
// if audio is playing, get the latest LBA from the CDROM layer
if (audio_active)
{
our_this->last_lba = cdda_get_audio_lba(cdda);
last_lba = cdda_get_audio_lba(cdda);
}
else
{
our_this->last_lba = 0;
last_lba = 0;
}
data[2] = 0;
data[3] = 12; // data length
data[4] = 0x01; // sub-channel format code
data[5] = 0x10 | (audio_active ? 0 : 4);
data[6] = cdrom_get_track(cdrom, our_this->last_lba) + 1; // track
data[6] = cdrom_get_track(cdrom, last_lba) + 1; // track
data[7] = 0; // index
last_phys_frame = our_this->last_lba;
last_phys_frame = last_lba;
if (msf)
{
@ -715,7 +786,7 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
break;
default:
SCSIBase( &SCSIClassGDROM, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
scsidev_device::ReadData( data, dataLength );
break;
}
}
@ -724,12 +795,11 @@ static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataL
//
// Write data to the CD-ROM device as part of the execution of a command
static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
void gdrom_device::WriteData( UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
GetCommand( &command, &commandLength );
switch (command[ 0 ])
{
@ -745,8 +815,8 @@ static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int data
{
logerror("GDROM: Experimental SGI 512-byte block extension enabled\n");
our_this->bytes_per_sector = 512;
our_this->num_subblocks = 4;
bytes_per_sector = 512;
num_subblocks = 4;
}
else
{
@ -764,112 +834,17 @@ static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int data
break;
default:
SCSIBase( &SCSIClassGDROM, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
scsidev_device::WriteData( data, dataLength );
break;
}
}
static void scsicd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
void gdrom_device::GetDevice( void **_cdrom )
{
running_machine &machine = scsiInstance->machine();
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
our_this->lba = 0;
our_this->blocks = 0;
our_this->last_lba = 0;
our_this->bytes_per_sector = 2048;
our_this->num_subblocks = 1;
our_this->cur_subblock = 0;
our_this->play_err_flag = 0;
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->blocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->last_lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->bytes_per_sector );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->num_subblocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->cur_subblock );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->play_err_flag );
if (machine.device( diskregion )) {
our_this->is_file = TRUE;
cdrom_image_device *cdrom = machine.device<cdrom_image_device>(diskregion);
our_this->cdrom = cdrom->get_cdrom_file();
} else {
our_this->is_file = FALSE;
our_this->cdrom = cdrom_open(get_disk_handle( machine, diskregion ));
}
if (!our_this->cdrom)
{
logerror("GDROM: no CD found!\n");
}
*(cdrom_file **)_cdrom = cdrom;
}
static void scsicd_delete_instance( SCSIInstance *scsiInstance )
void gdrom_device::SetDevice( void *_cdrom )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
if (!our_this->is_file) {
if( our_this->cdrom )
{
cdrom_close( our_this->cdrom );
}
}
cdrom = (cdrom_file *) _cdrom;
}
static void scsicd_get_device( SCSIInstance *scsiInstance, cdrom_file **cdrom )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
*cdrom = our_this->cdrom;
}
static void scsicd_set_device( SCSIInstance *scsiInstance, cdrom_file *cdrom )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
our_this->cdrom = cdrom;
}
static int scsigd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
{
SCSIAllocInstanceParams *params;
switch (operation)
{
case SCSIOP_EXEC_COMMAND:
return scsicd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
scsicd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_WRITE_DATA:
scsicd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
SCSIBase( &SCSIClassGDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
scsicd_alloc_instance( params->instance, params->diskregion );
return 0;
case SCSIOP_DELETE_INSTANCE:
scsicd_delete_instance( (SCSIInstance *)file );
break;
case SCSIOP_GET_DEVICE:
scsicd_get_device( (SCSIInstance *)file, (cdrom_file **)ptrparm );
return 0;
case SCSIOP_SET_DEVICE:
scsicd_set_device( (SCSIInstance *)file, (cdrom_file *)ptrparm );
return 0;
}
return SCSIBase( &SCSIClassGDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
}
const SCSIClass SCSIClassGDROM =
{
&SCSIClassDevice,
scsigd_dispatch,
sizeof( SCSIGd )
};

View File

@ -7,11 +7,45 @@
#ifndef _GDROM_H_
#define _GDROM_H_
#include "machine/scsi.h"
#include "machine/scsidev.h"
// Sega GD-ROM handler
extern const SCSIClass SCSIClassGDROM;
#define SCSI_DEVICE_GDROM &SCSIClassGDROM
class gdrom_device : public scsidev_device
{
public:
// construction/destruction
gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual machine_config_constructor device_mconfig_additions() const;
virtual void SetDevice( void *device );
virtual void GetDevice( void **device );
virtual void ExecCommand( int *transferLength );
virtual void WriteData( UINT8 *data, int dataLength );
virtual void ReadData( UINT8 *data, int dataLength );
static struct cdrom_interface cd_intf;
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_stop();
private:
UINT32 lba;
UINT32 blocks;
UINT32 last_lba;
UINT32 bytes_per_sector;
UINT32 num_subblocks;
UINT32 cur_subblock;
UINT32 play_err_flag;
UINT32 read_type; // for command 0x30 only
UINT32 data_select; // for command 0x30 only
cdrom_file *cdrom;
bool is_file;
};
// device type definition
extern const device_type GDROM;
#endif