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:
parent
a9ef194a3c
commit
c183af29c1
7 changed files with 98 additions and 30 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
20
src/ide.c
20
src/ide.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
4
src/pc.c
4
src/pc.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue