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> #include <io.h>
#ifdef __MINGW64__ #ifdef __MINGW64__
#include "ntddcdrm.h" #include "ntddcdrm.h"
#include "ntddscsi.h"
#else #else
#include "ddk/ntddcdrm.h" #include "ddk/ntddcdrm.h"
#include "ddk/ntddscsi.h"
#endif #endif
#include "ibm.h" #include "ibm.h"
#include "ide.h" #include "ide.h"
@ -426,21 +428,73 @@ static void ioctl_load(void)
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); 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; LARGE_INTEGER pos;
BOOL status;
long size; long size;
if (!cdrom_drive) return; int c;
if (!cdrom_drive)
return -1;
if (ioctl_cd_state == CD_PLAYING) if (ioctl_cd_state == CD_PLAYING)
return; return -1;
ioctl_cd_state = CD_STOPPED; ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048; pos.QuadPart=sector*2048;
ioctl_open(0); ioctl_open(0);
SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN); SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
ReadFile(hIOCTL,b,2048,&size,NULL); status = ReadFile(hIOCTL,b,2048,&size,NULL);
ioctl_close(); 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) static void lba_to_msf(uint8_t *buf, int lba)
@ -695,28 +749,22 @@ void ioctl_reset()
tocvalid = 1; 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) int ioctl_open(char d)
{ {
// char s[8]; hIOCTL = CreateFile(ioctl_path,GENERIC_READ | GENERIC_WRITE,
if (!ioctl_inited) FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
{
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);
if (!hIOCTL) if (!hIOCTL)
{ {
//fatal("IOCTL"); //fatal("IOCTL");
} }
atapi=&ioctl_atapi;
if (!ioctl_inited)
{
ioctl_inited=1;
CloseHandle(hIOCTL);
hIOCTL = NULL;
}
return 0; return 0;
} }
@ -732,7 +780,6 @@ void ioctl_close(void)
static void ioctl_exit(void) static void ioctl_exit(void)
{ {
ioctl_stop(); ioctl_stop();
ioctl_inited=0;
tocvalid=0; tocvalid=0;
} }

View file

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

View file

@ -99,11 +99,13 @@ static void iso_load(void)
pclog("iso_load stub\n"); 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); fseek(iso_image,sector*2048,SEEK_SET);
fread(b,2048,1,iso_image); fread(b,2048,1,iso_image);
return 0;
} }
static void lba_to_msf(uint8_t *buf, int lba) static void lba_to_msf(uint8_t *buf, int lba)

View file

@ -108,6 +108,7 @@
/* ATAPI Additional Sense Codes */ /* ATAPI Additional Sense Codes */
#define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_ILLEGAL_OPCODE 0x20 #define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 #define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
#define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASC_MEDIUM_NOT_PRESENT 0x3a
@ -2131,7 +2132,24 @@ static void atapicommand(int ide_board)
break; 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 #ifndef RPCEMU_IDE
readflash=1; readflash=1;
#endif #endif

View file

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

View file

@ -290,13 +290,13 @@ void initpc(int argc, char *argv[])
cdrom_null_open(cdrom_drive); cdrom_null_open(cdrom_drive);
#else #else
cdrom_drive = 0; cdrom_drive = 0;
ioctl_open(cdrom_drive); ioctl_set_drive(cdrom_drive);
#endif #endif
} }
} }
else 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->exit();
atapi_close(); atapi_close();
ioctl_open(0); ioctl_set_drive(0);
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED); CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
@ -1065,7 +1065,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
} }
atapi->exit(); atapi->exit();
atapi_close(); atapi_close();
ioctl_open(0); ioctl_set_drive(0);
if (cdrom_enabled) if (cdrom_enabled)
{ {
/* Signal disc change to the emulated machine. */ /* 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; old_cdrom_drive = cdrom_drive;
atapi->exit(); atapi->exit();
atapi_close(); atapi_close();
ioctl_open(new_cdrom_drive); ioctl_set_drive(new_cdrom_drive);
if (cdrom_enabled) if (cdrom_enabled)
{ {
/* Signal disc change to the emulated machine. */ /* Signal disc change to the emulated machine. */