Massive IDE clean-ups, and finally implemented ATAPI hard disks.

This commit is contained in:
OBattler
2023-10-28 22:00:23 +02:00
parent 26d9fa4daa
commit b474e3d056
19 changed files with 2005 additions and 1702 deletions

View File

@@ -36,6 +36,8 @@
#include <86box/hdc_ide.h>
#include <86box/zip.h>
#define IDE_ATAPI_IS_EARLY id->sc->pad0
zip_drive_t zip_drives[ZIP_NUM];
/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */
@@ -588,11 +590,11 @@ zip_init(zip_t *dev)
dev->drv->bus_mode |= 1;
zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode);
if (dev->drv->bus_type < ZIP_BUS_SCSI) {
dev->phase = 1;
dev->request_length = 0xEB14;
dev->tf->phase = 1;
dev->tf->request_length = 0xEB14;
}
dev->status = READY_STAT | DSC_STAT;
dev->pos = 0;
dev->tf->status = READY_STAT | DSC_STAT;
dev->tf->pos = 0;
dev->packet_status = PHASE_NONE;
zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0;
}
@@ -622,36 +624,9 @@ zip_current_mode(zip_t *dev)
if (!zip_supports_pio(dev) && zip_supports_dma(dev))
return 2;
if (zip_supports_pio(dev) && zip_supports_dma(dev)) {
zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO");
return (dev->features & 1) ? 2 : 1;
}
return 0;
}
/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */
int
zip_atapi_phase_to_scsi(zip_t *dev)
{
if (dev->status & 8) {
switch (dev->phase & 3) {
case 0:
return 0;
case 1:
return 2;
case 2:
return 1;
case 3:
return 7;
default:
break;
}
} else {
if ((dev->phase & 3) == 3)
return 3;
else
return 4;
zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id,
(dev->tf->features & 1) ? "DMA" : "PIO");
return (dev->tf->features & 1) ? 2 : 1;
}
return 0;
@@ -791,7 +766,7 @@ zip_update_request_length(zip_t *dev, int len, int block_len)
int bt;
int min_len = 0;
dev->max_transfer_len = dev->request_length;
dev->max_transfer_len = dev->tf->request_length;
/* For media access commands, make sure the requested DRQ length matches the block length. */
switch (dev->current_cdb[0]) {
@@ -835,9 +810,9 @@ zip_update_request_length(zip_t *dev, int len, int block_len)
dev->max_transfer_len = 65534;
if ((len <= dev->max_transfer_len) && (len >= min_len))
dev->request_length = dev->max_transfer_len = len;
dev->tf->request_length = dev->max_transfer_len = len;
else if (len > dev->max_transfer_len)
dev->request_length = dev->max_transfer_len;
dev->tf->request_length = dev->max_transfer_len;
return;
}
@@ -868,9 +843,9 @@ zip_command_common(zip_t *dev)
double bytes_per_second;
double period;
dev->status = BUSY_STAT;
dev->phase = 1;
dev->pos = 0;
dev->tf->status = BUSY_STAT;
dev->tf->phase = 1;
dev->tf->pos = 0;
if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0.0;
else {
@@ -932,8 +907,8 @@ static void
zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction)
{
zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n",
dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length);
dev->pos = 0;
dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length);
dev->tf->pos = 0;
if (alloc_len >= 0) {
if (alloc_len < len)
len = alloc_len;
@@ -962,7 +937,8 @@ zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int d
}
zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n",
dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase);
dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos,
dev->tf->phase);
}
static void
@@ -987,12 +963,12 @@ static void
zip_cmd_error(zip_t *dev)
{
zip_set_phase(dev, SCSI_PHASE_STATUS);
dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR;
dev->tf->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR;
if (dev->unit_attention)
dev->error |= MCR_ERR;
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
dev->tf->error |= MCR_ERR;
dev->tf->status = READY_STAT | ERR_STAT;
dev->tf->phase = 3;
dev->tf->pos = 0;
dev->packet_status = PHASE_ERROR;
dev->callback = 50.0 * ZIP_TIME;
zip_set_callback(dev);
@@ -1004,12 +980,12 @@ static void
zip_unit_attention(zip_t *dev)
{
zip_set_phase(dev, SCSI_PHASE_STATUS);
dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR;
dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR;
if (dev->unit_attention)
dev->error |= MCR_ERR;
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
dev->tf->error |= MCR_ERR;
dev->tf->status = READY_STAT | ERR_STAT;
dev->tf->phase = 3;
dev->tf->pos = 0;
dev->packet_status = PHASE_ERROR;
dev->callback = 50.0 * ZIP_TIME;
zip_set_callback(dev);
@@ -1097,7 +1073,7 @@ zip_invalid_field(zip_t *dev)
zip_asc = ASC_INV_FIELD_IN_CMD_PACKET;
zip_ascq = 0;
zip_cmd_error(dev);
dev->status = 0x53;
dev->tf->status = 0x53;
}
static void
@@ -1107,7 +1083,7 @@ zip_invalid_field_pl(zip_t *dev)
zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST;
zip_ascq = 0;
zip_cmd_error(dev);
dev->status = 0x53;
dev->tf->status = 0x53;
}
static void
@@ -1184,7 +1160,8 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb)
int ready = 0;
if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) {
zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7));
zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id,
((dev->tf->request_length >> 5) & 7));
zip_invalid_lun(dev);
return 0;
}
@@ -1274,14 +1251,14 @@ zip_reset(scsi_common_t *sc)
zip_t *dev = (zip_t *) sc;
zip_rezero(dev);
dev->status = 0;
dev->callback = 0.0;
dev->tf->status = 0;
dev->callback = 0.0;
zip_set_callback(dev);
dev->phase = 1;
dev->request_length = 0xEB14;
dev->packet_status = PHASE_NONE;
dev->unit_attention = 0;
dev->cur_lun = SCSI_LUN_USE_CDB;
dev->tf->phase = 1;
dev->tf->request_length = 0xEB14;
dev->packet_status = PHASE_NONE;
dev->unit_attention = 0;
dev->cur_lun = SCSI_LUN_USE_CDB;
}
static void
@@ -1373,11 +1350,11 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f;
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length;
dev->status &= ~ERR_STAT;
BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length;
dev->tf->status &= ~ERR_STAT;
} else {
BufLen = &blen;
dev->error = 0;
BufLen = &blen;
dev->tf->error = 0;
}
dev->packet_len = 0;
@@ -1388,7 +1365,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
if (cdb[0] != 0) {
zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n",
dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention);
zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length);
zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->tf->request_length);
zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id,
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
@@ -1465,8 +1442,9 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
break;
case GPCMD_REQUEST_SENSE:
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
should forget about the not ready, and report unit attention straight away. */
/* If there's a unit attention condition and there's a buffered not
ready, a standalone REQUEST SENSE should forget about the not
ready, and report unit attention straight away. */
zip_set_phase(dev, SCSI_PHASE_DATA_IN);
max_len = cdb[4];
@@ -1507,7 +1485,14 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
switch (cdb[0]) {
case GPCMD_READ_6:
dev->sector_len = cdb[4];
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
/*
For READ (6) and WRITE (6), a length of 0 indicates a
transfer of 256 sectors.
*/
if (dev->sector_len == 0)
dev->sector_len = 256;
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) |
(((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos);
break;
case GPCMD_READ_10:
@@ -1516,14 +1501,21 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos);
break;
case GPCMD_READ_12:
dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]);
dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) |
(((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]);
dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) |
(((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
break;
default:
break;
}
if (dev->sector_pos >= dev->drv->medium_size) {
zip_lba_out_of_range(dev);
return;
}
if (!dev->sector_len) {
zip_set_phase(dev, SCSI_PHASE_STATUS);
/* zip_log("ZIP %i: All done - callback set\n", dev->id); */
@@ -1534,9 +1526,13 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
}
max_len = dev->sector_len;
dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT
matter anyway, this step should be identical and only the way the read dat is
transferred to the host should be different. */
/*
If we're reading all blocks in one go for DMA, why not also for
PIO, it should NOT matter anyway, this step should be identical
and only the way the read dat is transferred to the host should
be different.
*/
dev->requested_blocks = max_len;
dev->packet_len = max_len * alloc_length;
zip_buf_alloc(dev, dev->packet_len);
@@ -1558,10 +1554,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0);
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE);
return;
case GPCMD_VERIFY_6:
@@ -1590,9 +1583,14 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
case GPCMD_VERIFY_6:
case GPCMD_WRITE_6:
dev->sector_len = cdb[4];
/*
For READ (6) and WRITE (6), a length of 0 indicates a
transfer of 256 sectors.
*/
if (dev->sector_len == 0)
dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
dev->sector_len = 256;
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) |
(((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
break;
case GPCMD_VERIFY_10:
case GPCMD_WRITE_10:
@@ -1604,17 +1602,17 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
case GPCMD_VERIFY_12:
case GPCMD_WRITE_12:
case GPCMD_WRITE_AND_VERIFY_12:
dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]);
dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) |
(((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]);
dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) |
(((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
break;
default:
break;
}
if ((dev->sector_pos >= dev->drv->medium_size) /* ||
((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/
) {
if (dev->sector_pos >= dev->drv->medium_size) {
zip_lba_out_of_range(dev);
return;
}
@@ -1629,9 +1627,13 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
}
max_len = dev->sector_len;
dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT
matter anyway, this step should be identical and only the way the read dat is
transferred to the host should be different. */
/*
If we're writing all blocks in one go for DMA, why not also for
PIO, it should NOT matter anyway, this step should be identical
and only the way the read dat is transferred to the host should
be different.
*/
dev->requested_blocks = max_len;
dev->packet_len = max_len * alloc_length;
zip_buf_alloc(dev, dev->packet_len);
@@ -1643,10 +1645,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1);
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE);
return;
case GPCMD_WRITE_SAME_10:
@@ -1665,9 +1664,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
dev->sector_len = (cdb[7] << 8) | cdb[8];
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
if ((dev->sector_pos >= dev->drv->medium_size) /* ||
((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/
) {
if (dev->sector_pos >= dev->drv->medium_size) {
zip_lba_out_of_range(dev);
return;
}
@@ -1693,10 +1690,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb)
zip_data_command_finish(dev, 512, 512, alloc_length, 1);
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE);
return;
case GPCMD_MODE_SENSE_6:
@@ -2034,10 +2028,10 @@ atapi_out:
}
#if 0
zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length);
zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length);
#endif
if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS)
if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR))
zip_buf_free(dev);
}
@@ -2321,6 +2315,9 @@ zip_drive_reset(int c)
dev->cur_lun = SCSI_LUN_USE_CDB;
if (zip_drives[c].bus_type == ZIP_BUS_SCSI) {
if (!dev->tf)
dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t));
/* SCSI ZIP, attach to the SCSI bus. */
sd = &scsi_devices[scsi_bus][scsi_id];
@@ -2339,6 +2336,8 @@ zip_drive_reset(int c)
that's not attached to anything. */
if (id) {
id->sc = (scsi_common_t *) dev;
dev->tf = id->tf;
IDE_ATAPI_IS_EARLY = 0;
id->get_max = zip_get_max;
id->get_timings = zip_get_timings;
id->identify = zip_identify;
@@ -2425,6 +2424,9 @@ zip_close(void)
if (dev) {
zip_disk_unload(dev);
if (dev->tf)
free(dev->tf);
free(dev);
zip_drives[c].priv = NULL;
}