Moved the phase callback handler to hdc_ide.c, where it belongs, rather than in each SCSI(-like) device's code, and made it no longer used when a device's bus type is set to SCSI.
This commit is contained in:
@@ -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, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -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:
|
||||
|
||||
@@ -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, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -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
|
||||
|
||||
|
||||
197
src/disk/zip.c
197
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, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user