Refactored dreamcast to use an ATA interface [smf]

This commit is contained in:
smf- 2013-09-03 17:25:38 +00:00
parent a3eb1c6917
commit 1657fcfa43
5 changed files with 173 additions and 658 deletions

View File

@ -11,6 +11,17 @@
#include "gdrom.h"
#include "debugger.h"
#define GDROM_BUSY_STATE 0x00
#define GDROM_PAUSE_STATE 0x01
#define GDROM_STANDBY_STATE 0x02
#define GDROM_PLAY_STATE 0x03
#define GDROM_SEEK_STATE 0x04
#define GDROM_SCAN_STATE 0x05
#define GDROM_OPEN_STATE 0x06
#define GDROM_NODISC_STATE 0x07
#define GDROM_RETRY_STATE 0x08
#define GDROM_ERROR_STATE 0x09
static const UINT8 GDROM_Cmd71_Reply[] =
{
0x0b,0x96,0xf0,0x45,0xff,0x7e,0x06,0x3d,0x7d,0x4d,0xbf,0x10,0x00,0x07,0xcf,0x73,
@ -89,15 +100,15 @@ static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
}
// device type definition
const device_type GDROM = &device_creator<gdrom_device>;
const device_type SCSI_GDROM = &device_creator<scsi_gdrom_device>;
gdrom_device::gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsihle_device(mconfig, GDROM, "GDROM", tag, owner, clock, "gdrom", __FILE__),
scsi_gdrom_device::scsi_gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scsihle_device(mconfig, SCSI_GDROM, "SCSI GDROM", tag, owner, clock, "scsi_gdrom", __FILE__),
m_cdda(*this, "cdda")
{
}
void gdrom_device::device_start()
void scsi_gdrom_device::device_start()
{
save_item( NAME( lba ) );
save_item( NAME( blocks ) );
@ -108,7 +119,7 @@ void gdrom_device::device_start()
save_item( NAME( play_err_flag ) );
}
void gdrom_device::device_reset()
void scsi_gdrom_device::device_reset()
{
scsihle_device::device_reset();
@ -148,7 +159,7 @@ void gdrom_device::device_reset()
play_err_flag = 0;
}
void gdrom_device::device_stop()
void scsi_gdrom_device::device_stop()
{
if (!is_file)
{
@ -159,13 +170,14 @@ void gdrom_device::device_stop()
}
}
cdrom_interface gdrom_device::cd_intf = { 0, 0 };
cdrom_interface scsi_gdrom_device::cd_intf = { 0, 0 };
static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
MCFG_CDROM_ADD("image", gdrom_device::cd_intf)
MCFG_CDROM_ADD("image", scsi_gdrom_device::cd_intf)
MCFG_SOUND_ADD("cdda", CDDA, 0)
MACHINE_CONFIG_END
machine_config_constructor gdrom_device::device_mconfig_additions() const
machine_config_constructor scsi_gdrom_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(scsi_cdrom);
}
@ -174,7 +186,7 @@ machine_config_constructor gdrom_device::device_mconfig_additions() const
//
// Execute a SCSI command.
void gdrom_device::ExecCommand( int *transferLength )
void scsi_gdrom_device::ExecCommand( int *transferLength )
{
int trk;
@ -565,7 +577,7 @@ void gdrom_device::ExecCommand( int *transferLength )
//
// Read data from the device resulting from the execution of a command
void gdrom_device::ReadData( UINT8 *data, int dataLength )
void scsi_gdrom_device::ReadData( UINT8 *data, int dataLength )
{
int i;
UINT32 last_phys_frame;
@ -994,7 +1006,7 @@ void gdrom_device::ReadData( UINT8 *data, int dataLength )
//
// Write data to the CD-ROM device as part of the execution of a command
void gdrom_device::WriteData( UINT8 *data, int dataLength )
void scsi_gdrom_device::WriteData( UINT8 *data, int dataLength )
{
switch (command[ 0 ])
{
@ -1038,17 +1050,91 @@ void gdrom_device::WriteData( UINT8 *data, int dataLength )
}
}
void gdrom_device::GetDevice( void **_cdrom )
void scsi_gdrom_device::GetDevice( void **_cdrom )
{
*(cdrom_file **)_cdrom = cdrom;
}
void gdrom_device::SetDevice( void *_cdrom )
void scsi_gdrom_device::SetDevice( void *_cdrom )
{
cdrom = (cdrom_file *) _cdrom;
}
int gdrom_device::GetSectorBytes()
int scsi_gdrom_device::GetSectorBytes()
{
return bytes_per_sector;
}
// 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)
: atapi_hle_device(mconfig, GDROM, "GDROM", tag, owner, clock, "gdrom", __FILE__)
{
}
static MACHINE_CONFIG_FRAGMENT( gdrom )
MCFG_DEVICE_ADD("device", SCSI_GDROM, 0)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor gdrom_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( gdrom );
}
void gdrom_device::device_start()
{
memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
m_identify_buffer[ 0 ] = 0x8600; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
m_identify_buffer[ 23 ] = ('S' << 8) | 'E';
m_identify_buffer[ 24 ] = (' ' << 8) | ' ';
m_identify_buffer[ 25 ] = (' ' << 8) | ' ';
m_identify_buffer[ 26 ] = (' ' << 8) | ' ';
m_identify_buffer[ 27 ] = ('C' << 8) | 'D';
m_identify_buffer[ 28 ] = ('-' << 8) | 'R';
m_identify_buffer[ 29 ] = ('O' << 8) | 'M';
m_identify_buffer[ 30 ] = (' ' << 8) | 'D';
m_identify_buffer[ 31 ] = ('R' << 8) | 'I';
m_identify_buffer[ 32 ] = ('V' << 8) | 'E';
m_identify_buffer[ 33 ] = (' ' << 8) | ' ';
m_identify_buffer[ 34 ] = (' ' << 8) | ' ';
m_identify_buffer[ 35 ] = ('6' << 8) | '.';
m_identify_buffer[ 36 ] = ('4' << 8) | '2';
m_identify_buffer[ 37 ] = (' ' << 8) | ' ';
m_identify_buffer[ 38 ] = (' ' << 8) | ' ';
m_identify_buffer[ 39 ] = (' ' << 8) | ' ';
m_identify_buffer[ 40 ] = (' ' << 8) | ' ';
m_identify_buffer[ 41 ] = (' ' << 8) | ' ';
m_identify_buffer[ 42 ] = (' ' << 8) | ' ';
m_identify_buffer[ 43 ] = (' ' << 8) | ' ';
m_identify_buffer[ 44 ] = (' ' << 8) | ' ';
m_identify_buffer[ 45 ] = (' ' << 8) | ' ';
m_identify_buffer[ 46 ] = (' ' << 8) | ' ';
m_identify_buffer[ 49 ] = 0x0400; // IORDY may be disabled
atapi_hle_device::device_start();
}
void gdrom_device::perform_diagnostic()
{
m_error = IDE_ERROR_DIAGNOSTIC_PASSED;
}
void gdrom_device::process_buffer()
{
atapi_hle_device::process_buffer();
m_sector_number = 0x80 | GDROM_PAUSE_STATE; /// HACK: find out when this should be updated
}
void gdrom_device::identify_packet_device()
{
}

View File

@ -7,15 +7,17 @@
#ifndef _GDROM_H_
#define _GDROM_H_
#include "machine/atapihle.h"
#include "machine/scsihle.h"
#include "sound/cdda.h"
#include "cdrom.h"
// Sega GD-ROM handler
class gdrom_device : public scsihle_device
class scsi_gdrom_device : public scsihle_device
{
public:
// construction/destruction
gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
scsi_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 );
@ -45,11 +47,29 @@ private:
UINT32 data_select; // for command 0x30 only
UINT32 transferOffset;
cdrom_file *cdrom;
optional_device<cdda_device> m_cdda;
required_device<cdda_device> m_cdda;
bool is_file;
UINT8 GDROM_Cmd11_Reply[32];
};
// device type definition
extern const device_type SCSI_GDROM;
class gdrom_device : public atapi_hle_device
{
public:
gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
// device-level overrides
virtual machine_config_constructor device_mconfig_additions() const;
virtual void device_start();
virtual void perform_diagnostic();
virtual void identify_packet_device();
virtual void process_buffer();
};
// device type definition
extern const device_type GDROM;

View File

@ -365,7 +365,8 @@ static ADDRESS_MAP_START( dc_map, AS_PROGRAM, 64, dc_cons_state )
AM_RANGE(0x00200000, 0x0021ffff) AM_ROM AM_REGION("dcflash",0)//AM_READWRITE8(dc_flash_r,dc_flash_w, U64(0xffffffffffffffff))
AM_RANGE(0x005f6800, 0x005f69ff) AM_READWRITE(dc_sysctrl_r, dc_sysctrl_w )
AM_RANGE(0x005f6c00, 0x005f6cff) AM_DEVICE32( "maple_dc", maple_dc_device, amap, U64(0xffffffffffffffff) )
AM_RANGE(0x005f7000, 0x005f70ff) AM_READWRITE32(dc_mess_gdrom_r, dc_mess_gdrom_w, U64(0xffffffffffffffff) )
AM_RANGE(0x005f7000, 0x005f701f) AM_DEVREADWRITE16("ata", ata_interface_device, read_cs1, write_cs1, U64(0x0000ffff0000ffff) )
AM_RANGE(0x005f7080, 0x005f709f) AM_DEVREADWRITE16("ata", ata_interface_device, read_cs0, write_cs0, U64(0x0000ffff0000ffff) )
AM_RANGE(0x005f7400, 0x005f74ff) AM_READWRITE32(dc_mess_g1_ctrl_r, dc_mess_g1_ctrl_w, U64(0xffffffffffffffff) )
AM_RANGE(0x005f7800, 0x005f78ff) AM_READWRITE(dc_g2_ctrl_r, dc_g2_ctrl_w )
AM_RANGE(0x005f7c00, 0x005f7cff) AM_DEVICE32("powervr2", powervr2_device, pd_dma_map, U64(0xffffffffffffffff))
@ -562,7 +563,6 @@ MACHINE_RESET_MEMBER(dc_cons_state,dc_console)
device_t *aica = machine().device("aica");
dc_state::machine_reset();
aica_set_ram_base(aica, dc_sound_ram, 2*1024*1024);
dreamcast_atapi_reset();
}
WRITE_LINE_MEMBER(dc_cons_state::aica_irq)
@ -590,6 +590,16 @@ static const aica_interface dc_aica_interface =
static const struct sh4_config sh4cpu_config = { 1, 0, 1, 0, 0, 0, 1, 1, 0, CPU_CLOCK };
SLOT_INTERFACE_START(dccons_ata_devices)
SLOT_INTERFACE("gdrom", GDROM)
SLOT_INTERFACE_END
static MACHINE_CONFIG_FRAGMENT( gdrom_config )
MCFG_DEVICE_MODIFY("device:cdda")
MCFG_SOUND_ROUTE(0, "^^^^^lspeaker", 1.0)
MCFG_SOUND_ROUTE(1, "^^^^^rspeaker", 1.0)
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( dc, dc_cons_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", SH4LE, CPU_CLOCK)
@ -624,7 +634,11 @@ static MACHINE_CONFIG_START( dc, dc_cons_state )
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.0)
MCFG_DEVICE_ADD("cdrom", GDROM, 0)
MCFG_ATA_INTERFACE_ADD("ata", dccons_ata_devices, "gdrom", NULL, true)
MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(dc_cons_state, ata_interrupt))
MCFG_DEVICE_MODIFY("ata:0")
MCFG_DEVICE_CARD_MACHINE_CONFIG( "gdrom", gdrom_config )
MACHINE_CONFIG_END
/*

View File

@ -1,15 +1,18 @@
#include "imagedev/chd_cd.h"
#include "machine/gdrom.h"
#include "machine/ataintf.h"
#include "machine/intelfsh.h"
class dc_cons_state : public dc_state
{
public:
dc_cons_state(const machine_config &mconfig, device_type type, const char *tag)
: dc_state(mconfig, type, tag)
: dc_state(mconfig, type, tag),
m_ata(*this, "ata")
// m_dcflash(*this, "dcflash")
{ }
required_device<ata_interface_device> m_ata;
// required_device<macronix_29lv160tmc_device> m_dcflash;
DECLARE_DRIVER_INIT(dc);
@ -26,23 +29,11 @@ public:
DECLARE_WRITE64_MEMBER(dc_arm_w);
DECLARE_WRITE_LINE_MEMBER(aica_irq);
DECLARE_WRITE_LINE_MEMBER(sh4_aica_irq);
void gdrom_raise_irq();
void gdrom_set_status(UINT8 flag,bool state);
void gdrom_set_error(UINT8 flag,bool state);
DECLARE_WRITE_LINE_MEMBER(ata_interrupt);
TIMER_CALLBACK_MEMBER( atapi_xfer_end );
TIMER_CALLBACK_MEMBER( atapi_cmd_exec );
UINT8 cur_atapi_cmd;
void atapi_cmd_nop();
void atapi_cmd_packet();
void atapi_cmd_identify_packet();
void atapi_cmd_set_features();
void dreamcast_atapi_init();
void dreamcast_atapi_reset();
inline int decode_reg32_64(UINT32 offset, UINT64 mem_mask, UINT64 *shift);
DECLARE_READ32_MEMBER( dc_mess_gdrom_r );
DECLARE_WRITE32_MEMBER( dc_mess_gdrom_w );
DECLARE_READ32_MEMBER( dc_mess_g1_ctrl_r );
DECLARE_WRITE32_MEMBER( dc_mess_g1_ctrl_w );
// DECLARE_READ8_MEMBER( dc_flash_r );
@ -50,13 +41,6 @@ public:
private:
UINT64 PDTRA, PCTRA;
UINT8 *atapi_regs;
emu_timer *atapi_timer,*atapi_cmd_timer;
gdrom_device *gdrom;
UINT8 *atapi_data;
int atapi_data_ptr, atapi_data_len, atapi_xferlen, atapi_xferbase, atapi_cdata_wait, atapi_xfermod;
UINT8 xfer_mode;
int atapi_pio_ptr;
UINT8 pio_sector_buffer[2048];
emu_timer *atapi_timer;
int atapi_xferlen, atapi_xferbase;
};

View File

@ -26,233 +26,39 @@
#define ATAPI_CYCLES_PER_SECTOR (5000) // TBD for Dreamcast
#define ATAPI_STAT_BSY 0x80
#define ATAPI_STAT_DRDY 0x40
#define ATAPI_STAT_DMARDDF 0x20
#define ATAPI_STAT_SERVDSC 0x10
#define ATAPI_STAT_DRQ 0x08
#define ATAPI_STAT_CORR 0x04
#define ATAPI_STAT_CHECK 0x01
#define ATAPI_ERR_ABORT 0x04
#define ATAPI_INTREASON_COMMAND 0x01
#define ATAPI_INTREASON_IO 0x02
#define ATAPI_INTREASON_RELEASE 0x04
#define ATAPI_REG_DATA 0
#define ATAPI_REG_FEATURES 1
#define ATAPI_REG_INTREASON 2
#define ATAPI_REG_SAMTAG 3
#define ATAPI_REG_COUNTLOW 4
#define ATAPI_REG_COUNTHIGH 5
#define ATAPI_REG_DRIVESEL 6
#define ATAPI_REG_CMDSTATUS 7
#define ATAPI_REG_ERROR 16 // read-only ERROR (write is FEATURES)
#define GDROM_BUSY_STATE 0x00
#define GDROM_PAUSE_STATE 0x01
#define GDROM_STANDBY_STATE 0x02
#define GDROM_PLAY_STATE 0x03
#define GDROM_SEEK_STATE 0x04
#define GDROM_SCAN_STATE 0x05
#define GDROM_OPEN_STATE 0x06
#define GDROM_NODISC_STATE 0x07
#define GDROM_RETRY_STATE 0x08
#define GDROM_ERROR_STATE 0x09
#define ATAPI_REG_MAX 24
#define ATAPI_XFER_PIO 0x00
#define ATAPI_XFER_PIO_FLOW 0x08
#define ATAPI_XFER_SINGLE_DMA 0x10
#define ATAPI_XFER_MULTI_DMA 0x20
#define ATAPI_XFER_ULTRA_DMA 0x40
#define ATAPI_DATA_SIZE ( 64 * 1024 )
#define MAX_TRANSFER_SIZE ( 63488 )
void dc_cons_state::gdrom_set_status(UINT8 flag,bool state)
WRITE_LINE_MEMBER(dc_cons_state::ata_interrupt)
{
if(flag & ATAPI_STAT_DRQ)
printf("DRQ %02x\n",state);
if(state)
atapi_regs[ATAPI_REG_CMDSTATUS] |= flag;
if (state)
dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM;
else
atapi_regs[ATAPI_REG_CMDSTATUS] &= ~flag;
}
dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_GDROM;
void dc_cons_state::gdrom_set_error(UINT8 flag,bool state)
{
if(state)
atapi_regs[ATAPI_REG_ERROR] |= flag;
else
atapi_regs[ATAPI_REG_ERROR] &= ~flag;
}
void dc_cons_state::gdrom_raise_irq()
{
dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM;
dc_update_interrupt_status();
}
void dc_cons_state::atapi_cmd_nop()
{
gdrom_set_status(ATAPI_STAT_BSY,false);
gdrom_set_status(ATAPI_STAT_DRDY,true);
gdrom_set_status(ATAPI_STAT_CHECK,true);
gdrom_set_error(ATAPI_ERR_ABORT,true);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_COMMAND;
gdrom_raise_irq();
}
void dc_cons_state::atapi_cmd_packet()
{
atapi_data_ptr = 0;
atapi_data_len = 0;
/* we have no data */
atapi_xferlen = 0;
atapi_xfermod = 0;
atapi_cdata_wait = 0;
gdrom_set_status(ATAPI_STAT_BSY,false);
gdrom_set_status(ATAPI_STAT_DRQ,true);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_COMMAND;
/* TODO: raise irq? */
}
void dc_cons_state::atapi_cmd_identify_packet()
{
atapi_data_ptr = 0;
atapi_data_len = 512;
/* we have no data */
atapi_xferlen = 0;
atapi_xfermod = 0;
memset( atapi_data, 0, atapi_data_len );
atapi_data[ 0 ^ 1 ] = 0x86; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
atapi_data[ 1 ^ 1 ] = 0x00;
memset( &atapi_data[ 46 ], ' ', 8 );
atapi_data[ 46 ^ 1 ] = 'S';
atapi_data[ 47 ^ 1 ] = 'E';
memset( &atapi_data[ 54 ], ' ', 40 );
atapi_data[ 54 ^ 1 ] = 'C';
atapi_data[ 55 ^ 1 ] = 'D';
atapi_data[ 56 ^ 1 ] = '-';
atapi_data[ 57 ^ 1 ] = 'R';
atapi_data[ 58 ^ 1 ] = 'O';
atapi_data[ 59 ^ 1 ] = 'M';
atapi_data[ 60 ^ 1 ] = ' ';
atapi_data[ 61 ^ 1 ] = 'D';
atapi_data[ 62 ^ 1 ] = 'R';
atapi_data[ 63 ^ 1 ] = 'I';
atapi_data[ 64 ^ 1 ] = 'V';
atapi_data[ 65 ^ 1 ] = 'E';
atapi_data[ 66 ^ 1 ] = ' ';
atapi_data[ 67 ^ 1 ] = ' ';
atapi_data[ 68 ^ 1 ] = ' ';
atapi_data[ 69 ^ 1 ] = ' ';
atapi_data[ 70 ^ 1 ] = '6';
atapi_data[ 71 ^ 1 ] = '.';
atapi_data[ 72 ^ 1 ] = '4';
atapi_data[ 73 ^ 1 ] = '2';
atapi_data[ 98 ^ 1 ] = 0x04; // IORDY may be disabled
atapi_data[ 99 ^ 1 ] = 0x00;
atapi_regs[ATAPI_REG_COUNTLOW] = 0;
atapi_regs[ATAPI_REG_COUNTHIGH] = 2;
gdrom_set_status(ATAPI_STAT_BSY,false);
gdrom_set_status(ATAPI_STAT_DRQ,true);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO; /* ok? */
gdrom_raise_irq();
}
void dc_cons_state::atapi_cmd_set_features()
{
//TODO: error ABORT flag clear
// set xfer mode?
if (atapi_regs[ATAPI_REG_FEATURES] == 0x03)
{
printf("Set transfer mode to %x\n", atapi_regs[ATAPI_REG_COUNTLOW] & 0xf8);
xfer_mode = atapi_regs[ATAPI_REG_COUNTLOW] & 0xf8;
}
else
{
printf("ATAPI: Unknown set features %x\n", atapi_regs[ATAPI_REG_FEATURES]);
}
gdrom_set_status(ATAPI_STAT_BSY,false);
gdrom_set_error(ATAPI_ERR_ABORT,false);
gdrom_set_status(ATAPI_STAT_SERVDSC,false);
gdrom_set_status(ATAPI_STAT_DMARDDF,false);
gdrom_set_status(ATAPI_STAT_CHECK,false);
gdrom_set_status(ATAPI_STAT_DRDY,true);
atapi_data_ptr = 0;
atapi_data_len = 0;
gdrom_raise_irq();
}
TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_cmd_exec )
{
atapi_cmd_timer->adjust(attotime::never);
gdrom_set_status(ATAPI_STAT_CHECK,false);
gdrom_set_error(ATAPI_ERR_ABORT,false);
switch (cur_atapi_cmd)
{
case 0x00:
atapi_cmd_nop();
break;
case 0xa0: // PACKET
atapi_cmd_packet();
break;
case 0xa1: // IDENTIFY PACKET DEVICE
atapi_cmd_identify_packet();
break;
case 0xef: // SET FEATURES
atapi_cmd_set_features();
break;
default:
mame_printf_debug("ATAPI: Unknown IDE command %x\n", cur_atapi_cmd);
break;
}
}
TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end )
{
UINT8 sector_buffer[ 4096 ];
atapi_timer->adjust(attotime::never);
printf("atapi_xfer_end atapi_xferlen = %d, atapi_xfermod=%d\n", atapi_xfermod, atapi_xferlen );
printf("atapi_xfer_end atapi_xferlen = %d\n", atapi_xferlen );
mame_printf_debug("ATAPI: xfer_end. xferlen = %d, atapi_xfermod = %d\n", atapi_xferlen, atapi_xfermod);
//mame_printf_debug("ATAPI: xfer_end. xferlen = %d\n", atapi_xferlen);
address_space &space = m_maincpu->space(AS_PROGRAM);
while (atapi_xferlen > 0 )
{
struct sh4_ddt_dma ddtdata;
// get a sector from the SCSI device
gdrom->ReadData( sector_buffer, 2048 );
for (int i = 0; i < 2048/2; i++)
{
int d = m_ata->read_cs0(space, 0, 0xffff);
sector_buffer[ i*2 ] = d & 0xff;
sector_buffer[ (i*2)+1 ] = d >> 8;
}
atapi_xferlen -= 2048;
@ -270,93 +76,17 @@ TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end )
atapi_xferbase += 2048;
}
if (atapi_xfermod > MAX_TRANSFER_SIZE)
{
atapi_xferlen = MAX_TRANSFER_SIZE;
atapi_xfermod = atapi_xfermod - MAX_TRANSFER_SIZE;
}
else
{
atapi_xferlen = atapi_xfermod;
atapi_xfermod = 0;
}
if (atapi_xferlen > 0)
{
printf("ATAPI: starting next piece of multi-part transfer\n");
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
atapi_timer->adjust(m_maincpu->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048))));
}
else
{
printf("ATAPI: Transfer completed, dropping DRQ\n");
gdrom_set_status(ATAPI_STAT_DRDY,true);
gdrom_set_status(ATAPI_STAT_DRQ,false);
gdrom_set_status(ATAPI_STAT_BSY,false);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO | ATAPI_INTREASON_COMMAND;
atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
g1bus_regs[SB_GDST]=0;
dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM;
dc_update_interrupt_status();
}
gdrom_raise_irq();
printf( "atapi_xfer_end: %d %d\n", atapi_xferlen, atapi_xfermod );
g1bus_regs[SB_GDST]=0;
dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM;
dc_update_interrupt_status();
}
void dc_cons_state::dreamcast_atapi_init()
{
xfer_mode = ATAPI_XFER_PIO;
atapi_regs = auto_alloc_array_clear(machine(), UINT8, ATAPI_REG_MAX);
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
atapi_regs[ATAPI_REG_ERROR] = 1;
atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
atapi_data_ptr = 0;
atapi_data_len = 0;
atapi_cdata_wait = 0;
atapi_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_cons_state::atapi_xfer_end),this));
atapi_timer->adjust(attotime::never);
atapi_cmd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_cons_state::atapi_cmd_exec),this));
atapi_cmd_timer->adjust(attotime::never);
gdrom = NULL;
atapi_data = auto_alloc_array(machine(), UINT8, ATAPI_DATA_SIZE );
save_pointer(NAME(atapi_regs), ATAPI_REG_MAX );
save_pointer(NAME(atapi_data), ATAPI_DATA_SIZE / 2 );
save_item(NAME(atapi_data_ptr));
save_item(NAME(atapi_data_len));
save_item(NAME(atapi_xferlen));
save_item(NAME(atapi_xferbase));
save_item(NAME(atapi_cdata_wait));
save_item(NAME(atapi_xfermod));
gdrom = machine().device<gdrom_device>( "cdrom" );
}
void dc_cons_state::dreamcast_atapi_reset()
{
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
atapi_regs[ATAPI_REG_ERROR] = 1;
atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
atapi_data_ptr = 0;
atapi_data_len = 0;
atapi_cdata_wait = 0;
atapi_xferlen = 0;
atapi_xfermod = 0;
}
/*
@ -379,330 +109,6 @@ c000776 - DMA triggered to c008000
*/
READ32_MEMBER(dc_cons_state::dc_mess_gdrom_r)
{
// printf("gdrom_r: @ %x (off %x), mask %llx (PC %x)\n", offset, off, mem_mask, space.device().safe_pc());
switch(offset)
{
case 0x18/4:
return atapi_regs[ATAPI_REG_CMDSTATUS] | 0x10;
case 0x80/4:
UINT32 data;
if (atapi_data_ptr == 0 && atapi_data_len == 0)
{
// get the data from the device
if( atapi_xferlen > 0 )
{
gdrom->ReadData( atapi_data, atapi_xferlen );
atapi_data_len = atapi_xferlen;
}
if (atapi_xfermod > MAX_TRANSFER_SIZE)
{
atapi_xferlen = MAX_TRANSFER_SIZE;
atapi_xfermod = atapi_xfermod - MAX_TRANSFER_SIZE;
}
else
{
atapi_xferlen = atapi_xfermod;
atapi_xfermod = 0;
}
// printf( "atapi_r: atapi_xferlen=%d\n", atapi_xferlen );
if( atapi_xferlen != 0 )
{
//atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC;
//atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
else
{
printf("ATAPI: dropping DRQ\n");
//gdrom_set_status(ATAPI_STAT_DRQ,false);
//atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
//atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
gdrom_raise_irq();
}
if( atapi_cdata_wait )
{
data = atapi_data[atapi_data_ptr++];
data |= ( atapi_data[atapi_data_ptr++] << 8 );
atapi_cdata_wait-=2;
if( atapi_cdata_wait == 0 )
{
// printf( "atapi_r: read all bytes\n" );
atapi_data_ptr = 0;
atapi_data_len = 0;
if( atapi_xferlen == 0 )
{
printf("Read from SCSI\n");
//debugger_break(machine());
gdrom_set_status(ATAPI_STAT_DRQ,false);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
gdrom_raise_irq();
}
}
}
else
{
/* GD-Rom transfer via PIO, preliminary */
UINT8 pio_tr_size;
if(atapi_pio_ptr == 0)
{
gdrom->ReadData( pio_sector_buffer, 2048 );
}
data = 0;
pio_tr_size = 0;
for(int i=0;i<4;i++)
{
if(mem_mask & (0xff << i*8))
{
data|= pio_sector_buffer[atapi_pio_ptr+pio_tr_size]<<i*8;
pio_tr_size++;
}
}
printf("Read from PIO SCSI queue %08x %08x %08x\n",atapi_xferlen,atapi_pio_ptr,mem_mask);
atapi_xferlen -= pio_tr_size;
atapi_pio_ptr += pio_tr_size;
atapi_pio_ptr &=0x7ff;
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
if(atapi_pio_ptr == 0)
{
gdrom_set_status(ATAPI_STAT_DRDY,true);
gdrom_set_status(ATAPI_STAT_DRQ,false);
gdrom_set_status(ATAPI_STAT_BSY,false);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO | ATAPI_INTREASON_COMMAND;
atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
// g1bus_regs[SB_GDST]=0;
gdrom_raise_irq();
}
}
return data;
case 0x84/4:
return atapi_regs[ATAPI_REG_ERROR];
case 0x88/4:
return atapi_regs[ATAPI_REG_INTREASON];
case 0x8c/4:
return atapi_regs[ATAPI_REG_SAMTAG];
case 0x90/4:
return atapi_regs[ATAPI_REG_COUNTLOW];
case 0x94/4:
return atapi_regs[ATAPI_REG_COUNTHIGH];
case 0x98/4:
return atapi_regs[ATAPI_REG_DRIVESEL];
case 0x9c/4:
dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_GDROM;
dc_update_interrupt_status();
return atapi_regs[ATAPI_REG_CMDSTATUS] | 0x10;
}
return 0;
}
WRITE32_MEMBER(dc_cons_state::dc_mess_gdrom_w )
{
switch(offset)
{
case 0x18/4:
/* Device Control */
//COMBINE_DATA(&atapi_regs[ATAPI_REG_CMDSTATUS]);
return;
/* TODO: move this behind a timer */
case 0x80/4:
{
// printf("atapi_w: data=%04x\n", data );
// printf("ATAPI: packet write %04x\n", data);
atapi_data[atapi_data_ptr++] = data & 0xff;
atapi_data[atapi_data_ptr++] = data >> 8;
//printf("%02x %02x %d\n",data & 0xff, data >> 8,atapi_data_ptr);
if (atapi_cdata_wait)
{
// printf("ATAPI: waiting, ptr %d wait %d\n", atapi_data_ptr, atapi_cdata_wait);
if (atapi_data_ptr == atapi_cdata_wait)
{
// send it to the device
gdrom->WriteData( atapi_data, atapi_cdata_wait );
// assert IRQ
gdrom_raise_irq();
// not sure here, but clear DRQ at least?
gdrom_set_status(ATAPI_STAT_DRQ,false);
printf("cdata wait status\n");
atapi_cdata_wait = 0;
}
}
else if ( atapi_data_ptr == 12 )
{
int phase;
// printf("atapi_w: command %02x\n", atapi_data[0]&0xff );
// reset data pointer for reading SCSI results
atapi_data_ptr = 0;
atapi_data_len = 0;
// send it to the SCSI device
gdrom->SetCommand( atapi_data, 12 );
gdrom->ExecCommand( &atapi_xferlen );
gdrom->GetPhase( &phase );
if (atapi_xferlen != -1)
{
printf("ATAPI: SCSI command %02x returned %d bytes from the device\n", atapi_data[0]&0xff, atapi_xferlen);
// store the returned command length in the ATAPI regs, splitting into
// multiple transfers if necessary
atapi_xfermod = 0;
if (atapi_xferlen > MAX_TRANSFER_SIZE)
{
atapi_xfermod = atapi_xferlen - MAX_TRANSFER_SIZE;
atapi_xferlen = MAX_TRANSFER_SIZE;
}
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
if (atapi_xferlen == 0)
{
// if no data to return, set the registers properly
//atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRDY;
gdrom_set_status(ATAPI_STAT_DRDY,true);
gdrom_set_status(ATAPI_STAT_DRQ,false);
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO|ATAPI_INTREASON_COMMAND;
}
else
{
printf("ATAPI features %02x\n",atapi_regs[ATAPI_REG_FEATURES]);
// indicate data ready: set DRQ and DMA ready, and IO in INTREASON
if (atapi_regs[ATAPI_REG_FEATURES] & 0x01) // DMA feature
{
//gdrom_set_status(ATAPI_STAT_BSY | ATAPI_STAT_DRDY | ATAPI_STAT_SERVDSC,true);
//atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_BSY | ATAPI_STAT_DRDY | ATAPI_STAT_SERVDSC;
}
else
{
//gdrom_set_status(ATAPI_STAT_SERVDSC,true);
/* Ok? */
gdrom_set_status(ATAPI_STAT_DRQ,true);
//atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC | ATAPI_STAT_DRQ;
}
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
switch( phase )
{
case SCSI_PHASE_DATAOUT:
case SCSI_PHASE_DATAIN:
atapi_cdata_wait = atapi_xferlen;
break;
}
// perform special ATAPI processing of certain commands
switch (atapi_data[0]&0xff)
{
case 0x00: // BUS RESET / TEST UNIT READY
case 0xbb: // SET CDROM SPEED
//atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
break;
case 0x45: // PLAY
gdrom_set_status(ATAPI_STAT_BSY,true);
atapi_timer->adjust( downcast<cpu_device *>(&space.device())->cycles_to_attotime(ATAPI_CYCLES_PER_SECTOR ) );
break;
}
// assert IRQ
gdrom_raise_irq();
}
else
{
printf("ATAPI: SCSI device returned error!\n");
//atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_CHECK;
//atapi_regs[ATAPI_REG_ERROR] = 0x50; // sense key = ILLEGAL REQUEST
atapi_regs[ATAPI_REG_COUNTLOW] = 0;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0;
}
}
}
return;
case 0x84/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_FEATURES]);
return;
case 0x88/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_INTREASON]);
return;
case 0x8c/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_SAMTAG]);
return;
case 0x90/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_COUNTLOW]);
return;
case 0x94/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_COUNTHIGH]);
return;
case 0x98/4:
COMBINE_DATA(&atapi_regs[ATAPI_REG_DRIVESEL]);
return;
case 0x9c/4:
{
printf("ATAPI command %x issued! (PC=%x)\n", data, space.device().safe_pc());
gdrom_set_status(ATAPI_STAT_BSY,true);
gdrom_set_status(ATAPI_STAT_DRQ,false);
gdrom_set_status(ATAPI_STAT_DRDY,false);
cur_atapi_cmd = data;
/* TODO: timing of this */
atapi_cmd_timer->adjust(m_maincpu->cycles_to_attotime(ATAPI_CYCLES_PER_SECTOR));
}
return;
}
}
// register decode helpers
// this accepts only 32-bit accesses
int dc_cons_state::decode_reg32_64( UINT32 offset, UINT64 mem_mask, UINT64 *shift)
{
int reg = offset * 2;
*shift = 0;
// non 32-bit accesses have not yet been seen here, we need to know when they are
if ((mem_mask != U64(0xffffffff00000000)) && (mem_mask != U64(0x00000000ffffffff)))
{
mame_printf_verbose("%s:Wrong mask!\n", machine().describe_context());
// debugger_break(machine);
}
if (mem_mask == U64(0xffffffff00000000))
{
reg++;
*shift = 32;
}
return reg;
}
READ32_MEMBER(dc_cons_state::dc_mess_g1_ctrl_r )
{
switch(offset)
@ -740,14 +146,19 @@ WRITE32_MEMBER(dc_cons_state::dc_mess_g1_ctrl_w )
atapi_xferbase = g1bus_regs[SB_GDSTAR];
atapi_timer->adjust(m_maincpu->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048))));
atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
// atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
}
break;
// The following is required to unlock the GD-ROM. The original Japanese BIOS doesn't need it
case SB_GDLEN:
atapi_xferlen = data;
break;
// The following is required to unlock the GD-ROM. The original Japanese BIOS doesn't need it
case GD_UNLOCK:
if (data==0 || data==0x001fffff || data==0x42fe)
{
atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
// atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
printf("Unlocking GD-ROM! %x\n", data);
}
break;