Merge pull request #6834 from 86Box/TC1995

Sort out the IRQ/INT enabling/disabling stuff of the 5380/53c80 chip.
This commit is contained in:
Miran Grča
2026-02-22 23:51:48 +01:00
committed by GitHub
4 changed files with 86 additions and 50 deletions

View File

@@ -84,6 +84,7 @@ typedef struct ncr_t {
int (*dma_send_ext)(void *priv, void *ext_priv);
int (*dma_initiator_receive_ext)(void *priv, void *ext_priv);
void (*timer)(void *ext_priv, double period);
int (*irq_ena)(void *priv, void *ext_priv, int state);
scsi_bus_t scsibus;
} ncr_t;

View File

@@ -62,13 +62,9 @@ void
ncr5380_irq(ncr_t *ncr, int set_irq)
{
if (set_irq) {
ncr->irq_state = 1;
ncr->isr |= STATUS_INT;
if (ncr->irq != -1)
picint(1 << ncr->irq);
} else {
ncr->irq_state = 0;
ncr->isr &= ~STATUS_INT;
if (ncr->irq != 1)
picintc(1 << ncr->irq);
}
@@ -104,7 +100,12 @@ ncr5380_reset(ncr_t *ncr)
scsi_bus->data = 0;
scsi_bus->command_issued = 0;
ncr5380_irq(ncr, 0);
if (ncr->irq_ena)
ncr->irq_ena(ncr, ncr->priv, 0);
else
ncr5380_irq(ncr, 0);
ncr->isr &= ~STATUS_INT;
}
uint32_t
@@ -164,7 +165,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
if ((val & 0x80) && !(ncr->icr & 0x80)) {
ncr5380_log("Resetting the 5380\n");
ncr5380_reset(ncr);
ncr5380_irq(ncr, 1);
ncr->isr |= STATUS_INT;
}
ncr->icr = val;
ncr5380_log("ICR WaitData=%d, ClearReq=%d.\n", scsi_bus->wait_data, scsi_bus->clear_req);
@@ -301,7 +302,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
if (bus & BUS_MSG)
bus_state |= TCR_MSG;
if ((ncr->tcr & 7) != bus_state) {
ncr5380_irq(ncr, 1);
ncr->isr |= STATUS_INT;
ncr5380_log("IRQ issued\n");
}
}
@@ -321,7 +322,12 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
case 7: /* reset Parity/Interrupt */
ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20);
ncr5380_irq(ncr, 0);
if (ncr->irq_ena)
ncr->irq_ena(ncr, ncr->priv, 0);
else
ncr5380_irq(ncr, 0);
ncr->isr &= ~STATUS_INT;
ncr5380_log("Reset Interrupt\n");
break;

View File

@@ -72,6 +72,7 @@ typedef struct ncr53c400_t {
int8_t type;
uint8_t block_count;
uint8_t status_ctrl;
uint8_t irq_config;
int block_count_loaded;
@@ -103,6 +104,23 @@ ncr53c400_log(const char *fmt, ...)
# define ncr53c400_log(fmt, ...)
#endif
static int
ncr53c400_irq_enable(void *priv, void *ext_priv, int state)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
if (ncr->irq_state != state) {
ncr->irq_state = state;
ncr400->status_ctrl &= ~0x01;
ncr400->status_ctrl |= (state << 0);
ncr53c400_log("Status Control bit 4=%02x.\n", ncr400->status_ctrl);
if (ncr400->status_ctrl & 0x10)
ncr5380_irq(ncr, state);
}
return 1;
}
static void
ncr53c400_timer_on_auto(void *ext_priv, double period)
{
@@ -263,7 +281,8 @@ ncr53c400_read(uint32_t addr, void *priv)
ncr->isr |= STATUS_END_OF_DMA;
if (ncr->mode & MODE_ENA_EOP_INT) {
ncr53c400_log("NCR read irq\n");
ncr5380_irq(ncr, 1);
ncr53c400_irq_enable(ncr, ncr400, 1);
ncr->isr |= STATUS_INT;
}
} else if (!timer_is_enabled(&ncr400->timer)) {
ncr53c400_log("Timer re-enabled.\n");
@@ -277,15 +296,16 @@ ncr53c400_read(uint32_t addr, void *priv)
case 0x3980:
switch (addr) {
case 0x3980: /* status */
if (ncr400->reset) {
ncr400->reset = 0;
ncr53c400_irq_enable(ncr, ncr400, 1);
}
ret = ncr400->status_ctrl;
ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY);
if (!ncr400->busy)
ret |= STATUS_5380_ACCESSIBLE;
if (ncr400->reset) {
ncr400->reset = 0;
ret |= 0x01;
}
ncr53c400_log("NCR 53c400 status=%02x.\n", ret);
break;
@@ -295,10 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv)
break;
case 0x3982: /* switch register read */
if (ncr->irq != -1) {
ret = 0xf8;
ret += ncr->irq;
}
ret = ((ncr400->irq_config >> 5) & 7) | 0xf8;
ncr53c400_log("Switches read=%02x.\n", ret);
break;
@@ -519,7 +536,8 @@ ncr53c400_callback(void *priv)
ncr->isr |= STATUS_END_OF_DMA;
if (ncr->mode & MODE_ENA_EOP_INT) {
ncr53c400_log("NCR 53c400 write irq\n");
ncr5380_irq(ncr, 1);
ncr53c400_irq_enable(ncr, ncr400, 1);
ncr->isr |= STATUS_INT;
}
}
break;
@@ -573,7 +591,8 @@ ncr53c400_callback(void *priv)
ncr->isr |= STATUS_END_OF_DMA;
if (ncr->mode & MODE_ENA_EOP_INT) {
ncr53c400_log("NCR read irq\n");
ncr5380_irq(ncr, 1);
ncr53c400_irq_enable(ncr, ncr400, 1);
ncr->isr |= STATUS_INT;
}
} else
timer_on_auto(&ncr400->timer, 1.0);
@@ -675,7 +694,8 @@ ncr53c400_init(const device_t *info)
switch (ncr400->type) {
case ROM_LCS6821N: /* Longshine LCS6821N */
ncr400->rom_addr = device_get_config_hex20("bios_addr");
ncr->irq = device_get_config_int("irq");
ncr400->irq_config = device_get_config_hex16("irq");
ncr->irq = (ncr400->irq_config >> 5) & 7;
rom_init(&ncr400->bios_rom, LCS6821N_ROM,
ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
@@ -689,7 +709,8 @@ ncr53c400_init(const device_t *info)
case ROM_LS2000: /* Corel LS2000 */
ncr400->rom_addr = device_get_config_hex20("bios_addr");
ncr->irq = device_get_config_int("irq");
ncr400->irq_config = device_get_config_hex16("irq");
ncr->irq = (ncr400->irq_config >> 5) & 7;
rom_init(&ncr400->bios_rom, COREL_LS2000_ROM,
ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
@@ -702,7 +723,9 @@ ncr53c400_init(const device_t *info)
case ROM_RT1000B: /* Rancho RT1000B/MC */
ncr400->rom_addr = device_get_config_hex20("bios_addr");
ncr->irq = device_get_config_int("irq");
ncr400->irq_config = device_get_config_hex16("irq");
ncr->irq = (ncr400->irq_config >> 5) & 7;
if (info->flags & DEVICE_MCA) {
rom_init(&ncr400->bios_rom, RT1000B_820R_ROM,
0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
@@ -729,7 +752,8 @@ ncr53c400_init(const device_t *info)
case ROM_T130B: /* Trantor T130B */
ncr400->rom_addr = device_get_config_hex20("bios_addr");
ncr400->base = device_get_config_hex16("base");
ncr->irq = device_get_config_int("irq");
ncr400->irq_config = device_get_config_hex16("irq");
ncr->irq = (ncr400->irq_config >> 5) & 7;
if (ncr400->rom_addr > 0x00000) {
rom_init(&ncr400->bios_rom, T130B_ROM,
@@ -754,6 +778,7 @@ ncr53c400_init(const device_t *info)
ncr->dma_send_ext = NULL;
ncr->dma_initiator_receive_ext = NULL;
ncr->timer = ncr53c400_timer_on_auto;
ncr->irq_ena = ncr53c400_irq_enable;
scsi_bus->bus_device = ncr->bus;
scsi_bus->timer = ncr->timer;
scsi_bus->priv = ncr->priv;
@@ -839,16 +864,16 @@ static const device_config_t ncr53c400_mmio_config[] = {
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 5,
.default_int = 0xa0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "None", .value = -1 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "IRQ 3", .value = 0x60 },
{ .description = "IRQ 4", .value = 0x80 },
{ .description = "IRQ 5", .value = 0xa0 },
{ .description = "IRQ 7", .value = 0xe0 },
{ .description = "" }
},
.bios = { { 0 } }
@@ -910,16 +935,16 @@ static const device_config_t rt1000b_config[] = {
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 5,
.default_int = 0xa0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "None", .value = -1 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "IRQ 3", .value = 0x60 },
{ .description = "IRQ 4", .value = 0x80 },
{ .description = "IRQ 5", .value = 0xa0 },
{ .description = "IRQ 7", .value = 0xe0 },
{ .description = "" }
},
.bios = { { 0 } }
@@ -931,16 +956,16 @@ static const device_config_t rt1000b_mc_config[] = {
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 5,
.default_int = 0xa0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "None", .value = -1 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "IRQ 3", .value = 0x60 },
{ .description = "IRQ 4", .value = 0x80 },
{ .description = "IRQ 5", .value = 0xa0 },
{ .description = "IRQ 7", .value = 0xe0 },
{ .description = "" }
},
.bios = { { 0 } }
@@ -987,16 +1012,16 @@ static const device_config_t t130b_config[] = {
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 5,
.default_int = 0xa0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "None", .value = -1 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "IRQ 3", .value = 0x60 },
{ .description = "IRQ 4", .value = 0x80 },
{ .description = "IRQ 5", .value = 0xa0 },
{ .description = "IRQ 7", .value = 0xe0 },
{ .description = "" }
},
.bios = { { 0 } }

View File

@@ -27,7 +27,6 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/pic.h>
@@ -41,6 +40,7 @@
#include <86box/scsi_device.h>
#include <86box/scsi_ncr5380.h>
#include <86box/scsi_t128.h>
#include "cpu.h"
#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin"
@@ -75,7 +75,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
if ((addr >= 0x1800) && (addr < 0x1880))
t128->ext_ram[addr & 0x7f] = val;
else if ((addr >= 0x1c00) && (addr < 0x1c20)) {
t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA);
t128_log("T128 ctrl write=%02x, mode=%02x.\n", val & 0x10, ncr->mode & MODE_DMA);
t128->ctrl = val;
} else if ((addr >= 0x1d00) && (addr < 0x1e00))
ncr5380_write((addr - 0x1d00) >> 5, val, ncr);
@@ -141,6 +141,7 @@ t128_read(uint32_t addr, void *priv)
if (ncr->mode & MODE_ENA_EOP_INT) {
t128_log("T128 read irq\n");
ncr5380_irq(ncr, 1);
ncr->isr |= STATUS_INT;
}
scsi_bus->bus_out |= BUS_CD;
scsi_bus->tx_mode = PIO_TX_BUS;
@@ -298,6 +299,7 @@ t128_callback(void *priv)
if (ncr->mode & MODE_ENA_EOP_INT) {
t128_log("T128 write irq\n");
ncr5380_irq(ncr, 1);
ncr->isr |= STATUS_INT;
}
scsi_bus->tx_mode = PIO_TX_BUS;
timer_stop(&t128->timer);
@@ -497,6 +499,7 @@ t128_init(const device_t *info)
ncr->dma_send_ext = t128_dma_send_ext;
ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext;
ncr->timer = t128_timer_on_auto;
ncr->irq_ena = NULL;
scsi_bus->bus_device = ncr->bus;
scsi_bus->timer = ncr->timer;
scsi_bus->priv = ncr->priv;
@@ -566,12 +569,13 @@ static const device_config_t t128_config[] = {
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 5,
.default_int = -1,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "None", .value = -1 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 4", .value = 4 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "IRQ 10", .value = 10 },