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, ...)
|
# define ncr53c400_log(fmt, ...)
|
||||||
#endif
|
#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. */
|
/* Memory-mapped I/O WRITE handler. */
|
||||||
static void
|
static void
|
||||||
ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
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;
|
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
|
||||||
ncr_t *ncr = &ncr400->ncr;
|
ncr_t *ncr = &ncr400->ncr;
|
||||||
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
|
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
|
||||||
int actual_block = 0;
|
|
||||||
|
|
||||||
addr &= 0x3fff;
|
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)) {
|
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||||
ncr400->busy = 1;
|
ncr400->busy = 1;
|
||||||
|
if (!(ncr->mode & MODE_MONITOR_BUSY))
|
||||||
|
timer_on_auto(&ncr400->timer, ncr->period / 280.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -165,19 +178,13 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
|||||||
ncr400->buffer_host_pos = 0;
|
ncr400->buffer_host_pos = 0;
|
||||||
ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
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));
|
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);
|
if (ncr->mode & MODE_MONITOR_BUSY)
|
||||||
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
|
|
||||||
timer_on_auto(&ncr400->timer, ncr->period);
|
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;
|
break;
|
||||||
|
|
||||||
@@ -232,6 +239,8 @@ ncr53c400_read(uint32_t addr, void *priv)
|
|||||||
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||||
ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl);
|
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;
|
break;
|
||||||
@@ -258,8 +267,7 @@ ncr53c400_read(uint32_t addr, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3982: /* switch register read */
|
case 0x3982: /* switch register read */
|
||||||
ret = 0xf8;
|
ret = 0xff;
|
||||||
ret |= (ncr->irq & 0x07);
|
|
||||||
ncr53c400_log("Switches read=%02x.\n", ret);
|
ncr53c400_log("Switches read=%02x.\n", ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -392,24 +400,13 @@ ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
|
|||||||
ncr_t *ncr = (ncr_t *) 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*/
|
/*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");
|
ncr53c400_log("No DMA mode\n");
|
||||||
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
||||||
ncr->isr &= ~STATUS_END_OF_DMA;
|
ncr->isr &= ~STATUS_END_OF_DMA;
|
||||||
ncr->dma_mode = DMA_IDLE;
|
ncr->dma_mode = DMA_IDLE;
|
||||||
}
|
} 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
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -428,16 +425,10 @@ ncr53c400_callback(void *priv)
|
|||||||
if (ncr->data_wait & 1) {
|
if (ncr->data_wait & 1) {
|
||||||
ncr->clear_req = 3;
|
ncr->clear_req = 3;
|
||||||
ncr->data_wait &= ~1;
|
ncr->data_wait &= ~1;
|
||||||
if (ncr->dma_mode == DMA_IDLE) {
|
|
||||||
timer_stop(&ncr400->timer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncr->dma_mode == DMA_IDLE) {
|
if (ncr->dma_mode == DMA_IDLE)
|
||||||
timer_stop(&ncr400->timer);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
switch (ncr->dma_mode) {
|
switch (ncr->dma_mode) {
|
||||||
case DMA_SEND:
|
case DMA_SEND:
|
||||||
@@ -462,7 +453,6 @@ ncr53c400_callback(void *priv)
|
|||||||
if (ncr->cur_bus & BUS_REQ)
|
if (ncr->cur_bus & BUS_REQ)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data ready. */
|
/* Data ready. */
|
||||||
temp = ncr400->buffer[ncr400->buffer_pos];
|
temp = ncr400->buffer[ncr400->buffer_pos];
|
||||||
|
|
||||||
@@ -487,7 +477,6 @@ ncr53c400_callback(void *priv)
|
|||||||
ncr53c400_log("IO End of write transfer\n");
|
ncr53c400_log("IO End of write transfer\n");
|
||||||
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
||||||
ncr->isr |= STATUS_END_OF_DMA;
|
ncr->isr |= STATUS_END_OF_DMA;
|
||||||
timer_stop(&ncr400->timer);
|
|
||||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||||
ncr53c400_log("NCR 53c400 write irq\n");
|
ncr53c400_log("NCR 53c400 write irq\n");
|
||||||
ncr5380_irq(ncr, 1);
|
ncr5380_irq(ncr, 1);
|
||||||
@@ -518,7 +507,6 @@ ncr53c400_callback(void *priv)
|
|||||||
if (ncr->cur_bus & BUS_REQ)
|
if (ncr->cur_bus & BUS_REQ)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data ready. */
|
/* Data ready. */
|
||||||
ncr5380_bus_read(ncr);
|
ncr5380_bus_read(ncr);
|
||||||
temp = BUS_GETDATA(ncr->cur_bus);
|
temp = BUS_GETDATA(ncr->cur_bus);
|
||||||
@@ -541,7 +529,6 @@ ncr53c400_callback(void *priv)
|
|||||||
ncr400->block_count_loaded = 0;
|
ncr400->block_count_loaded = 0;
|
||||||
ncr53c400_log("IO End of read transfer\n");
|
ncr53c400_log("IO End of read transfer\n");
|
||||||
ncr->isr |= STATUS_END_OF_DMA;
|
ncr->isr |= STATUS_END_OF_DMA;
|
||||||
timer_stop(&ncr400->timer);
|
|
||||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||||
ncr53c400_log("NCR read irq\n");
|
ncr53c400_log("NCR read irq\n");
|
||||||
ncr5380_irq(ncr, 1);
|
ncr5380_irq(ncr, 1);
|
||||||
@@ -562,6 +549,7 @@ ncr53c400_callback(void *priv)
|
|||||||
ncr53c400_log("Updating DMA\n");
|
ncr53c400_log("Updating DMA\n");
|
||||||
ncr->mode &= ~MODE_DMA;
|
ncr->mode &= ~MODE_DMA;
|
||||||
ncr->dma_mode = DMA_IDLE;
|
ncr->dma_mode = DMA_IDLE;
|
||||||
|
ncr400->block_count_loaded = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user