diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c
index 84c63d40b..e325c7597 100644
--- a/src/disk/hdc_ide.c
+++ b/src/disk/hdc_ide.c
@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
- * Version: @(#)hdc_ide.c 1.0.56 2018/10/28
+ * Version: @(#)hdc_ide.c 1.0.57 2018/10/31
*
* Authors: Sarah Walker,
* Miran Grca,
@@ -132,6 +132,7 @@ int ide_ter_enabled = 0, ide_qua_enabled = 0;
static uint16_t ide_base_main[4] = { 0x1f0, 0x170, 0x168, 0x1e8 };
static uint16_t ide_side_main[4] = { 0x3f6, 0x376, 0x36e, 0x3ee };
+static void ide_atapi_callback(ide_t *ide);
static void ide_callback(void *priv);
@@ -941,6 +942,101 @@ ide_set_callback(uint8_t board, int64_t callback)
}
+static void
+ide_atapi_command_bus(ide_t *ide)
+{
+ ide->sc->status = BUSY_STAT;
+ ide->sc->phase = 1;
+ ide->sc->pos = 0;
+ ide->sc->callback = 1LL * IDE_TIME;
+ ide_set_callback(ide->board, ide->sc->callback);
+}
+
+
+static int
+ide_atapi_dma(ide_t *ide, int out)
+{
+ int ret = 1;
+
+ ret = 0;
+
+ if (out && ide && ide_bus_master_write) {
+ ret = ide_bus_master_write(ide->board,
+ ide->sc->temp_buffer, ide->sc->packet_len,
+ ide_bus_master_priv[ide->board]);
+ } else if (!out && ide && ide_bus_master_read) {
+ ret = ide_bus_master_read(ide->board,
+ ide->sc->temp_buffer, ide->sc->packet_len,
+ ide_bus_master_priv[ide->board]);
+ }
+
+ if (ret == 0) {
+ if (ide->bus_master_error)
+ ide->bus_master_error(ide->sc);
+ } else if (ret == 1) {
+ if (out && ide->phase_data_out)
+ ret = ide->phase_data_out(ide->sc);
+ else if (!out && ide->command_stop)
+ ide->command_stop(ide->sc);
+
+ if ((ide->sc->packet_status == PHASE_COMPLETE) && !ide->sc->callback)
+ ide_atapi_callback(ide);
+ }
+
+ return ret;
+}
+
+
+static void
+ide_atapi_callback(ide_t *ide)
+{
+ int ret;
+
+ switch(ide->sc->packet_status) {
+ case PHASE_IDLE:
+ ide->sc->pos = 0;
+ ide->sc->phase = 1;
+ ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT);
+ return;
+ case PHASE_COMMAND:
+ ide->sc->status = BUSY_STAT | (ide->sc->status & ERR_STAT);
+ if (ide->packet_command) {
+ ide->packet_command(ide->sc, ide->sc->atapi_cdb);
+ if ((ide->sc->packet_status == PHASE_COMPLETE) && !ide->sc->callback)
+ ide_atapi_callback(ide);
+ }
+ return;
+ case PHASE_COMPLETE:
+ ide->sc->status = READY_STAT;
+ ide->sc->phase = 3;
+ ide->sc->packet_status = PHASE_NONE;
+ ide_irq_raise(ide);
+ return;
+ case PHASE_DATA_IN:
+ case PHASE_DATA_OUT:
+ ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT);
+ ide->sc->phase = !(ide->sc->packet_status & 0x01) << 1;
+ ide_irq_raise(ide);
+ return;
+ case PHASE_DATA_IN_DMA:
+ case PHASE_DATA_OUT_DMA:
+ ret = ide_atapi_dma(ide, ide->sc->packet_status & 0x01);
+
+ if (ret == 2)
+ ide_atapi_command_bus(ide);
+ else if ((ide->sc->packet_status == PHASE_COMPLETE) && !ide->sc->callback)
+ ide_atapi_callback(ide);
+ return;
+ case PHASE_ERROR:
+ ide->sc->status = READY_STAT | ERR_STAT;
+ ide->sc->phase = 3;
+ ide->sc->packet_status = PHASE_NONE;
+ ide_irq_raise(ide);
+ return;
+ }
+}
+
+
/* This is the general ATAPI PIO request function. */
static void
ide_atapi_pio_request(ide_t *ide, uint8_t out)
@@ -957,8 +1053,11 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
dev->pos = dev->request_pos = 0;
if (out && ide->phase_data_out)
ide->phase_data_out(dev);
- else if (ide->command_stop)
+ else if (!out && ide->command_stop)
ide->command_stop(dev);
+
+ if ((ide->sc->packet_status == PHASE_COMPLETE) && !ide->sc->callback)
+ ide_atapi_callback(ide);
} else {
ide_log("%i bytes %s, %i bytes are still left\n", dev->pos,
out ? "written" : "read", dev->packet_len - dev->pos);
@@ -970,12 +1069,11 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
dev->max_transfer_len);
- dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN;
+ dev->packet_status = PHASE_DATA_IN | out;
dev->status = BSY_STAT;
dev->phase = 1;
- if (ide->packet_callback)
- ide->packet_callback(dev);
+ ide_atapi_callback(ide);
dev->callback = 0LL;
ide_set_callback(ide->board >> 1, dev->callback);
@@ -1090,8 +1188,7 @@ ide_atapi_packet_write(ide_t *ide, uint32_t val, int length)
dev->status = BSY_STAT;
dev->packet_status = PHASE_COMMAND;
timer_process();
- if (ide->packet_callback)
- ide->packet_callback(dev);
+ ide_atapi_callback(ide);
timer_update_outstanding();
}
return;
@@ -2298,10 +2395,10 @@ ide_callback(void *priv)
return;
case WIN_PACKETCMD: /* ATAPI Packet */
- if (!ide_drive_is_atapi(ide) || !ide->packet_callback)
+ if (!ide_drive_is_atapi(ide))
goto abort_cmd;
- ide->packet_callback(ide->sc);
+ ide_atapi_callback(ide);
return;
case 0xFF:
diff --git a/src/disk/hdc_ide.h b/src/disk/hdc_ide.h
index e9eddda90..34a6a730e 100644
--- a/src/disk/hdc_ide.h
+++ b/src/disk/hdc_ide.h
@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
- * Version: @(#)hdd_ide.h 1.0.13 2018/10/28
+ * Version: @(#)hdd_ide.h 1.0.14 2018/10/31
*
* Authors: Sarah Walker,
* Miran Grca,
@@ -57,10 +57,11 @@ typedef struct ide_s {
int (*get_timings)(int ide_has_dma, int type);
void (*identify)(struct ide_s *ide, int ide_has_dma);
void (*stop)(scsi_common_t *sc);
- void (*packet_callback)(scsi_common_t *sc);
+ void (*packet_command)(scsi_common_t *sc, uint8_t *cdb);
void (*device_reset)(scsi_common_t *sc);
uint8_t (*phase_data_out)(scsi_common_t *sc);
void (*command_stop)(scsi_common_t *sc);
+ void (*bus_master_error)(scsi_common_t *sc);
} ide_t;
#endif
diff --git a/src/disk/zip.c b/src/disk/zip.c
index d8c45740c..f6701b71b 100644
--- a/src/disk/zip.c
+++ b/src/disk/zip.c
@@ -9,7 +9,7 @@
* Implementation of the Iomega ZIP drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
- * Version: @(#)zip.c 1.0.35 2018/10/30
+ * Version: @(#)zip.c 1.0.36 2018/10/31
*
* Author: Miran Grca,
*
@@ -437,8 +437,6 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_changeable =
static void zip_command_complete(zip_t *dev);
static void zip_init(zip_t *dev);
-static void zip_callback(scsi_common_t *sc);
-
#ifdef ENABLE_ZIP_LOG
int zip_do_log = ENABLE_ZIP_LOG;
@@ -604,7 +602,7 @@ zip_init(zip_t *dev)
}
dev->status = READY_STAT | DSC_STAT;
dev->pos = 0;
- dev->packet_status = 0xff;
+ dev->packet_status = PHASE_NONE;
zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0;
}
@@ -855,17 +853,6 @@ zip_update_request_length(zip_t *dev, int len, int block_len)
}
-static void
-zip_command_bus(zip_t *dev)
-{
- dev->status = BUSY_STAT;
- dev->phase = 1;
- dev->pos = 0;
- dev->callback = 1LL * ZIP_TIME;
- zip_set_callback(dev);
-}
-
-
static void
zip_command_common(zip_t *dev)
{
@@ -875,10 +862,9 @@ zip_command_common(zip_t *dev)
dev->status = BUSY_STAT;
dev->phase = 1;
dev->pos = 0;
- if (dev->packet_status == PHASE_COMPLETE) {
- zip_callback((scsi_common_t *) dev);
+ if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0LL;
- } else {
+ else {
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
dev->callback = -1LL; /* Speed depends on SCSI controller */
return;
@@ -1011,7 +997,7 @@ zip_cmd_error(zip_t *dev)
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
- dev->packet_status = 0x80;
+ dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * ZIP_TIME;
zip_set_callback(dev);
zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq);
@@ -1028,7 +1014,7 @@ zip_unit_attention(zip_t *dev)
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
- dev->packet_status = 0x80;
+ dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * ZIP_TIME;
zip_set_callback(dev);
zip_log("ZIP %i: UNIT ATTENTION\n", dev->id);
@@ -1036,8 +1022,31 @@ zip_unit_attention(zip_t *dev)
static void
-zip_bus_master_error(zip_t *dev)
+zip_buf_alloc(zip_t *dev, uint32_t len)
{
+ zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len);
+ if (!dev->buffer)
+ dev->buffer = (uint8_t *) malloc(len);
+}
+
+
+static void
+zip_buf_free(zip_t *dev)
+{
+ if (dev->buffer) {
+ zip_log("ZIP %i: Freeing buffer...\n", dev->id);
+ free(dev->buffer);
+ dev->buffer = NULL;
+ }
+}
+
+
+static void
+zip_bus_master_error(scsi_common_t *sc)
+{
+ zip_t *dev = (zip_t *) sc;
+
+ zip_buf_free(dev);
zip_sense_key = zip_asc = zip_ascq = 0;
zip_cmd_error(dev);
}
@@ -1281,7 +1290,7 @@ zip_reset(scsi_common_t *sc)
zip_set_callback(dev);
dev->phase = 1;
dev->request_length = 0xEB14;
- dev->packet_status = 0xff;
+ dev->packet_status = PHASE_NONE;
dev->unit_attention = 0;
}
@@ -1358,26 +1367,6 @@ zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len)
}
-static void
-zip_buf_alloc(zip_t *dev, uint32_t len)
-{
- zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len);
- if (!dev->buffer)
- dev->buffer = (uint8_t *) malloc(len);
-}
-
-
-static void
-zip_buf_free(zip_t *dev)
-{
- if (dev->buffer) {
- zip_log("ZIP %i: Freeing buffer...\n", dev->id);
- free(dev->buffer);
- dev->buffer = NULL;
- }
-}
-
-
static void
zip_command(scsi_common_t *sc, uint8_t *cdb)
{
@@ -2182,125 +2171,6 @@ zip_phase_data_out(scsi_common_t *sc)
}
-static void
-zip_irq_raise(scsi_common_t *sc)
-{
- zip_t *dev = (zip_t *) sc;
-
- if (dev->drv && (dev->drv->bus_type < ZIP_BUS_SCSI))
- ide_irq_raise(ide_drives[dev->drv->ide_channel]);
-}
-
-
-static int
-zip_dma(zip_t *dev, int out)
-{
- int ret = 1;
-
- if (dev->drv->bus_type == ZIP_BUS_ATAPI) {
- ret = 0;
-
- if (out && dev && ide_bus_master_write) {
- ret = ide_bus_master_write(dev->drv->ide_channel >> 1,
- dev->buffer, dev->packet_len,
- ide_bus_master_priv[dev->drv->ide_channel >> 1]);
- } else if (!out && dev && ide_bus_master_read) {
- ret = ide_bus_master_read(dev->drv->ide_channel >> 1,
- dev->buffer, dev->packet_len,
- ide_bus_master_priv[dev->drv->ide_channel >> 1]);
- }
- }
-
- if (ret == 0) {
- zip_buf_free(dev);
- zip_bus_master_error(dev);
- } else if (ret == 1) {
- if (out)
- ret = zip_phase_data_out((scsi_common_t *) dev);
- else
- zip_command_stop((scsi_common_t *) dev);
- }
-
- return ret;
-}
-
-
-static void
-zip_callback(scsi_common_t *sc)
-{
- zip_t *dev = (zip_t *) sc;
- int ret;
-
- switch(sc->packet_status) {
- case PHASE_IDLE:
- zip_log("ZIP %i: PHASE_IDLE\n", sc->id);
- sc->pos = 0;
- sc->phase = 1;
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- return;
- case PHASE_COMMAND:
- zip_log("ZIP %i: PHASE_COMMAND\n", sc->id);
- sc->status = BUSY_STAT | (sc->status & ERR_STAT);
- zip_command(sc, sc->atapi_cdb);
- return;
- case PHASE_COMPLETE:
- zip_log("ZIP %i: PHASE_COMPLETE\n", sc->id);
- sc->status = READY_STAT;
- sc->phase = 3;
- sc->packet_status = 0xFF;
- ui_sb_update_icon(SB_ZIP | sc->id, 0);
- zip_irq_raise(sc);
- return;
- case PHASE_DATA_OUT:
- zip_log("ZIP %i: PHASE_DATA_OUT\n", sc->id);
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- sc->phase = 0;
- zip_irq_raise(sc);
- return;
- case PHASE_DATA_OUT_DMA:
- zip_log("ZIP %i: PHASE_DATA_OUT_DMA\n", dev->id);
- ret = zip_dma(dev, 1);
-
- if (ret == 2) {
- zip_log("ZIP %i: DMA out not enabled, wait\n", sc->id);
- zip_command_bus(dev);
-#ifdef ENABLE_ZIP_LOG
- } else {
- zip_log("ZIP %i: DMA data out phase %s\n", sc->id, ret ? "done" : "failure");
-#endif
- }
- return;
- case PHASE_DATA_IN:
- zip_log("ZIP %i: PHASE_DATA_IN\n", sc->id);
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- sc->phase = 2;
- zip_irq_raise(sc);
- return;
- case PHASE_DATA_IN_DMA:
- zip_log("ZIP %i: PHASE_DATA_IN_DMA\n", sc->id);
- ret = zip_dma(dev, 0);
-
- if (ret == 2) {
- zip_log("ZIP %i: DMA in not enabled, wait\n", sc->id);
- zip_command_bus(dev);
-#ifdef ENABLE_ZIP_LOG
- } else {
- zip_log("ZIP %i: DMA data in phase %s\n", sc->id, ret ? "done" : "failure");
-#endif
- }
- return;
- case PHASE_ERROR:
- zip_log("ZIP %i: PHASE_ERROR\n", sc->id);
- sc->status = READY_STAT | ERR_STAT;
- sc->phase = 3;
- sc->packet_status = 0xFF;
- zip_irq_raise(sc);
- ui_sb_update_icon(SB_ZIP | sc->id, 0);
- return;
- }
-}
-
-
/* Peform a master init on the entire module. */
void
zip_global_init(void)
@@ -2425,9 +2295,9 @@ zip_drive_reset(int c)
sd->sc = (scsi_common_t *) dev;
sd->command = zip_command;
- sd->callback = zip_callback;
sd->request_sense = zip_request_sense_for_scsi;
sd->reset = zip_reset;
+ sd->phase_data_out = zip_phase_data_out;
sd->command_stop = zip_command_stop;
sd->type = SCSI_REMOVABLE_DISK;
} else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) {
@@ -2442,10 +2312,11 @@ zip_drive_reset(int c)
id->get_timings = zip_get_timings;
id->identify = zip_identify;
id->stop = NULL;
- id->packet_callback = zip_callback;
+ id->packet_command = zip_command;
id->device_reset = zip_reset;
id->phase_data_out = zip_phase_data_out;
id->command_stop = zip_command_stop;
+ id->bus_master_error = zip_bus_master_error;
id->interrupt_drq = 1;
ide_atapi_attach(id);
diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c
index 8db242d00..ffd40ac5d 100644
--- a/src/scsi/scsi_cdrom.c
+++ b/src/scsi/scsi_cdrom.c
@@ -9,7 +9,7 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
- * Version: @(#)scsi_cdrom.c 1.0.66 2018/10/30
+ * Version: @(#)scsi_cdrom.c 1.0.67 2018/10/31
*
* Author: Miran Grca,
*
@@ -307,8 +307,6 @@ static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev);
static void scsi_cdrom_init(scsi_cdrom_t *dev);
-static void scsi_cdrom_callback(scsi_common_t *sc);
-
#ifdef ENABLE_SCSI_CDROM_LOG
int scsi_cdrom_do_log = ENABLE_SCSI_CDROM_LOG;
@@ -361,7 +359,7 @@ scsi_cdrom_init(scsi_cdrom_t *dev)
dev->sense[7] = 10;
dev->status = READY_STAT | DSC_STAT;
dev->pos = 0;
- dev->packet_status = 0xff;
+ dev->packet_status = PHASE_NONE;
scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0;
dev->drv->cur_speed = dev->drv->speed;
scsi_cdrom_mode_sense_load(dev);
@@ -632,17 +630,6 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev)
}
-static void
-scsi_cdrom_command_bus(scsi_cdrom_t *dev)
-{
- dev->status = BUSY_STAT;
- dev->phase = 1;
- dev->pos = 0;
- dev->callback = 1LL * CDROM_TIME;
- scsi_cdrom_set_callback(dev);
-}
-
-
static void
scsi_cdrom_command_common(scsi_cdrom_t *dev)
{
@@ -656,10 +643,9 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
scsi_cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed);
- if (dev->packet_status == PHASE_COMPLETE) {
- scsi_cdrom_callback((scsi_common_t *) dev);
+ if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0LL;
- } else {
+ else {
switch(dev->current_cdb[0]) {
case GPCMD_REZERO_UNIT:
case 0x0b:
@@ -828,7 +814,7 @@ scsi_cdrom_cmd_error(scsi_cdrom_t *dev)
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
- dev->packet_status = 0x80;
+ dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq);
@@ -845,7 +831,7 @@ scsi_cdrom_unit_attention(scsi_cdrom_t *dev)
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
dev->pos = 0;
- dev->packet_status = 0x80;
+ dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION\n", dev->id);
@@ -853,8 +839,31 @@ scsi_cdrom_unit_attention(scsi_cdrom_t *dev)
static void
-scsi_cdrom_bus_master_error(scsi_cdrom_t *dev)
+scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, uint32_t len)
{
+ scsi_cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len);
+ if (!dev->buffer)
+ dev->buffer = (uint8_t *) malloc(len);
+}
+
+
+static void
+scsi_cdrom_buf_free(scsi_cdrom_t *dev)
+{
+ if (dev->buffer) {
+ scsi_cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id);
+ free(dev->buffer);
+ dev->buffer = NULL;
+ }
+}
+
+
+static void
+scsi_cdrom_bus_master_error(scsi_common_t *sc)
+{
+ scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
+
+ scsi_cdrom_buf_free(dev);
scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0;
scsi_cdrom_cmd_error(dev);
}
@@ -1348,7 +1357,7 @@ scsi_cdrom_reset(scsi_common_t *sc)
scsi_cdrom_set_callback(dev);
dev->phase = 1;
dev->request_length = 0xEB14;
- dev->packet_status = 0xff;
+ dev->packet_status = PHASE_NONE;
dev->unit_attention = 0xff;
}
@@ -1429,26 +1438,6 @@ scsi_cdrom_set_buf_len(scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len)
}
-static void
-scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, uint32_t len)
-{
- scsi_cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len);
- if (!dev->buffer)
- dev->buffer = (uint8_t *) malloc(len);
-}
-
-
-static void
-scsi_cdrom_buf_free(scsi_cdrom_t *dev)
-{
- if (dev->buffer) {
- scsi_cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id);
- free(dev->buffer);
- dev->buffer = NULL;
- }
-}
-
-
static void
scsi_cdrom_stop(scsi_common_t *sc)
{
@@ -2488,124 +2477,6 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc)
}
-static void
-scsi_cdrom_irq_raise(scsi_common_t *sc)
-{
- scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
-
- if (dev->drv && (dev->drv->bus_type < CDROM_BUS_SCSI))
- ide_irq_raise(ide_drives[dev->drv->ide_channel]);
-}
-
-
-static int
-scsi_cdrom_dma(scsi_cdrom_t *dev, int out)
-{
- int ret = 1;
-
- if (dev->drv->bus_type == CDROM_BUS_ATAPI) {
- ret = 0;
-
- if (out && dev && ide_bus_master_write) {
- ret = ide_bus_master_write(dev->drv->ide_channel >> 1,
- dev->buffer, dev->packet_len,
- ide_bus_master_priv[dev->drv->ide_channel >> 1]);
- } else if (!out && dev && ide_bus_master_read) {
- ret = ide_bus_master_read(dev->drv->ide_channel >> 1,
- dev->buffer, dev->packet_len,
- ide_bus_master_priv[dev->drv->ide_channel >> 1]);
- }
- }
-
- if (ret == 0) {
- scsi_cdrom_buf_free(dev);
- scsi_cdrom_bus_master_error(dev);
- } else if (ret == 1) {
- if (out)
- ret = scsi_cdrom_phase_data_out((scsi_common_t *) dev);
- else
- scsi_cdrom_command_stop((scsi_common_t *) dev);
- }
-
- return ret;
-}
-
-
-static void
-scsi_cdrom_callback(scsi_common_t *sc)
-{
- scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
- int ret;
-
- switch(sc->packet_status) {
- case PHASE_IDLE:
- scsi_cdrom_log("CD-ROM %i: PHASE_IDLE\n", sc->id);
- sc->pos = 0;
- sc->phase = 1;
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- return;
- case PHASE_COMMAND:
- scsi_cdrom_log("CD-ROM %i: PHASE_COMMAND\n", dev->id);
- sc->status = BUSY_STAT | (dev->status & ERR_STAT);
- scsi_cdrom_command(sc, sc->atapi_cdb);
- return;
- case PHASE_COMPLETE:
- scsi_cdrom_log("CD-ROM %i: PHASE_COMPLETE\n", dev->id);
- sc->status = READY_STAT;
- sc->phase = 3;
- sc->packet_status = 0xFF;
- ui_sb_update_icon(SB_CDROM | sc->id, 0);
- scsi_cdrom_irq_raise(sc);
- return;
- case PHASE_DATA_OUT:
- scsi_cdrom_log("CD-ROM %i: PHASE_DATA_OUT\n", dev->id);
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- sc->phase = 0;
- scsi_cdrom_irq_raise(sc);
- return;
- case PHASE_DATA_OUT_DMA:
- scsi_cdrom_log("CD-ROM %i: PHASE_DATA_OUT_DMA\n", sc->id);
- ret = scsi_cdrom_dma(dev, 1);
-
- if (ret == 2) {
- scsi_cdrom_log("CD-ROM %i: DMA out not enabled, wait\n", sc->id);
- scsi_cdrom_command_bus(dev);
-#ifdef ENABLE_SCSI_CDROM_LOG
- } else {
- scsi_cdrom_log("CD-ROM %i: DMA data out phase %s\n", sc->id, ret ? "done" : "failure");
-#endif
- }
- return;
- case PHASE_DATA_IN:
- scsi_cdrom_log("CD-ROM %i: PHASE_DATA_IN\n", sc->id);
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- sc->phase = 2;
- scsi_cdrom_irq_raise(sc);
- return;
- case PHASE_DATA_IN_DMA:
- scsi_cdrom_log("CD-ROM %i: PHASE_DATA_IN_DMA\n", dev->id);
- ret = scsi_cdrom_dma(dev, 0);
-
- if (ret == 2) {
- scsi_cdrom_log("CD-ROM %i: DMA in not enabled, wait\n", sc->id);
- scsi_cdrom_command_bus(dev);
-#ifdef ENABLE_SCSI_CDROM_LOG
- } else {
- scsi_cdrom_log("CD-ROM %i: DMA data in phase %s\n", sc->id, ret ? "done" : "failure");
-#endif
- }
- return;
- case PHASE_ERROR:
- scsi_cdrom_log("CD-ROM %i: PHASE_ERROR\n", sc->id);
- sc->status = READY_STAT | ERR_STAT;
- sc->phase = 3;
- scsi_cdrom_irq_raise(sc);
- ui_sb_update_icon(SB_CDROM | sc->id, 0);
- return;
- }
-}
-
-
static void
scsi_cdrom_close(void *p)
{
@@ -2740,9 +2611,9 @@ scsi_cdrom_drive_reset(int c)
sd->sc = (scsi_common_t *) dev;
sd->command = scsi_cdrom_command;
- sd->callback = scsi_cdrom_callback;
sd->request_sense = scsi_cdrom_request_sense_for_scsi;
sd->reset = scsi_cdrom_reset;
+ sd->phase_data_out = scsi_cdrom_phase_data_out;
sd->command_stop = scsi_cdrom_command_stop;
sd->type = SCSI_REMOVABLE_CDROM;
@@ -2759,10 +2630,11 @@ scsi_cdrom_drive_reset(int c)
id->get_timings = scsi_cdrom_get_timings;
id->identify = scsi_cdrom_identify;
id->stop = scsi_cdrom_stop;
- id->packet_callback = scsi_cdrom_callback;
+ id->packet_command = scsi_cdrom_command;
id->device_reset = scsi_cdrom_reset;
id->phase_data_out = scsi_cdrom_phase_data_out;
id->command_stop = scsi_cdrom_command_stop;
+ id->bus_master_error = scsi_cdrom_bus_master_error;
id->interrupt_drq = 0;
ide_atapi_attach(id);
diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c
index b6bfb7b70..fb1a9db89 100644
--- a/src/scsi/scsi_device.c
+++ b/src/scsi/scsi_device.c
@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
- * Version: @(#)scsi_device.c 1.0.22 2018/10/28
+ * Version: @(#)scsi_device.c 1.0.23 2018/10/31
*
* Authors: Miran Grca,
* Fred N. van Kempen,
@@ -47,29 +47,6 @@ scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb)
}
-static void
-scsi_device_target_callback(scsi_device_t *dev)
-{
- if (dev->callback)
- dev->callback(dev->sc);
-
- return;
-}
-
-
-static int
-scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
-{
- if (dev->sc)
- if (dev->sc->status & ERR_STAT)
- return SCSI_STATUS_CHECK_CONDITION;
- else
- return SCSI_STATUS_OK;
- else
- return SCSI_STATUS_CHECK_CONDITION;
-}
-
-
int64_t
scsi_device_get_callback(scsi_device_t *dev)
{
@@ -148,12 +125,16 @@ scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
/* Finally, execute the SCSI command immediately and get the transfer length. */
dev->phase = SCSI_PHASE_COMMAND;
dev->status = scsi_device_target_command(dev, cdb);
+}
- if (dev->phase == SCSI_PHASE_STATUS) {
- /* Command completed (either OK or error) - call the phase callback to complete the command. */
- scsi_device_target_callback(dev);
+
+void
+scsi_device_command_stop(scsi_device_t *dev)
+{
+ if (dev->command_stop) {
+ dev->command_stop(dev->sc);
+ dev->status = SCSI_STATUS_OK;
}
- /* If the phase is DATA IN or DATA OUT, finish this here. */
}
@@ -164,19 +145,16 @@ scsi_device_command_phase1(scsi_device_t *dev)
return;
/* Call the second phase. */
- scsi_device_target_callback(dev);
- dev->status = scsi_device_target_err_stat_to_scsi(dev);
- /* Command second phase complete - call the callback to complete the command. */
- scsi_device_target_callback(dev);
-}
+ if (dev->phase == SCSI_PHASE_DATA_OUT) {
+ if (dev->phase_data_out)
+ dev->phase_data_out(dev->sc);
+ } else
+ scsi_device_command_stop(dev);
-
-void
-scsi_device_command_stop(scsi_device_t *dev)
-{
- if (!dev->command_stop)
- dev->command_stop(dev->sc);
- scsi_device_target_callback(dev);
+ if (dev->sc->status & ERR_STAT)
+ dev->status = SCSI_STATUS_CHECK_CONDITION;
+ else
+ dev->status = SCSI_STATUS_OK;
}
diff --git a/src/scsi/scsi_device.h b/src/scsi/scsi_device.h
index 6c5e34327..4c8d982ad 100644
--- a/src/scsi/scsi_device.h
+++ b/src/scsi/scsi_device.h
@@ -8,7 +8,7 @@
*
* Definitions for the generic SCSI device command handler.
*
- * Version: @(#)scsi_device.h 1.0.15 2018/10/30
+ * Version: @(#)scsi_device.h 1.0.16 2018/10/31
*
* Authors: Miran Grca,
* Fred N. van Kempen,
@@ -268,12 +268,13 @@
#define PHASE_IDLE 0x00
#define PHASE_COMMAND 0x01
-#define PHASE_COMPLETE 0x02
-#define PHASE_DATA_IN 0x03
+#define PHASE_DATA_IN 0x02
+#define PHASE_DATA_OUT 0x03
#define PHASE_DATA_IN_DMA 0x04
-#define PHASE_DATA_OUT 0x05
-#define PHASE_DATA_OUT_DMA 0x06
+#define PHASE_DATA_OUT_DMA 0x05
+#define PHASE_COMPLETE 0x06
#define PHASE_ERROR 0x80
+#define PHASE_NONE 0xff
#define SCSI_PHASE_DATA_OUT 0
#define SCSI_PHASE_DATA_IN BUS_IO
@@ -349,9 +350,9 @@ typedef struct {
scsi_common_t *sc;
void (*command)(scsi_common_t *sc, uint8_t *cdb);
- void (*callback)(scsi_common_t *sc);
void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length);
void (*reset)(scsi_common_t *sc);
+ uint8_t (*phase_data_out)(scsi_common_t *sc);
void (*command_stop)(scsi_common_t *sc);
} scsi_device_t;
diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c
index 35a85dace..24977a460 100644
--- a/src/scsi/scsi_disk.c
+++ b/src/scsi/scsi_disk.c
@@ -6,7 +6,7 @@
*
* Emulation of SCSI fixed disks.
*
- * Version: @(#)scsi_disk.c 1.0.28 2018/10/28
+ * Version: @(#)scsi_disk.c 1.0.29 2018/10/31
*
* Author: Miran Grca,
*
@@ -122,9 +122,6 @@ static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable =
} };
-static void scsi_disk_callback(scsi_common_t *sc);
-
-
#ifdef ENABLE_SCSI_DISK_LOG
int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG;
@@ -245,10 +242,9 @@ scsi_disk_command_common(scsi_disk_t *dev)
{
dev->status = BUSY_STAT;
dev->phase = 1;
- if (dev->packet_status == PHASE_COMPLETE) {
- scsi_disk_callback((scsi_common_t *) dev);
+ if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0LL;
- } else
+ else
dev->callback = -1LL; /* Speed depends on SCSI controller */
}
@@ -323,7 +319,7 @@ scsi_disk_cmd_error(scsi_disk_t *dev)
dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR;
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
- dev->packet_status = 0x80;
+ dev->packet_status = PHASE_ERROR;
dev->callback = 50 * SCSI_TIME;
scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq);
}
@@ -446,7 +442,7 @@ scsi_disk_reset(scsi_common_t *sc)
scsi_disk_rezero(dev);
dev->status = 0;
dev->callback = 0;
- dev->packet_status = 0xff;
+ dev->packet_status = PHASE_NONE;
}
@@ -1015,7 +1011,7 @@ scsi_disk_command_stop(scsi_common_t *sc)
}
-static void
+static uint8_t
scsi_disk_phase_data_out(scsi_common_t *sc)
{
scsi_disk_t *dev = (scsi_disk_t *) sc;
@@ -1030,7 +1026,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc)
if (!*BufLen) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
- return;
+ return 1;
}
switch (dev->current_cdb[0]) {
@@ -1140,39 +1136,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc)
}
scsi_disk_command_stop((scsi_common_t *) dev);
-}
-
-
-/* If the result is 1, issue an IRQ, otherwise not. */
-static void
-scsi_disk_callback(scsi_common_t *sc)
-{
- switch(sc->packet_status) {
- case PHASE_IDLE:
- scsi_disk_log("SCSI HD %i: PHASE_IDLE\n", dev->id);
- sc->phase = 1;
- sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
- return;
- case PHASE_COMPLETE:
- scsi_disk_log("SCSI HD %i: PHASE_COMPLETE\n", dev->id);
- sc->status = READY_STAT;
- sc->phase = 3;
- sc->packet_status = 0xFF;
- return;
- case PHASE_DATA_OUT_DMA:
- scsi_disk_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id);
- scsi_disk_phase_data_out(sc);
- return;
- case PHASE_DATA_IN_DMA:
- scsi_disk_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id);
- scsi_disk_command_stop(sc);
- return;
- case PHASE_ERROR:
- scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id);
- sc->status = READY_STAT | ERR_STAT;
- sc->phase = 3;
- return;
- }
+ return 1;
}
@@ -1211,9 +1175,9 @@ scsi_disk_hard_reset(void)
sd->sc = (scsi_common_t *) dev;
sd->command = scsi_disk_command;
- sd->callback = scsi_disk_callback;
sd->request_sense = scsi_disk_request_sense_for_scsi;
sd->reset = scsi_disk_reset;
+ sd->phase_data_out = scsi_disk_phase_data_out;
sd->command_stop = scsi_disk_command_stop;
sd->type = SCSI_FIXED_DISK;