Redid the ATAPI READ CD command completely and fixed IOCTL raw sector reading;
Added the ATAPI READ CD MSF command; UNIT ATTENTION is now a condition above the SCSI/ATAPI senses so that non-UNIT ATTENTION senses can still be reported if said condition is present, should they occur; Applies mainline PCem commit: Added code generation for RMW versions of INC/DEC.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include "ntddcdrm.h"
|
||||
#include "ntddscsi.h"
|
||||
#include "ibm.h"
|
||||
#include "cdrom.h"
|
||||
#include "cdrom-ioctl.h"
|
||||
@@ -208,7 +209,7 @@ static void ioctl_seek(uint32_t pos)
|
||||
{
|
||||
if (!cdrom_drive) return;
|
||||
// ioctl_cd_state = CD_STOPPED;
|
||||
pclog("Seek %08X\n", pos);
|
||||
// pclog("Seek %08X\n", pos);
|
||||
ioctl_cd_pos = pos;
|
||||
ioctl_cd_state = CD_STOPPED;
|
||||
/* pos+=150;
|
||||
@@ -268,7 +269,7 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i
|
||||
int lb=0;
|
||||
if (!cdrom_drive) return 0;
|
||||
ioctl_cd_state = CD_STOPPED;
|
||||
pclog("ioctl_readtoc(): IOCtl state now CD_STOPPED\n");
|
||||
// pclog("ioctl_readtoc(): IOCtl state now CD_STOPPED\n");
|
||||
ioctl_open(0);
|
||||
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&lbtoc,sizeof(lbtoc),&size,NULL);
|
||||
ioctl_close();
|
||||
@@ -448,16 +449,29 @@ static int is_track_audio(uint32_t pos)
|
||||
if (!tocvalid)
|
||||
return 0;
|
||||
|
||||
for (c = toc.FirstTrack; c < toc.LastTrack; c++)
|
||||
// for (c = toc.FirstTrack; c <= toc.LastTrack; c++)
|
||||
for (c = 0; c <= toc.LastTrack; c++)
|
||||
{
|
||||
uint32_t track_address = toc.TrackData[c].Address[3] +
|
||||
(toc.TrackData[c].Address[2] * 75) +
|
||||
(toc.TrackData[c].Address[1] * 75 * 60);
|
||||
uint32_t track_address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
|
||||
|
||||
// pclog("Track address: %i (%02X%02X%02X%02X), Position: %i\n", track_address, toc.TrackData[c].Address[0], toc.TrackData[c].Address[1], toc.TrackData[c].Address[2], toc.TrackData[c].Address[3], pos);
|
||||
|
||||
if (track_address <= pos)
|
||||
control = toc.TrackData[c].Control;
|
||||
}
|
||||
return (control & 4) ? 0 : 1;
|
||||
// pclog("Control: %i\n", control);
|
||||
if ((control & 0xd) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if ((control & 0xd) == 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
|
||||
@@ -469,24 +483,169 @@ static int ioctl_is_track_audio(uint32_t pos, int ismsf)
|
||||
int f = pos & 0xff;
|
||||
pos = MSFtoLBA(m, s, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += 150;
|
||||
}
|
||||
return is_track_audio(pos);
|
||||
}
|
||||
|
||||
static void ioctl_readsector_raw(uint8_t *b, int sector)
|
||||
/* Direct SCSI read in MSF mode. */
|
||||
int SCSIReadMSF(uint8_t *b, int sector)
|
||||
{
|
||||
LARGE_INTEGER pos;
|
||||
long size;
|
||||
uint32_t temp;
|
||||
if (!cdrom_drive) return;
|
||||
if (ioctl_cd_state == CD_PLAYING)
|
||||
return;
|
||||
HANDLE fh;
|
||||
DWORD ioctl_bytes;
|
||||
DWORD out_size;
|
||||
int ioctl_rv;
|
||||
const UCHAR cdb_0[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 0, 0 };
|
||||
const UCHAR cdb_1[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 1, 0 };
|
||||
const UCHAR cdb_2[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 2, 0 };
|
||||
const UCHAR cdb_4[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 4, 0 };
|
||||
UCHAR buf[2856];
|
||||
struct sptd_with_sense
|
||||
{
|
||||
SCSI_PASS_THROUGH_DIRECT s;
|
||||
UCHAR sense[128];
|
||||
} sptd;
|
||||
|
||||
ioctl_cd_state = CD_STOPPED;
|
||||
pos.QuadPart=sector*2048; /* Yes, 2048, the API specifies that. */
|
||||
ioctl_open(0);
|
||||
/* This should read the actual raw sectors from the disc. */
|
||||
DeviceIoControl( hIOCTL, IOCTL_CDROM_RAW_READ, NULL, 0, b, 1, &size, NULL );
|
||||
ioctl_close();
|
||||
ioctl_open(0);
|
||||
|
||||
memset(&sptd, 0, sizeof(sptd));
|
||||
sptd.s.Length = sizeof(sptd.s);
|
||||
sptd.s.CdbLength = sizeof(cdb_0); /* All 4 of our CDB's are identically sized, therefore we can take this shortcut. */
|
||||
sptd.s.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd.s.TimeOutValue = 30;
|
||||
sptd.s.DataBuffer = buf;
|
||||
sptd.s.DataTransferLength = 2856;
|
||||
sptd.s.SenseInfoLength = sizeof(sptd.sense);
|
||||
sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense);
|
||||
|
||||
/* Fill the buffer with zeroes. */
|
||||
memset(b, 0, 2856);
|
||||
|
||||
/* First, read without subchannel data so we at least have *SOMETHING*. */
|
||||
memcpy(sptd.s.Cdb, cdb_0, sizeof(cdb_0));
|
||||
ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) without subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b, sptd.s.DataBuffer, 2648);
|
||||
|
||||
/* Next, try to read RAW subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_1, sizeof(cdb_1));
|
||||
ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with RAW subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648, sptd.s.DataBuffer + 2648, 96);
|
||||
|
||||
/* Next, try to read Q subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_2, sizeof(cdb_2));
|
||||
ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with Q subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648 + 96, sptd.s.DataBuffer + 2648, 16);
|
||||
|
||||
/* Next, try to read R - W subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_4, sizeof(cdb_4));
|
||||
ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with R - W subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648 + 96 + 16, sptd.s.DataBuffer + 2648, 96);
|
||||
|
||||
ioctl_close();
|
||||
|
||||
return ioctl_rv;
|
||||
}
|
||||
|
||||
/* Direct SCSI read in LBA mode. */
|
||||
void SCSIRead(uint8_t *b, int sector)
|
||||
{
|
||||
HANDLE fh;
|
||||
DWORD ioctl_bytes;
|
||||
DWORD out_size;
|
||||
BOOL ioctl_rv;
|
||||
const UCHAR cdb_0[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 0, 0 };
|
||||
const UCHAR cdb_1[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 1, 0 };
|
||||
const UCHAR cdb_2[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 2, 0 };
|
||||
const UCHAR cdb_4[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 4, 0 };
|
||||
UCHAR buf[2856];
|
||||
struct sptd_with_sense
|
||||
{
|
||||
SCSI_PASS_THROUGH_DIRECT s;
|
||||
UCHAR sense[128];
|
||||
} sptd;
|
||||
|
||||
ioctl_open(0);
|
||||
|
||||
memset(&sptd, 0, sizeof(sptd));
|
||||
sptd.s.Length = sizeof(sptd.s);
|
||||
sptd.s.CdbLength = sizeof(cdb_0); /* All 4 of our CDB's are identically sized, therefore we can take this shortcut. */
|
||||
sptd.s.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd.s.TimeOutValue = 30;
|
||||
sptd.s.DataBuffer = buf;
|
||||
sptd.s.DataTransferLength = 2856;
|
||||
sptd.s.SenseInfoLength = sizeof(sptd.sense);
|
||||
sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense);
|
||||
|
||||
/* Fill the buffer with zeroes. */
|
||||
memset(b, 0, 2856);
|
||||
|
||||
/* First, read without subchannel data so we at least have *SOMETHING*. */
|
||||
memcpy(sptd.s.Cdb, cdb_0, sizeof(cdb_0));
|
||||
ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) without subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b, sptd.s.DataBuffer, 2648);
|
||||
|
||||
/* Next, try to read RAW subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_1, sizeof(cdb_1));
|
||||
ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with RAW subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648, sptd.s.DataBuffer + 2648, 96);
|
||||
|
||||
/* Next, try to read Q subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_2, sizeof(cdb_2));
|
||||
ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with Q subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648 + 96, sptd.s.DataBuffer + 2648, 16);
|
||||
|
||||
/* Next, try to read R - W subchannel data. */
|
||||
memcpy(sptd.s.Cdb, cdb_4, sizeof(cdb_4));
|
||||
ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL);
|
||||
// pclog("Read (%i) with R - W subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE");
|
||||
memcpy(b + 2648 + 96 + 16, sptd.s.DataBuffer + 2648, 96);
|
||||
|
||||
ioctl_close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ioctl_readsector_raw(uint8_t *b, int sector, int ismsf)
|
||||
{
|
||||
RAW_READ_INFO in;
|
||||
LARGE_INTEGER pos;
|
||||
DWORD count = 0;
|
||||
long size;
|
||||
uint32_t temp;
|
||||
if (!cdrom_drive) return;
|
||||
if (ioctl_cd_state == CD_PLAYING)
|
||||
return;
|
||||
|
||||
if (ismsf)
|
||||
{
|
||||
if (!SCSIReadMSF(b, sector))
|
||||
{
|
||||
int m = (sector >> 16) & 0xff;
|
||||
int s = (sector >> 8) & 0xff;
|
||||
int f = sector & 0xff;
|
||||
sector = (m * 60 * 75) + (s * 75) + f;
|
||||
if (sector < 150)
|
||||
{
|
||||
memset(b, 0, 2856);
|
||||
return;
|
||||
}
|
||||
sector += 150;
|
||||
SCSIRead(b, sector);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SCSIRead(b, sector);
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
|
||||
@@ -691,11 +850,14 @@ int ioctl_open(char d)
|
||||
if (!ioctl_inited)
|
||||
{
|
||||
sprintf(ioctl_path,"\\\\.\\%c:",d);
|
||||
pclog("Path is %s\n",ioctl_path);
|
||||
// pclog("Path is %s\n",ioctl_path);
|
||||
tocvalid=0;
|
||||
}
|
||||
// pclog("Opening %s\n",ioctl_path);
|
||||
hIOCTL = CreateFile(/*"\\\\.\\g:"*/ioctl_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
|
||||
// hIOCTL = CreateFile(/*"\\\\.\\g:"*/ioctl_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
|
||||
hIOCTL = CreateFile(ioctl_path, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (!hIOCTL)
|
||||
{
|
||||
//fatal("IOCTL");
|
||||
|
@@ -28,42 +28,42 @@ void iso_audio_callback(int16_t *output, int len)
|
||||
|
||||
void iso_audio_stop()
|
||||
{
|
||||
pclog("iso_audio_stop stub\n");
|
||||
// pclog("iso_audio_stop stub\n");
|
||||
}
|
||||
|
||||
static int get_track_nr(uint32_t pos)
|
||||
{
|
||||
pclog("get_track_nr stub\n");
|
||||
// pclog("get_track_nr stub\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iso_playaudio(uint32_t pos, uint32_t len, int ismsf)
|
||||
{
|
||||
pclog("iso_playaudio stub\n");
|
||||
// pclog("iso_playaudio stub\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void iso_pause(void)
|
||||
{
|
||||
pclog("iso_pause stub\n");
|
||||
// pclog("iso_pause stub\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void iso_resume(void)
|
||||
{
|
||||
pclog("iso_resume stub\n");
|
||||
// pclog("iso_resume stub\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void iso_stop(void)
|
||||
{
|
||||
pclog("iso_stop stub\n");
|
||||
// pclog("iso_stop stub\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void iso_seek(uint32_t pos)
|
||||
{
|
||||
pclog("iso_seek stub\n");
|
||||
// pclog("iso_seek stub\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,18 +112,18 @@ static int iso_medium_changed(void)
|
||||
|
||||
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
|
||||
{
|
||||
pclog("iso_getcurrentsubchannel stub\n");
|
||||
// pclog("iso_getcurrentsubchannel stub\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iso_eject(void)
|
||||
{
|
||||
pclog("iso_eject stub\n");
|
||||
// pclog("iso_eject stub\n");
|
||||
}
|
||||
|
||||
static void iso_load(void)
|
||||
{
|
||||
pclog("iso_load stub\n");
|
||||
// pclog("iso_load stub\n");
|
||||
}
|
||||
|
||||
static void iso_readsector(uint8_t *b, int sector)
|
||||
@@ -137,12 +137,18 @@ static void iso_readsector(uint8_t *b, int sector)
|
||||
|
||||
static void lba_to_msf(uint8_t *buf, int lba)
|
||||
{
|
||||
#if 0
|
||||
double dlba = (double) lba + 150;
|
||||
buf[2] = (uint8_t) (((uint32_t) dlba) % 75);
|
||||
dlba /= 75;
|
||||
buf[1] = (uint8_t) (((uint32_t) dlba) % 60);
|
||||
dlba /= 60;
|
||||
buf[0] = (uint8_t) dlba;
|
||||
#endif
|
||||
lba += 150;
|
||||
buf[0] = (lba / 75) / 60;
|
||||
buf[1] = (lba / 75) % 60;
|
||||
buf[2] = lba % 75;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -155,10 +161,24 @@ static void lba_to_msf(uint8_t *buf, int lba)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void iso_readsector_raw(uint8_t *b, int sector)
|
||||
static void iso_readsector_raw(uint8_t *b, int sector, int ismsf)
|
||||
{
|
||||
uint32_t temp;
|
||||
if (!cdrom_drive) return;
|
||||
memset(b, 0, 2856);
|
||||
if (ismsf)
|
||||
{
|
||||
int m = (sector >> 16) & 0xff;
|
||||
int s = (sector >> 8) & 0xff;
|
||||
int f = sector & 0xff;
|
||||
sector = (m * 60 * 75) + (s * 75) + f;
|
||||
if (sector < 150)
|
||||
{
|
||||
memset(b, 0, 2856);
|
||||
return;
|
||||
}
|
||||
sector -= 150;
|
||||
}
|
||||
iso_image = fopen(iso_path, "rb");
|
||||
fseek(iso_image, sector*2048, SEEK_SET);
|
||||
fread(b+16, 2048, 1, iso_image);
|
||||
@@ -174,6 +194,8 @@ static void iso_readsector_raw(uint8_t *b, int sector)
|
||||
b += 4;
|
||||
b += 2048;
|
||||
memset(b, 0, 288);
|
||||
b += 288;
|
||||
memset(b, 0, 392);
|
||||
}
|
||||
|
||||
static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single)
|
||||
@@ -343,7 +365,7 @@ int iso_open(char *fn)
|
||||
if (!iso_inited || iso_changed)
|
||||
{
|
||||
sprintf(iso_path, "%s", fn);
|
||||
pclog("Path is %s\n", iso_path);
|
||||
// pclog("Path is %s\n", iso_path);
|
||||
}
|
||||
iso_image = fopen(iso_path, "rb");
|
||||
cdrom = &iso_cdrom;
|
||||
|
@@ -66,7 +66,7 @@ static void null_readsector(uint8_t *b, int sector)
|
||||
{
|
||||
}
|
||||
|
||||
static void null_readsector_raw(uint8_t *b, int sector)
|
||||
static void null_readsector_raw(uint8_t *b, int sector, int ismsf)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ typedef struct CDROM
|
||||
int (*readtoc_raw)(uint8_t *b, int maxlen);
|
||||
uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
|
||||
void (*readsector)(uint8_t *b, int sector);
|
||||
void (*readsector_raw)(uint8_t *b, int sector);
|
||||
void (*readsector_raw)(uint8_t *b, int sector, int ismsf);
|
||||
void (*playaudio)(uint32_t pos, uint32_t len, int ismsf);
|
||||
void (*seek)(uint32_t pos);
|
||||
void (*load)(void);
|
||||
|
@@ -47,7 +47,7 @@ RecompOpFn recomp_opcodes[512] =
|
||||
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, ropCLD, ropSTD, NULL, ropFF_16,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, ropCLD, ropSTD, ropFE, ropFF_16,
|
||||
|
||||
/*32-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
@@ -69,7 +69,7 @@ RecompOpFn recomp_opcodes[512] =
|
||||
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, ropCLD, ropSTD, NULL, ropFF_32
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, ropCLD, ropSTD, ropFE, ropFF_32
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_0f[512] =
|
||||
|
@@ -14,28 +14,122 @@ static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t codegen_temp;
|
||||
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
return 0;
|
||||
|
||||
CALL_FUNC(flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
}
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
host_reg = 0;
|
||||
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_INC8);
|
||||
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_DEC8);
|
||||
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t codegen_temp;
|
||||
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC(flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
{
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
host_reg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_W(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_INC16);
|
||||
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_DEC16);
|
||||
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
@@ -66,25 +160,68 @@ static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
|
||||
}
|
||||
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC(flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
host_reg = 0;
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
{
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
host_reg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_L(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_INC32);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_DEC32);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
526
src/ide.c
526
src/ide.c
@@ -167,6 +167,49 @@ int ide_ter_enabled = 0;
|
||||
|
||||
uint8_t getstat(IDE *ide) { return ide->atastat; }
|
||||
|
||||
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint8_t user_data[2048];
|
||||
uint8_t ecc[288];
|
||||
} m1_data_t;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint8_t sub_header[8];
|
||||
uint8_t user_data[2328];
|
||||
} m2_data_t;
|
||||
|
||||
typedef union __attribute__((packed))
|
||||
{
|
||||
m1_data_t m1_data;
|
||||
m2_data_t m2_data;
|
||||
uint8_t raw_data[2352];
|
||||
} sector_data_t;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uint8_t sync[12];
|
||||
uint8_t header[4];
|
||||
sector_data_t data;
|
||||
uint8_t c2[296];
|
||||
uint8_t subchannel_raw[96];
|
||||
uint8_t subchannel_q[16];
|
||||
uint8_t subchannel_rw[96];
|
||||
} cdrom_sector_t;
|
||||
|
||||
typedef union __attribute__((packed))
|
||||
{
|
||||
cdrom_sector_t cdrom_sector;
|
||||
uint8_t buffer[2856];
|
||||
} sector_buffer_t;
|
||||
|
||||
sector_buffer_t cdrom_sector_buffer;
|
||||
|
||||
int cdrom_sector_type, cdrom_sector_flags;
|
||||
int cdrom_sector_size, cdrom_sector_ismsf;
|
||||
|
||||
int image_is_hdi(const char *s)
|
||||
{
|
||||
int i, len;
|
||||
@@ -381,10 +424,8 @@ static void ide_atapi_identify(IDE *ide)
|
||||
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
|
||||
ide_padstr((char *) (ide->buffer + 23), emulator_version, 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "86BoxCD", 40); /* Model */
|
||||
ide->buffer[49] = 0x300; /* LBA and DMA supported */
|
||||
ide->buffer[62] = ide->dma_identify_data[0];
|
||||
ide->buffer[63] = ide->dma_identify_data[1];
|
||||
ide->buffer[88] = ide->dma_identify_data[2];
|
||||
ide->buffer[49] = 0x200; /* LBA supported */
|
||||
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -551,6 +592,10 @@ int ide_set_features(IDE *ide)
|
||||
case 0xc2:
|
||||
return 1;
|
||||
case 0x03:
|
||||
if (ide->type == IDE_CDROM)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
switch(ide->secount >> 3)
|
||||
{
|
||||
case 0:
|
||||
@@ -678,6 +723,8 @@ void resetide(void)
|
||||
// ide_drives[1].type = IDE_CDROM;
|
||||
|
||||
page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED;
|
||||
|
||||
SCSISense.UnitAttention = 0;
|
||||
}
|
||||
|
||||
int idetimes=0;
|
||||
@@ -1791,6 +1838,282 @@ static void atapi_sense_clear(int command, int ignore_ua)
|
||||
}
|
||||
}
|
||||
|
||||
static int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type)
|
||||
{
|
||||
if ((cdrom_sector_flags & 0x06) == 0x02)
|
||||
{
|
||||
/* Add error flags. */
|
||||
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294);
|
||||
cdrom_sector_size += 294;
|
||||
}
|
||||
else if ((cdrom_sector_flags & 0x06) == 0x04)
|
||||
{
|
||||
/* Add error flags. */
|
||||
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296);
|
||||
cdrom_sector_size += 296;
|
||||
}
|
||||
else if ((cdrom_sector_flags & 0x06) == 0x06)
|
||||
{
|
||||
pclog("Invalid error flags\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if (real_sector_type == 1)
|
||||
{ */
|
||||
if ((cdrom_sector_flags & 0x700) == 0x100)
|
||||
{
|
||||
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96);
|
||||
cdrom_sector_size += 96;
|
||||
}
|
||||
else if ((cdrom_sector_flags & 0x700) == 0x200)
|
||||
{
|
||||
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16);
|
||||
cdrom_sector_size += 16;
|
||||
}
|
||||
else if ((cdrom_sector_flags & 0x700) == 0x400)
|
||||
{
|
||||
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96);
|
||||
cdrom_sector_size += 96;
|
||||
}
|
||||
else if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400))
|
||||
{
|
||||
pclog("Invalid subchannel data flags\n");
|
||||
return 0;
|
||||
}
|
||||
// }
|
||||
|
||||
// pclog("CD-ROM sector size after processing: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags);
|
||||
|
||||
return cdrom_sector_size;
|
||||
}
|
||||
|
||||
static int cdrom_LBAtoMSF_accurate(IDE *ide)
|
||||
{
|
||||
int temp_pos;
|
||||
int m, s, f;
|
||||
|
||||
temp_pos = ide->cdpos;
|
||||
f = temp_pos % 75;
|
||||
temp_pos -= f;
|
||||
temp_pos /= 75;
|
||||
s = temp_pos % 60;
|
||||
temp_pos -= s;
|
||||
temp_pos /= 60;
|
||||
m = temp_pos;
|
||||
|
||||
return ((m << 16) | (s << 8) | f);
|
||||
}
|
||||
|
||||
static int cdrom_read_data(IDE *ide, uint8_t *buffer)
|
||||
{
|
||||
int real_sector_type;
|
||||
uint8_t *b;
|
||||
uint8_t *temp_b;
|
||||
int is_audio;
|
||||
int real_pos;
|
||||
|
||||
b = temp_b = buffer;
|
||||
|
||||
if (cdrom_sector_ismsf)
|
||||
{
|
||||
real_pos = cdrom_LBAtoMSF_accurate(ide);
|
||||
}
|
||||
else
|
||||
{
|
||||
real_pos = ide->cdpos;
|
||||
}
|
||||
|
||||
memset(cdrom_sector_buffer.buffer, 0, 2856);
|
||||
|
||||
cdrom->readsector_raw(cdrom_sector_buffer.buffer, real_pos, cdrom_sector_ismsf);
|
||||
is_audio = cdrom->is_track_audio(real_pos, cdrom_sector_ismsf);
|
||||
|
||||
if (!(cdrom_sector_flags & 0xf0)) /* 0x00 and 0x08 are illegal modes */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cdrom->is_track_audio(ide->cdpos, 0))
|
||||
{
|
||||
real_sector_type = 1;
|
||||
|
||||
if (cdrom_sector_type > 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(b, cdrom_sector_buffer.buffer, 2352);
|
||||
cdrom_sector_size = 2352;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((cdrom_sector_flags & 0x18) == 0x08) /* EDC/ECC without user data is an illegal mode */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cdrom_sector_size = 0;
|
||||
|
||||
if (cdrom_sector_flags & 0x80) /* Sync */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12);
|
||||
cdrom_sector_size += 12;
|
||||
temp_b += 12;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x20) /* Header */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4);
|
||||
cdrom_sector_size += 4;
|
||||
temp_b += 4;
|
||||
}
|
||||
|
||||
switch(cdrom_sector_buffer.cdrom_sector.header[3])
|
||||
{
|
||||
case 1:
|
||||
real_sector_type = 2; /* Mode 1 */
|
||||
break;
|
||||
case 2:
|
||||
real_sector_type = 3; /* Mode 2 */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_sector_type == 2)
|
||||
{
|
||||
if ((cdrom_sector_type == 0) || (cdrom_sector_type == 2))
|
||||
{
|
||||
/* Mode 1 sector, expected type is 1 type. */
|
||||
if (cdrom_sector_flags & 0x40) /* Sub-header */
|
||||
{
|
||||
if (!(cdrom_sector_flags & 0x10)) /* No user data */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
}
|
||||
}
|
||||
if (cdrom_sector_flags & 0x10) /* User data */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048);
|
||||
cdrom_sector_size += 2048;
|
||||
temp_b += 2048;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x08) /* EDC/ECC */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288);
|
||||
cdrom_sector_size += 288;
|
||||
temp_b += 288;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (real_sector_type == 3)
|
||||
{
|
||||
if ((cdrom_sector_type == 0) || (cdrom_sector_type == 3))
|
||||
{
|
||||
/* Mode 2 sector, non-XA mode. */
|
||||
if (cdrom_sector_flags & 0x40) /* Sub-header */
|
||||
{
|
||||
if (!(cdrom_sector_flags & 0x10)) /* No user data */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
}
|
||||
}
|
||||
if (cdrom_sector_flags & 0x10) /* User data */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 2328);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328);
|
||||
cdrom_sector_size += 2328;
|
||||
temp_b += 2328;
|
||||
}
|
||||
}
|
||||
else if (cdrom_sector_type == 4)
|
||||
{
|
||||
/* Mode 2 sector, XA Form 1 mode */
|
||||
if ((cdrom_sector_flags & 0xf0) == 0x30)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x40) /* Sub-header */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x10) /* User data */
|
||||
{
|
||||
if ((cdrom_sector_flags & 0xf0) == 0x10)
|
||||
{
|
||||
/* The data is alone, include sub-header. */
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
}
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2040);
|
||||
cdrom_sector_size += 2040;
|
||||
temp_b += 2040;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x08) /* EDC/ECC */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data + 2040, 288);
|
||||
cdrom_sector_size += 288;
|
||||
temp_b += 288;
|
||||
}
|
||||
}
|
||||
else if (cdrom_sector_type == 5)
|
||||
{
|
||||
/* Mode 2 sector, XA Form 2 mode */
|
||||
if ((cdrom_sector_flags & 0xf0) == 0x30)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* Mode 2 sector, XA Form 1 mode */
|
||||
if (cdrom_sector_flags & 0x40) /* Sub-header */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8);
|
||||
cdrom_sector_size += 8;
|
||||
temp_b += 8;
|
||||
}
|
||||
if (cdrom_sector_flags & 0x10) /* User data */
|
||||
{
|
||||
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328);
|
||||
cdrom_sector_size += 2328;
|
||||
temp_b += 2328;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// pclog("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags);
|
||||
return cdrom_add_error_and_subchannel(b, real_sector_type);
|
||||
}
|
||||
|
||||
static void atapicommand(int ide_board)
|
||||
{
|
||||
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
||||
@@ -1802,7 +2125,6 @@ static void atapicommand(int ide_board)
|
||||
int pos=0;
|
||||
unsigned char temp;
|
||||
uint32_t size;
|
||||
int is_error;
|
||||
uint8_t page_code;
|
||||
int max_len;
|
||||
unsigned idx = 0;
|
||||
@@ -1818,7 +2140,7 @@ static void atapicommand(int ide_board)
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins);
|
||||
pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention);
|
||||
|
||||
int CdbLength;
|
||||
for (CdbLength = 1; CdbLength < 12; CdbLength++)
|
||||
@@ -1828,39 +2150,44 @@ static void atapicommand(int ide_board)
|
||||
msf=idebufferb[1]&2;
|
||||
ide->cdlen=0;
|
||||
|
||||
is_error = 0;
|
||||
|
||||
if (cdrom->medium_changed())
|
||||
{
|
||||
SCSICDROM_Insert();
|
||||
}
|
||||
/*If UNIT_ATTENTION is set, error out with NOT_READY.
|
||||
VIDE-CDD.SYS will then issue a READ_TOC, which can pass through UNIT_ATTENTION and will clear sense.
|
||||
NT 3.1 / AZTIDECD.SYS will then issue a REQUEST_SENSE, which can also pass through UNIT_ATTENTION but will clear sense AFTER sending it back.
|
||||
In any case, if the command cannot pass through, set our state to errored.*/
|
||||
if (!(SCSICommandTable[idebufferb[0]] & ALLOW_UA) && SCSISense.SenseKey == SENSE_UNIT_ATTENTION)
|
||||
|
||||
if (!cdrom->ready() && SCSISense.UnitAttention)
|
||||
{
|
||||
atapi_cmd_error(ide, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq);
|
||||
is_error = 1;
|
||||
/* If the drive is not ready, there is no reason to keep the
|
||||
UNIT ATTENTION condition present, as we only use it to mark
|
||||
disc changes. */
|
||||
SCSISense.UnitAttention = 0;
|
||||
}
|
||||
/*Unless the command issued was a REQUEST_SENSE or TEST_UNIT_READY, clear sense.
|
||||
This is important because both VIDE-CDD.SYS and NT 3.1 / AZTIDECD.SYS rely on this behaving VERY specifically.
|
||||
VIDE-CDD.SYS will clear sense through READ_TOC, while NT 3.1 / AZTIDECD.SYS will issue a REQUEST_SENSE.*/
|
||||
if ((idebufferb[0]!=GPCMD_REQUEST_SENSE) && (idebufferb[0]!=GPCMD_TEST_UNIT_READY))
|
||||
|
||||
/* If the UNIT ATTENTION condition is set and the command does not allow
|
||||
execution under it, error out and report the condition. */
|
||||
if (!(SCSICommandTable[idebufferb[0]] & ALLOW_UA) && SCSISense.UnitAttention)
|
||||
{
|
||||
// pclog("UNIT ATTENTION: Command not allowed to pass through\n");
|
||||
atapi_cmd_error(ide, SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (idebufferb[0] == GPCMD_READ_TOC_PMA_ATIP)
|
||||
{
|
||||
SCSISense.UnitAttention = 0;
|
||||
}
|
||||
|
||||
/* Unless the command is REQUEST SENSE, clear the sense. This will *NOT*
|
||||
the UNIT ATTENTION condition if it's set. */
|
||||
if (idebufferb[0]!=GPCMD_REQUEST_SENSE)
|
||||
{
|
||||
/* GPCMD_TEST_UNIT_READY is NOT supposed to clear sense! */
|
||||
atapi_sense_clear(idebufferb[0], 1);
|
||||
}
|
||||
|
||||
/*If our state has been set to errored, clear it, and return.*/
|
||||
if (is_error)
|
||||
{
|
||||
is_error = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next it's time for NOT READY. */
|
||||
if ((SCSICommandTable[idebufferb[0]] & CHECK_READY) && !cdrom->ready())
|
||||
{
|
||||
// pclog("Not ready\n");
|
||||
atapi_cmd_error(ide, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0);
|
||||
SCSISense.SenseKey = SENSE_NOT_READY;
|
||||
SCSISense.Asc = ASC_MEDIUM_NOT_PRESENT;
|
||||
@@ -1868,6 +2195,8 @@ static void atapicommand(int ide_board)
|
||||
return;
|
||||
}
|
||||
|
||||
// pclog("Continuing with command\n");
|
||||
|
||||
prev_status = cd_status;
|
||||
cd_status = cdrom->status();
|
||||
if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED)))
|
||||
@@ -1911,18 +2240,34 @@ static void atapicommand(int ide_board)
|
||||
idebufferb[13]=SCSISense.Ascq;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING))
|
||||
{
|
||||
idebufferb[2]=SENSE_ILLEGAL_REQUEST;
|
||||
idebufferb[12]=ASC_AUDIO_PLAY_OPERATION;
|
||||
idebufferb[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SCSISense.UnitAttention)
|
||||
{
|
||||
idebufferb[2]=SENSE_UNIT_ATTENTION;
|
||||
idebufferb[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||
idebufferb[13]=0;
|
||||
}
|
||||
}
|
||||
|
||||
idebufferb[7]=10;
|
||||
|
||||
// pclog("REQUEST SENSE start\n");
|
||||
atapi_command_ready(ide_board, 18);
|
||||
|
||||
if (idebufferb[2] == SENSE_UNIT_ATTENTION)
|
||||
{
|
||||
/* If the last remaining sense is unit attention, clear
|
||||
that condition. */
|
||||
SCSISense.UnitAttention = 0;
|
||||
}
|
||||
|
||||
/* Clear the sense stuff as per the spec. */
|
||||
atapi_sense_clear(temp_command, 0);
|
||||
break;
|
||||
@@ -2005,56 +2350,71 @@ static void atapicommand(int ide_board)
|
||||
return;
|
||||
|
||||
case GPCMD_READ_CD:
|
||||
// pclog("Read CD : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]);
|
||||
rcdmode = idebufferb[9] & 0xF8;
|
||||
if ((rcdmode != 0x10) && (rcdmode != 0xF8))
|
||||
{
|
||||
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/
|
||||
ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
|
||||
if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION)
|
||||
ide->error |= MCR_ERR;
|
||||
SCSISense.Asc = ASC_ILLEGAL_OPCODE;
|
||||
ide->packetstatus = ATAPI_STATUS_ERROR;
|
||||
idecallback[ide_board]=50*IDE_TIME;
|
||||
break;
|
||||
// pclog("Bad flags bits %02X\n",idebufferb[9]);
|
||||
// exit(-1);
|
||||
}
|
||||
/* if (idebufferb[6] || idebufferb[7] || (idebufferb[8]!=1))
|
||||
{
|
||||
pclog("More than 1 sector!\n");
|
||||
exit(-1);
|
||||
}*/
|
||||
ide->cdlen=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8];
|
||||
ide->cdpos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
|
||||
// pclog("Read at %08X %08X\n",ide.cdpos,ide.cdpos*2048);
|
||||
if (rcdmode == 0x10)
|
||||
cdrom->readsector(idebufferb,ide->cdpos);
|
||||
else
|
||||
cdrom->readsector_raw(idebufferb,ide->cdpos);
|
||||
case GPCMD_READ_CD_MSF:
|
||||
// pclog("Read CD : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]);
|
||||
if (idebufferb[0] == GPCMD_READ_CD_MSF)
|
||||
{
|
||||
ide->cdpos=MSFtoLBA(idebufferb[3],idebufferb[4],idebufferb[5]);
|
||||
ide->cdlen=MSFtoLBA(idebufferb[6],idebufferb[7],idebufferb[8]);
|
||||
|
||||
ide->cdlen -= ide->cdpos;
|
||||
ide->cdlen++;
|
||||
|
||||
cdrom_sector_ismsf = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ide->cdlen=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8];
|
||||
ide->cdpos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
|
||||
|
||||
cdrom_sector_ismsf = 0;
|
||||
}
|
||||
|
||||
cdrom_sector_type = (idebufferb[1] >> 2) & 7;
|
||||
cdrom_sector_flags = idebufferb[9] || (((uint32_t) idebufferb[10]) << 8);
|
||||
|
||||
ret = cdrom_read_data(ide, idebufferb);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/
|
||||
ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
|
||||
if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION)
|
||||
{
|
||||
ide->error |= MCR_ERR;
|
||||
}
|
||||
SCSISense.Asc = ASC_ILLEGAL_OPCODE;
|
||||
ide->packetstatus = ATAPI_STATUS_ERROR;
|
||||
idecallback[ide_board]=50*IDE_TIME;
|
||||
break;
|
||||
// pclog("Bad flags bits %02X\n",idebufferb[9]);
|
||||
// exit(-1);
|
||||
}
|
||||
|
||||
// pclog("Read at %08X %08X\n",ide.cdpos,ide.cdpos*2048);
|
||||
|
||||
#ifndef RPCEMU_IDE
|
||||
readflash=1;
|
||||
readflash=1;
|
||||
#endif
|
||||
readcdmode = (rcdmode == 0xF8);
|
||||
ide->cdpos++;
|
||||
ide->cdlen--;
|
||||
if (ide->cdlen >= 0)
|
||||
ide->packetstatus = ATAPI_STATUS_READCD;
|
||||
else
|
||||
ide->packetstatus = ATAPI_STATUS_DATA;
|
||||
ide->cylinder=(idebufferb[9] == 0x10) ? 2048 : 2352;
|
||||
ide->secount=2;
|
||||
ide->pos=0;
|
||||
idecallback[ide_board]=60*IDE_TIME;
|
||||
ide->packlen=(idebufferb[9] == 0x10) ? 2048 : 2352;
|
||||
return;
|
||||
|
||||
ide->cdpos++;
|
||||
ide->cdlen--;
|
||||
if (ide->cdlen >= 0)
|
||||
ide->packetstatus = ATAPI_STATUS_READCD;
|
||||
else
|
||||
ide->packetstatus = ATAPI_STATUS_DATA;
|
||||
ide->cylinder=cdrom_sector_size;
|
||||
ide->secount=2;
|
||||
ide->pos=0;
|
||||
idecallback[ide_board]=60*IDE_TIME;
|
||||
ide->packlen=cdrom_sector_size;
|
||||
return;
|
||||
|
||||
case GPCMD_READ_6:
|
||||
case GPCMD_READ_10:
|
||||
case GPCMD_READ_12:
|
||||
// pclog("Read 10 : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]);
|
||||
|
||||
readcdmode = 0;
|
||||
cdrom_sector_ismsf = 0;
|
||||
|
||||
if (idebufferb[0] == GPCMD_READ_6)
|
||||
{
|
||||
@@ -2071,7 +2431,8 @@ static void atapicommand(int ide_board)
|
||||
ide->cdlen=(((uint32_t) idebufferb[6])<<24)|(((uint32_t) idebufferb[7])<<16)|(((uint32_t) idebufferb[8])<<8)|((uint32_t) idebufferb[9]);
|
||||
ide->cdpos=(((uint32_t) idebufferb[2])<<24)|(((uint32_t) idebufferb[3])<<16)|(((uint32_t) idebufferb[4])<<8)|((uint32_t) idebufferb[5]);
|
||||
}
|
||||
if (!ide->cdlen)
|
||||
|
||||
if (!ide->cdlen)
|
||||
{
|
||||
// pclog("All done - callback set\n");
|
||||
ide->packetstatus = ATAPI_STATUS_COMPLETE;
|
||||
@@ -2079,7 +2440,11 @@ static void atapicommand(int ide_board)
|
||||
break;
|
||||
}
|
||||
|
||||
cdrom->readsector(idebufferb,ide->cdpos);
|
||||
cdrom_sector_type = 0;
|
||||
cdrom_sector_flags = 0x10;
|
||||
|
||||
ret = cdrom_read_data(ide, idebufferb);
|
||||
|
||||
#ifndef RPCEMU_IDE
|
||||
readflash=1;
|
||||
#endif
|
||||
@@ -2716,6 +3081,8 @@ static void callnonreadcd(IDE *ide) /* Callabck for non-Read CD commands */
|
||||
|
||||
static void callreadcd(IDE *ide)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ide_irq_lower(ide);
|
||||
if (ide->cdlen<=0)
|
||||
{
|
||||
@@ -2726,22 +3093,21 @@ static void callreadcd(IDE *ide)
|
||||
}
|
||||
// pclog("Continue readcd! %i blocks left\n",ide->cdlen);
|
||||
ide->atastat = BUSY_STAT;
|
||||
|
||||
if (readcdmode)
|
||||
cdrom->readsector_raw((uint8_t *) ide->buffer, ide->cdpos);
|
||||
else
|
||||
cdrom->readsector((uint8_t *) ide->buffer, ide->cdpos);
|
||||
|
||||
ret = cdrom_read_data(ide, (uint8_t *) ide->buffer);
|
||||
|
||||
#ifndef RPCEMU_IDE
|
||||
readflash=1;
|
||||
#endif
|
||||
|
||||
ide->cdpos++;
|
||||
ide->cdlen--;
|
||||
ide->packetstatus = ATAPI_STATUS_READCD;
|
||||
ide->cylinder=readcdmode ? 2352 : 2048;
|
||||
ide->cylinder=cdrom_sector_size;
|
||||
ide->secount=2;
|
||||
ide->pos=0;
|
||||
idecallback[ide->board]=60*IDE_TIME;
|
||||
ide->packlen=readcdmode ? 2352 : 2048;
|
||||
ide->packlen=cdrom_sector_size;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -33,7 +33,9 @@
|
||||
#define GPCMD_PLAY_AUDIO_12 0xa5
|
||||
#define GPCMD_READ_12 0xa8
|
||||
#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */
|
||||
#define GPCMD_READ_CD_MSF 0xb9
|
||||
#define GPCMD_SET_SPEED 0xbb
|
||||
#define GPCMD_PLAY_CD 0xbc
|
||||
#define GPCMD_MECHANISM_STATUS 0xbd
|
||||
#define GPCMD_READ_CD 0xbe
|
||||
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */
|
||||
@@ -166,6 +168,7 @@ extern uint8_t scsi_cdrom_id;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t UnitAttention;
|
||||
uint8_t SenseKey;
|
||||
uint8_t Asc;
|
||||
uint8_t Ascq;
|
||||
|
@@ -25,13 +25,17 @@ uint8_t SCSICommandTable[0x100] =
|
||||
[GPCMD_INQUIRY] = ALLOW_UA,
|
||||
[GPCMD_MODE_SELECT_6] = 0,
|
||||
[GPCMD_MODE_SENSE_6] = 0,
|
||||
[GPCMD_START_STOP_UNIT] = 0,
|
||||
[GPCMD_START_STOP_UNIT] = CHECK_READY,
|
||||
[GPCMD_PREVENT_REMOVAL] = CHECK_READY,
|
||||
[GPCMD_READ_CDROM_CAPACITY] = CHECK_READY,
|
||||
[GPCMD_READ_10] = CHECK_READY,
|
||||
[GPCMD_SEEK] = CHECK_READY | NONDATA,
|
||||
[GPCMD_READ_SUBCHANNEL] = CHECK_READY,
|
||||
[GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY | ALLOW_UA, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS */
|
||||
[GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY | ALLOW_UA, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS
|
||||
NOTE: The ATAPI reference says otherwise, but I think this is a question of
|
||||
interpreting things right - the UNIT ATTENTION condition we have here
|
||||
is a tradition from not ready to ready, by definition the drive
|
||||
eventually becomes ready, make the condition go away. */
|
||||
[GPCMD_READ_HEADER] = CHECK_READY,
|
||||
[GPCMD_PLAY_AUDIO_10] = CHECK_READY,
|
||||
[GPCMD_GET_CONFIGURATION] = ALLOW_UA,
|
||||
@@ -45,7 +49,9 @@ uint8_t SCSICommandTable[0x100] =
|
||||
[GPCMD_PLAY_AUDIO_12] = CHECK_READY,
|
||||
[GPCMD_READ_12] = CHECK_READY,
|
||||
[GPCMD_READ_DVD_STRUCTURE] = CHECK_READY,
|
||||
[GPCMD_READ_CD_MSF] = CHECK_READY,
|
||||
[GPCMD_SET_SPEED] = 0,
|
||||
[GPCMD_PLAY_CD] = CHECK_READY,
|
||||
[GPCMD_MECHANISM_STATUS] = 0,
|
||||
[GPCMD_READ_CD] = CHECK_READY,
|
||||
[GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY
|
||||
@@ -359,9 +365,12 @@ uint32_t SCSICDROMEventStatus(uint8_t *buffer)
|
||||
|
||||
void SCSICDROM_Insert()
|
||||
{
|
||||
SCSISense.UnitAttention=1;
|
||||
#if 0
|
||||
SCSISense.SenseKey=SENSE_UNIT_ATTENTION;
|
||||
SCSISense.Asc=ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||
SCSISense.Ascq=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int cd_status = CD_STATUS_EMPTY;
|
||||
@@ -557,7 +566,7 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb)
|
||||
if (RCdMode == 0x10)
|
||||
cdrom->readsector(Scsi->SegmentData.Address,Scsi->SectorLba);
|
||||
else
|
||||
cdrom->readsector_raw(Scsi->SegmentData.Address,Scsi->SectorLba);
|
||||
cdrom->readsector_raw(Scsi->SegmentData.Address,Scsi->SectorLba, 0);
|
||||
|
||||
readcdmode = (RCdMode == 0xF8);
|
||||
|
||||
@@ -1181,7 +1190,7 @@ void SCSICDROM_CallRead(SCSI *Scsi, uint8_t Id)
|
||||
pclog("Continue Read command! %i blocks left\n", Scsi->SectorLen);
|
||||
|
||||
if (readcdmode)
|
||||
cdrom->readsector_raw(Scsi->SegmentData.Address, Scsi->SectorLba);
|
||||
cdrom->readsector_raw(Scsi->SegmentData.Address, Scsi->SectorLba, 0);
|
||||
else
|
||||
cdrom->readsector(Scsi->SegmentData.Address, Scsi->SectorLba);
|
||||
|
||||
|
Reference in New Issue
Block a user