IDE dword reads and writes reverted to original operation, fixes the last hard disk problems;

ATAPI CD-ROM word reads no longer incorrectly discard the upper 16 bits, fixes the CD-ROM problems;
Significantly rewrote parts of the AHA-154x and BusLogic emulation, NT 3.1 RTM and MS-DOS drivers now works correctly;
The function in cdrom.c to read data blocks from the disc now correctly advances the position of the sector to read in non-passthrough mode, fixes multiblock reads from directly mounted ISO's;
Both ATAPI and SCSI now always check for Unit Attention and Not Ready on command execution.
This commit is contained in:
OBattler
2017-01-20 23:53:19 +01:00
parent b613873ff3
commit 3f612ab71a
9 changed files with 551 additions and 376 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -779,6 +779,7 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
int transferred_blocks = 0;
int temp_len = 0;
int chunk = 0;
if (cdb[0] == 0x43)
{
@@ -791,13 +792,14 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
memcpy(cdb, in_cdb, 12);
temp_block_length = ioctl_get_block_length(id, cdb, cdrom[id].requested_blocks, 0);
*len = 0;
if (temp_block_length != -1)
{
if (temp_block_length > 65534)
{
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is bigger than 65534, splitting the transfer...\n", id, temp_block_length);
block_length = temp_block_length / cdrom[id].requested_blocks;
blocks_at_once = 32768 / block_length;
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is bigger than 65534, splitting the transfer into chunks of %i blocks...\n", id, temp_block_length, blocks_at_once);
buffer_pos = 0;
temp_pos = cdrom[id].sector_pos;
@@ -806,12 +808,15 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
temp_len = 0;
split_block_read_iterate:
if (temp_requested_blocks < blocks_at_once)
chunk = (cdrom[id].requested_blocks - transferred_blocks);
if (chunk < blocks_at_once)
{
cdrom_ioctl[id].actual_requested_blocks = temp_requested_blocks;
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): The remaining chunk (%i blocks) is less than a complete split block\n", id, chunk);
cdrom_ioctl[id].actual_requested_blocks = chunk;
}
else
{
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): The remaining chunk (%i blocks) is more or equal than a complete split block\n", id, chunk);
cdrom_ioctl[id].actual_requested_blocks = blocks_at_once;
}
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring %i blocks...\n", id, cdrom_ioctl[id].actual_requested_blocks);
@@ -819,8 +824,9 @@ split_block_read_iterate:
ret = SCSICommand(id, cdb, buf + buffer_pos, &temp_len, 0);
*len += temp_len;
transferred_blocks += cdrom_ioctl[id].actual_requested_blocks;
if (ret && (transferred_blocks >= cdrom[id].requested_blocks))
if (ret && (transferred_blocks < cdrom[id].requested_blocks))
{
/* Return value was successful and there are still more blocks left to transfer. */
temp_pos += cdrom_ioctl[id].actual_requested_blocks;
buffer_pos += (cdrom_ioctl[id].actual_requested_blocks * block_length);
goto split_block_read_iterate;

View File

@@ -3,6 +3,8 @@
*/
/*ISO CD-ROM support*/
#include <stdarg.h>
#include "ibm.h"
#include "cdrom.h"
#include "cdrom-iso.h"
@@ -10,12 +12,12 @@
static CDROM iso_cdrom;
int cdrom_iso_do_log = 1;
int cdrom_iso_do_log = 0;
void cdrom_iso_log(const char *format, ...)
{
#ifdef ENABLE_CDROM_ISO_LOG
if (cdrom_do_log)
if (cdrom_iso_do_log)
{
va_list ap;
va_start(ap, format);
@@ -273,12 +275,14 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
if (cdrom_sector_flags & 0x80) /* Sync */
{
cdrom_iso_log("CD-ROM %i: Sync\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12);
cdrom_sector_size += 12;
temp_b += 12;
}
if (cdrom_sector_flags & 0x20) /* Header */
{
cdrom_iso_log("CD-ROM %i: Header\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4);
cdrom_sector_size += 4;
temp_b += 4;
@@ -289,6 +293,7 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
{
if (!(cdrom_sector_flags & 0x10)) /* No user data */
{
cdrom_iso_log("CD-ROM %i: Sub-header\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8);
cdrom_sector_size += 8;
temp_b += 8;
@@ -296,12 +301,14 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
}
if (cdrom_sector_flags & 0x10) /* User data */
{
cdrom_iso_log("CD-ROM %i: User data\n", id);
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 */
{
cdrom_iso_log("CD-ROM %i: EDC/ECC\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288);
cdrom_sector_size += 288;
temp_b += 288;
@@ -312,33 +319,36 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
if ((cdrom_sector_flags & 0x06) == 0x02)
{
/* Add error flags. */
cdrom_iso_log("CD-ROM %i: Error flags\n", id);
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. */
cdrom_iso_log("CD-ROM %i: Full error flags\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296);
cdrom_sector_size += 296;
}
if ((cdrom_sector_flags & 0x700) == 0x100)
{
cdrom_iso_log("CD-ROM %i: Raw subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96);
cdrom_sector_size += 96;
}
else if ((cdrom_sector_flags & 0x700) == 0x200)
{
cdrom_iso_log("CD-ROM %i: Q subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16);
cdrom_sector_size += 16;
}
else if ((cdrom_sector_flags & 0x700) == 0x400)
{
cdrom_iso_log("CD-ROM %i: R/W subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96);
cdrom_sector_size += 96;
}
memcpy(buffer, b, cdrom_sector_size);
*len = cdrom_sector_size;

View File

@@ -330,12 +330,10 @@ void cdrom_init(int id, int cdb_len_setting, int bus_type)
if (!cdrom_drives[id].bus_type)
{
cdrom_set_signature(id);
cdrom_drives[id].check_on_execution = 1;
cdrom_drives[id].max_blocks_at_once = 1;
}
else
{
cdrom_drives[id].check_on_execution = scsi_model ? 0 : 1;
cdrom_drives[id].max_blocks_at_once = 85;
}
cdrom[id].status = READY_STAT | DSC_STAT;
@@ -881,12 +879,12 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al
{
if (cdrom_current_mode(id) == 2)
{
if (cdrom_drives[id].bus_type)
{
SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len;
}
if (direction == 0)
{
if (cdrom_drives[id].bus_type)
{
SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len;
}
cdrom_command_read_dma(id);
}
else
@@ -1121,6 +1119,8 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
int i = 0;
int temp_len = 0;
int last_valid_data_pos = 0;
if (cdrom_drives[id].handler->pass_through)
{
cdsize = cdrom_drives[id].handler->size(id);
@@ -1156,7 +1156,9 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
for (i = 0; i < cdrom[id].requested_blocks; i++)
{
ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + cdrom[id].data_pos, cdrom[id].sector_pos, msf, type, flags, &temp_len);
ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + cdrom[id].data_pos, cdrom[id].sector_pos + i, msf, type, flags, &temp_len);
last_valid_data_pos = cdrom[id].data_pos;
cdrom[id].data_pos += temp_len;
cdrom[id].old_len += temp_len;
@@ -1170,7 +1172,7 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
}
}
cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]);
cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[last_valid_data_pos + 0], cdbufferb[last_valid_data_pos + 1], cdbufferb[last_valid_data_pos + 2], cdbufferb[last_valid_data_pos + 3], cdbufferb[last_valid_data_pos + 4], cdbufferb[last_valid_data_pos + 5], cdbufferb[last_valid_data_pos + 6], cdbufferb[last_valid_data_pos + 7]);
}
return 1;
@@ -1616,12 +1618,9 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom[id].sector_len = 0;
/* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */
if (cdrom_drives[id].check_on_execution)
if (cdrom_pre_execution_check(id, cdb) == 0)
{
if (cdrom_pre_execution_check(id, cdb) == 0)
{
return;
}
return;
}
cdrom[id].prev_status = cdrom[id].cd_status;
@@ -2645,7 +2644,7 @@ int cdrom_mode_select_return(uint8_t id, int ret)
}
}
int cdrom_phase_callback(uint8_t id);
void cdrom_phase_callback(uint8_t id);
int cdrom_read_from_ide_dma(uint8_t channel)
{
@@ -2799,58 +2798,72 @@ int cdrom_write_to_dma(uint8_t id)
return 1;
}
void cdrom_irq_raise(uint8_t id)
{
if (!cdrom_drives[id].bus_type)
{
ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel]));
}
}
/* If the result is 1, issue an IRQ, otherwise not. */
int cdrom_phase_callback(uint8_t id)
void cdrom_phase_callback(uint8_t id)
{
switch(cdrom[id].packet_status)
{
case CDROM_PHASE_IDLE:
// cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id);
cdrom[id].pos=0;
cdrom[id].phase = 1;
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
return 0;
return;
case CDROM_PHASE_COMMAND:
// cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id);
cdrom[id].status = BUSY_STAT | (cdrom[id].status &ERR_STAT);
memcpy(cdrom[id].atapi_cdb, (uint8_t *) cdrom[id].buffer, cdrom[id].cdb_len);
cdrom_command(id, cdrom[id].atapi_cdb);
return 0;
return;
case CDROM_PHASE_COMPLETE:
// cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id);
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
cdrom[id].packet_status = 0xFF;
return 1;
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_OUT:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id);
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
cdrom[id].phase = 0;
return 1;
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_OUT_DMA:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id);
cdrom_read_from_dma(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
return 1;
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_IN:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id);
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
cdrom[id].phase = 2;
return 1;
cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_IN_DMA:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id);
cdrom_write_to_dma(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
return 1;
cdrom_irq_raise(id);
return;
case CDROM_PHASE_ERROR:
// cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id);
cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id);
cdrom[id].status = READY_STAT | ERR_STAT;
cdrom[id].phase = 3;
return 1;
cdrom_irq_raise(id);
return;
}
}
@@ -2957,7 +2970,7 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
cdrom[id].pos++;
break;
case 2:
cdbufferw[cdrom[id].pos >> 1] = val & 0xff;
cdbufferw[cdrom[id].pos >> 1] = val & 0xffff;
cdrom[id].pos += 2;
break;
case 4:

View File

@@ -129,9 +129,6 @@ typedef struct __attribute__((__packed__))
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t check_on_execution; /* 0 = Not Ready/Unit Attention checkeck is performed on the controller's side before command execution;
1 = Not Ready/Unit Attention checkeck is performed on command execution. */
uint8_t ide_channel;
uint8_t scsi_device_id;
@@ -190,7 +187,7 @@ void build_scsi_cdrom_map();
int cdrom_CDROM_PHASE_to_scsi(uint8_t id);
int cdrom_atapi_phase_to_scsi(uint8_t id);
void cdrom_command(uint8_t id, uint8_t *cdb);
int cdrom_phase_callback(uint8_t id);
void cdrom_phase_callback(uint8_t id);
uint32_t cdrom_read(uint8_t channel, int length);
void cdrom_write(uint8_t channel, uint32_t val, int length);
int cdrom_lba_to_msf_accurate(int lba);

View File

@@ -202,7 +202,7 @@ int image_is_hdi(const char *s)
int ide_enable[4] = { 1, 1, 0, 0 };
int ide_irq[4] = { 14, 15, 10, 11 };
static inline void ide_irq_raise(IDE *ide)
void ide_irq_raise(IDE *ide)
{
if ((ide->board > 3) || ide->irqstat)
{
@@ -344,7 +344,7 @@ static void ide_identify(IDE *ide)
h = hdc[cur_ide[ide->board]].hpc; /* Heads */
s = hdc[cur_ide[ide->board]].spt; /* Sectors */
ide->buffer[0] = 0x40; /* Fixed disk */
// ide->buffer[0] = 0x40; /* Fixed disk */
ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */
ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */
ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */
@@ -403,10 +403,11 @@ 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), device_identify, 40); /* Model */
ide->buffer[48] = 1; /*Dword transfers supported*/
ide->buffer[49] = 0x200; /* LBA supported */
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
ide->buffer[73] = 6;
ide->buffer[73] = 9;
ide->buffer[74] = 9;
ide->buffer[80] = 0x10; /*ATA/ATAPI-4 supported*/
if ((ide->board < 2) && (cdrom_drives[cdrom_id].bus_mode & 2))
@@ -736,7 +737,7 @@ void resetide(void)
if (ide_drives[d].type != IDE_NONE)
{
ide_drives[d].dma_identify_data[0] = 7;
ide_drives[d].dma_identify_data[1] = 7 | (1 << 15);
ide_drives[d].dma_identify_data[1] = 7 | (1 << 10);
ide_drives[d].dma_identify_data[2] = 0x3f;
}
@@ -835,7 +836,9 @@ void writeidew(int ide_board, uint16_t val)
void writeidel(int ide_board, uint32_t val)
{
// ide_log("WriteIDEl %08X\n", val);
ide_write_data(ide_board, val, 4);
// ide_write_data(ide_board, val, 4);
writeidew(ide_board, val);
writeidew(ide_board, val >> 16);
}
void writeide(int ide_board, uint16_t addr, uint8_t val)
@@ -1349,7 +1352,7 @@ uint32_t ide_read_data(int ide_board, int length)
ide->pos += 2;
break;
case 4:
temp = idebufferb[ide->pos >> 2];
temp = idebufferl[ide->pos >> 2];
ide->pos += 4;
break;
default:
@@ -1559,17 +1562,21 @@ int all_blocks_total = 0;
uint16_t readidew(int ide_board)
{
uint16_t temp;
temp = ide_read_data(ide_board, 2);
return temp;
return ide_read_data(ide_board, 2);
}
/* uint32_t readidel(int ide_board)
{
// ide_log("Read IDEl %i\n", ide_board);
return ide_read_data(ide_board, 4);
} */
uint32_t readidel(int ide_board)
{
uint16_t temp;
// ide_log("Read IDEl %i\n", ide_board);
temp = ide_read_data(ide_board, 4);
return temp;
// pclog("Read IDEl %i\n", ide_board);
temp = readidew(ide_board);
return temp | (readidew(ide_board) << 16);
}
int times30=0;
@@ -2015,10 +2022,7 @@ void callbackide(int ide_board)
goto abort_cmd;
}
if (cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]))
{
ide_irq_raise(ide);
}
cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]);
idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback;
ide_log("IDE callback now: %i\n", idecallback[ide_board]);
return;

View File

@@ -62,6 +62,7 @@ extern int idecallback[4];
extern char ide_fn[IDE_NUM][512];
void ide_irq_raise(IDE *ide);
void ide_irq_lower(IDE *ide);
IDE ide_drives[IDE_NUM];

View File

@@ -16,22 +16,6 @@
uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE;
uint8_t SCSIStatus = SCSI_STATUS_OK;
int SCSICallback[16][8] = { { 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 } };
uint8_t scsi_cdrom_id = 3; /*common setting*/
//Initialization function for the SCSI layer
@@ -41,8 +25,6 @@ void SCSIReset(uint8_t id, uint8_t lun)
if (buslogic_scsi_drive_is_cdrom(id, lun))
{
SCSICallback[id][lun] = 0;
cdrom_reset(cdrom_id);
SCSIDevices[id][lun].LunType = SCSI_CDROM;
}

View File

@@ -188,7 +188,6 @@ int MediaPresent;
extern uint8_t SCSIStatus;
extern uint8_t SCSIPhase;
extern int SCSICallback[16][8];
extern uint8_t scsi_cdrom_id;
struct