Merge pull request #4448 from 86Box/tc1995
DMA speed fixes in place on the 53c400.
This commit is contained in:
@@ -103,6 +103,18 @@ ncr53c400_log(const char *fmt, ...)
|
||||
# define ncr53c400_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
ncr53c400_timer_on_auto(void *ext_priv, double period)
|
||||
{
|
||||
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
|
||||
|
||||
ncr53c400_log("53c400: PERIOD=%lf, timer=%x.\n", period, timer_is_enabled(&ncr400->timer));
|
||||
if (period <= 0.0)
|
||||
timer_stop(&ncr400->timer);
|
||||
else if ((period > 0.0) && !timer_is_enabled(&ncr400->timer))
|
||||
timer_on_auto(&ncr400->timer, period);
|
||||
}
|
||||
|
||||
/* Memory-mapped I/O WRITE handler. */
|
||||
static void
|
||||
ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
@@ -110,7 +122,6 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
|
||||
ncr_t *ncr = &ncr400->ncr;
|
||||
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
|
||||
int actual_block = 0;
|
||||
|
||||
addr &= 0x3fff;
|
||||
|
||||
@@ -135,6 +146,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||
ncr400->busy = 1;
|
||||
if (!(ncr->mode & MODE_MONITOR_BUSY))
|
||||
timer_on_auto(&ncr400->timer, ncr->period / 280.0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -165,19 +178,13 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
ncr400->buffer_host_pos = 0;
|
||||
ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
||||
}
|
||||
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0) && !timer_is_on(&ncr400->timer)) {
|
||||
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
|
||||
memset(ncr400->buffer, 0, MIN(128, dev->buffer_length));
|
||||
ncr53c400_log("DMA timer on, callback=%lf, scsi buflen=%d.\n", scsi_device_get_callback(dev), dev->buffer_length);
|
||||
actual_block = ncr400->block_count;
|
||||
if (!actual_block)
|
||||
actual_block = 256;
|
||||
|
||||
/*Sometimes the actual block count doesn't match the SCSI buffer length / 128.*/
|
||||
if (actual_block != (dev->buffer_length / 128)) {
|
||||
/*FIXME: To be improved further, this is just to workaround callback de-syncs when split transfers occur.*/
|
||||
timer_on_auto(&ncr400->timer, (ncr->period / ((double)(actual_block * 40.0))));
|
||||
} else
|
||||
if (ncr->mode & MODE_MONITOR_BUSY)
|
||||
timer_on_auto(&ncr400->timer, ncr->period);
|
||||
else
|
||||
timer_on_auto(&ncr400->timer, 40.0);
|
||||
ncr53c400_log("DMA timer on, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -232,6 +239,8 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||
ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl);
|
||||
if (!(ncr->mode & MODE_MONITOR_BUSY))
|
||||
timer_on_auto(&ncr400->timer, ncr->period / 280.0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -258,8 +267,7 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
break;
|
||||
|
||||
case 0x3982: /* switch register read */
|
||||
ret = 0xf8;
|
||||
ret |= (ncr->irq & 0x07);
|
||||
ret = 0xff;
|
||||
ncr53c400_log("Switches read=%02x.\n", ret);
|
||||
break;
|
||||
|
||||
@@ -392,24 +400,13 @@ ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
|
||||
ncr_t *ncr = (ncr_t *) priv;
|
||||
|
||||
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
|
||||
if (!ncr400->block_count_loaded && !(ncr->mode & MODE_DMA)) {
|
||||
if (!(ncr->mode & MODE_DMA)) {
|
||||
ncr53c400_log("No DMA mode\n");
|
||||
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
||||
ncr->isr &= ~STATUS_END_OF_DMA;
|
||||
ncr->dma_mode = DMA_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ncr53c400_timer_on_auto(void *ext_priv, double period)
|
||||
{
|
||||
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
|
||||
|
||||
ncr53c400_log("53c400: PERIOD=%lf, timer=%x.\n", period, !!timer_is_on(&ncr400->timer));
|
||||
if (period == 0.0)
|
||||
timer_stop(&ncr400->timer);
|
||||
else
|
||||
timer_on_auto(&ncr400->timer, period);
|
||||
} else
|
||||
ncr53c400_log("Continuing DMA, mode bit=%02x, block loaded=%d, waitcomplete=%d.\n", ncr->mode, ncr400->block_count_loaded, ncr->wait_complete);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -428,16 +425,10 @@ ncr53c400_callback(void *priv)
|
||||
if (ncr->data_wait & 1) {
|
||||
ncr->clear_req = 3;
|
||||
ncr->data_wait &= ~1;
|
||||
if (ncr->dma_mode == DMA_IDLE) {
|
||||
timer_stop(&ncr400->timer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ncr->dma_mode == DMA_IDLE) {
|
||||
timer_stop(&ncr400->timer);
|
||||
if (ncr->dma_mode == DMA_IDLE)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ncr->dma_mode) {
|
||||
case DMA_SEND:
|
||||
@@ -462,7 +453,6 @@ ncr53c400_callback(void *priv)
|
||||
if (ncr->cur_bus & BUS_REQ)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Data ready. */
|
||||
temp = ncr400->buffer[ncr400->buffer_pos];
|
||||
|
||||
@@ -487,7 +477,6 @@ ncr53c400_callback(void *priv)
|
||||
ncr53c400_log("IO End of write transfer\n");
|
||||
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
timer_stop(&ncr400->timer);
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR 53c400 write irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
@@ -518,7 +507,6 @@ ncr53c400_callback(void *priv)
|
||||
if (ncr->cur_bus & BUS_REQ)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Data ready. */
|
||||
ncr5380_bus_read(ncr);
|
||||
temp = BUS_GETDATA(ncr->cur_bus);
|
||||
@@ -541,7 +529,6 @@ ncr53c400_callback(void *priv)
|
||||
ncr400->block_count_loaded = 0;
|
||||
ncr53c400_log("IO End of read transfer\n");
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
timer_stop(&ncr400->timer);
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
@@ -562,6 +549,7 @@ ncr53c400_callback(void *priv)
|
||||
ncr53c400_log("Updating DMA\n");
|
||||
ncr->mode &= ~MODE_DMA;
|
||||
ncr->dma_mode = DMA_IDLE;
|
||||
ncr400->block_count_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user