If a CD-ROM sector read fails when using the Windows IOCTL code, retry using SPTI. BeOS 5 now boots from CD.

This commit is contained in:
SarahW 2017-01-05 19:22:55 +00:00
commit c183af29c1
7 changed files with 98 additions and 30 deletions

View file

@ -4,8 +4,10 @@
#include <io.h>
#ifdef __MINGW64__
#include "ntddcdrm.h"
#include "ntddscsi.h"
#else
#include "ddk/ntddcdrm.h"
#include "ddk/ntddscsi.h"
#endif
#include "ibm.h"
#include "ide.h"
@ -426,21 +428,73 @@ static void ioctl_load(void)
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
}
static void ioctl_readsector(uint8_t *b, int sector)
#define IOCTL_DATA_BUFFER 8192
typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER {
SCSI_PASS_THROUGH_DIRECT spt;
ULONG Filler;
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
static int ioctl_readsector(uint8_t *b, int sector)
{
LARGE_INTEGER pos;
BOOL status;
long size;
if (!cdrom_drive) return;
int c;
if (!cdrom_drive)
return -1;
if (ioctl_cd_state == CD_PLAYING)
return;
return -1;
ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048;
ioctl_open(0);
SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
ReadFile(hIOCTL,b,2048,&size,NULL);
status = ReadFile(hIOCTL,b,2048,&size,NULL);
ioctl_close();
/*If the read failed, try again using SPTI*/
if (!status || size != 2048)
{
uint8_t cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
DWORD returned;
uint8_t data_buffer[IOCTL_DATA_BUFFER];
ioctl_open(0);
cmd[9] |= 1 << 4; // userdata
cmd[3] = (uint8_t)(sector >> 16);
cmd[4] = (uint8_t)(sector >> 8);
cmd[5] = (uint8_t)(sector >> 0);
memset(&swb, 0, sizeof (swb));
memcpy(swb.spt.Cdb, cmd, 12);
swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
swb.spt.CdbLength = 12;
swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
swb.spt.DataTransferLength = IOCTL_DATA_BUFFER;
swb.spt.DataBuffer = data_buffer;
memset(data_buffer, 0, IOCTL_DATA_BUFFER);
swb.spt.TimeOutValue = 80 * 60;
swb.spt.SenseInfoOffset = (uintptr_t)&swb.SenseBuf - (uintptr_t)&swb;//offsetof(swb, SenseBuf);
swb.spt.SenseInfoLength = 32;
if (DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT,
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&returned, NULL))
memcpy(b, data_buffer, 2048);
ioctl_close();
}
return !status;
}
static void lba_to_msf(uint8_t *buf, int lba)
@ -695,28 +749,22 @@ void ioctl_reset()
tocvalid = 1;
}
void ioctl_set_drive(char d)
{
sprintf(ioctl_path, "\\\\.\\%c:", d);
pclog("Path is %s\n", ioctl_path);
tocvalid = 0;
atapi = &ioctl_atapi;
}
int ioctl_open(char d)
{
// char s[8];
if (!ioctl_inited)
{
sprintf(ioctl_path,"\\\\.\\%c:",d);
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(ioctl_path,GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if (!hIOCTL)
{
//fatal("IOCTL");
}
atapi=&ioctl_atapi;
if (!ioctl_inited)
{
ioctl_inited=1;
CloseHandle(hIOCTL);
hIOCTL = NULL;
}
return 0;
}
@ -732,7 +780,6 @@ void ioctl_close(void)
static void ioctl_exit(void)
{
ioctl_stop();
ioctl_inited=0;
tocvalid=0;
}

View file

@ -7,5 +7,6 @@
extern int ioctl_open(char d);
extern void ioctl_reset();
extern void ioctl_close();
void ioctl_set_drive(char d);
#endif /* ! CDROM_IOCTL_H */

View file

@ -99,11 +99,13 @@ static void iso_load(void)
pclog("iso_load stub\n");
}
static void iso_readsector(uint8_t *b, int sector)
static int iso_readsector(uint8_t *b, int sector)
{
if (!cdrom_drive) return;
if (!cdrom_drive)
return -1;
fseek(iso_image,sector*2048,SEEK_SET);
fread(b,2048,1,iso_image);
return 0;
}
static void lba_to_msf(uint8_t *buf, int lba)

View file

@ -108,6 +108,7 @@
/* ATAPI Additional Sense Codes */
#define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
#define ASC_MEDIUM_NOT_PRESENT 0x3a
@ -2131,7 +2132,24 @@ static void atapicommand(int ide_board)
break;
}
atapi->readsector(idebufferb,ide->cdpos);
if (atapi->readsector(idebufferb,ide->cdpos))
{
// pclog("Read sector failed\n");
atapi_sense.sensekey = SENSE_ILLEGAL_REQUEST;
atapi_sense.asc = ASC_LBA_OUT_OF_RANGE;
atapi_sense.ascq = 0;
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/
ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
if (atapi_sense.sensekey == SENSE_UNIT_ATTENTION)
{
ide->error |= MCR_ERR;
}
atapi_sense.asc = ASC_ILLEGAL_OPCODE;
ide->packetstatus = ATAPI_STATUS_ERROR;
idecallback[ide_board]=50*IDE_TIME;
break;
}
#ifndef RPCEMU_IDE
readflash=1;
#endif

View file

@ -25,7 +25,7 @@ typedef struct ATAPI
int (*readtoc_session)(uint8_t *b, int msf, int maxlen);
int (*readtoc_raw)(uint8_t *b, int maxlen);
uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
void (*readsector)(uint8_t *b, int sector);
int (*readsector)(uint8_t *b, int sector);
void (*readsector_raw)(uint8_t *b, int sector);
void (*playaudio)(uint32_t pos, uint32_t len, int ismsf);
void (*seek)(uint32_t pos);

View file

@ -290,13 +290,13 @@ void initpc(int argc, char *argv[])
cdrom_null_open(cdrom_drive);
#else
cdrom_drive = 0;
ioctl_open(cdrom_drive);
ioctl_set_drive(cdrom_drive);
#endif
}
}
else
{
ioctl_open(cdrom_drive);
ioctl_set_drive(cdrom_drive);
}
}

View file

@ -1034,7 +1034,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
atapi->exit();
atapi_close();
ioctl_open(0);
ioctl_set_drive(0);
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
@ -1065,7 +1065,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
atapi->exit();
atapi_close();
ioctl_open(0);
ioctl_set_drive(0);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */
@ -1147,7 +1147,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
old_cdrom_drive = cdrom_drive;
atapi->exit();
atapi_close();
ioctl_open(new_cdrom_drive);
ioctl_set_drive(new_cdrom_drive);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */