From 265152db754b7b60cc3eeafd2b6b596ef0c4da0b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 7 Mar 2025 19:58:36 +0100 Subject: [PATCH 1/6] NCR 53c400: slightly more accurate speed. See above. --- src/scsi/scsi_ncr53c400.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index c83e75442..fc62a1cab 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -425,8 +425,8 @@ ncr53c400_callback(void *priv) if (scsi_bus->tx_mode != PIO_TX_BUS) { if (ncr400->type == ROM_T130B) { - ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 200.0); - timer_on_auto(&ncr400->timer, scsi_bus->period / 200.0); + ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0); + timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0); } else timer_on_auto(&ncr400->timer, 1.0); } From 05f6940844f9fed4bc6d68cd6819ae7fb76cad8e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 8 Mar 2025 05:47:44 +0100 Subject: [PATCH 2/6] Fixed ROM BASIC loading on XT 1982, fixes #5243. --- src/machine/m_xt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 9f232ac95..78d2daa13 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -366,7 +366,11 @@ machine_xt_init(const machine_t *model) fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); - (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); + /* On the real machine, the BASIC is repeated. */ + (void) bios_load_aux_linear(fn, 0x000f0000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f2000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f4000, 8192, 0); + (void) bios_load_aux_linear(fn, 0x000f6000, 8192, 0); } device_context_restore(); From 16d7bc26dcddf666f67ba0f5d12d6c8ec237a3ab Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 8 Mar 2025 10:14:58 +0500 Subject: [PATCH 3/6] Fix the LPT device list duplicating on every machine change --- src/qt/qt_settingsports.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 630c843b9..cb1ab794a 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -74,22 +74,26 @@ SettingsPorts::onCurrentMachineChanged(int machineId) this->machineId = machineId; for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); - auto *model = cbox->model(); - int c = 0; - int selectedRow = 0; + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *model = cbox->model(); + const auto removeRows = model->rowCount(); + int c = 0; + int selectedRow = 0; while (true) { const char *lptName = lpt_device_get_name(c); if (lptName == nullptr) { break; } - Models::AddEntry(model, tr(lptName), c); + int row = Models::AddEntry(model, tr(lptName), c); if (c == lpt_ports[i].device) { - selectedRow = c; + selectedRow = row - removeRows; } c++; } + model->removeRows(0, removeRows); + cbox->setEnabled(model->rowCount() > 0); + cbox->setCurrentIndex(-1); cbox->setCurrentIndex(selectedRow); auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); From 63c5b6003f7c9fed9d12212cde9a58808bdcc1f0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:29:13 +0100 Subject: [PATCH 4/6] Spock/Tribble changes of the day (March 8th, 2025) 1. Make IRQ's more correct and per manual. 2. Only an adapter reset command should reset the SCSI devices connected to it. 3. Differentiate the two controllers by the connector bit (pos3 bit 12) in the CMD GET POS INFO SCB command. 4. Actually emulate bit 7 of pos4 in the pos writes so that selection between 16KB and 32KB rom loading is done properly. 5. Some cleanups. --- src/scsi/scsi_spock.c | 144 +++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 567879a12..c500abfbc 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -206,7 +206,6 @@ typedef struct { #define IRQ_TYPE_COMMAND_FAIL 0xc #define IRQ_TYPE_COMMAND_ERROR 0xe #define IRQ_TYPE_SW_SEQ_ERROR 0xf -#define IRQ_TYPE_RESET_COMPLETE 0x10 #ifdef ENABLE_SPOCK_LOG int spock_do_log = ENABLE_SPOCK_LOG; @@ -226,7 +225,9 @@ spock_log(const char *fmt, ...) # define spock_log(fmt, ...) #endif -static void +static void spock_reset(void *priv); + +static __inline void spock_rethink_irqs(spock_t *scsi) { int irq_pending = 0; @@ -236,7 +237,7 @@ spock_rethink_irqs(spock_t *scsi) if (scsi->irq_requests[c] != IRQ_TYPE_NONE) { /* Found IRQ */ scsi->irq_status = c | (scsi->irq_requests[c] << 4); - spock_log("Found IRQ: status = %02x\n", scsi->irq_status); + spock_log("Found IRQ: status=%02x.\n", scsi->irq_status); scsi->status |= STATUS_IRQ; irq_pending = 1; break; @@ -245,38 +246,37 @@ spock_rethink_irqs(spock_t *scsi) } else irq_pending = 1; + spock_log("spock_rethink_irqs: irqstat=%02x, ctrl=%02x, irqpend=%d.\n", scsi->irq_status, scsi->basic_ctrl, irq_pending); if (scsi->basic_ctrl & CTRL_IRQ_ENA) { if (irq_pending) { spock_log("IRQ issued\n"); - scsi->irq_inactive = 0; + scsi->status |= STATUS_IRQ; picint(1 << scsi->irq); } else { /* No IRQs pending, clear IRQ state */ spock_log("IRQ cleared\n"); - scsi->irq_status = 0; - scsi->irq_inactive = 1; - scsi->status &= ~STATUS_IRQ; picintc(1 << scsi->irq); } } else { - spock_log("IRQ disabled\n"); - picintc(1 << scsi->irq); + spock_log("IRQ disabled, pending=%d.\n", irq_pending); + if (irq_pending) + scsi->status |= STATUS_IRQ; } } -static __inline void +static void spock_set_irq(spock_t *scsi, int id, int type) { - spock_log("spock_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status); + spock_log("spock_set_irq: id=%i, type=%x, irqstat=%02x\n", id, type, scsi->irq_status); scsi->irq_requests[id] = type; if (!scsi->irq_status) /* Don't change IRQ status if one is currently being processed */ spock_rethink_irqs(scsi); } -static __inline void +static void spock_clear_irq(spock_t *scsi, int id) { - spock_log("spock_clear_irq id=%i\n", id); + spock_log("spock_clear_irq: id=%i.\n", id); scsi->irq_requests[id] = IRQ_TYPE_NONE; spock_rethink_irqs(scsi); } @@ -292,7 +292,7 @@ spock_write(uint16_t port, uint8_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_writeb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_writeb: port=%04x, val=%02x.\n", CS, cpu_state.pc, port & 7, val); switch (port & 7) { case 0: @@ -308,16 +308,14 @@ spock_write(uint16_t port, uint8_t val, void *priv) case 4: /*Attention Register*/ scsi->attention_pending = val; - scsi->attention_wait = 2; + scsi->attention_wait = 2; scsi->status |= STATUS_BUSY; break; case 5: /*Basic Control Register*/ - if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { + if (!(scsi->basic_ctrl & CTRL_RESET) && (val & CTRL_RESET)) { spock_log("Spock: SCSI reset and busy\n"); - scsi->in_reset = 1; - scsi->cmd_timer = SPOCK_TIME * 2; - scsi->status |= STATUS_BUSY; + spock_reset(scsi); } scsi->basic_ctrl = val; spock_rethink_irqs(scsi); @@ -333,7 +331,7 @@ spock_writew(uint16_t port, uint16_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_writew: port=%04x, val=%04x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_writew: port=%04x, val=%04x.\n", CS, cpu_state.pc, port & 7, val); switch (port & 7) { case 0: /*Command Interface Register*/ @@ -391,7 +389,7 @@ spock_read(uint16_t port, void *priv) break; } - spock_log("spock_readb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); + spock_log("%04X:%08X: spock_readb: port=%04x, temp=%02x.\n", CS, cpu_state.pc, port & 7, temp); return temp; } @@ -442,9 +440,8 @@ spock_get_len(spock_t *scsi, scb_t *scb) DataToTransfer += scb->sge.sys_buf_byte_count; } return DataToTransfer; - } else { - return (scsi->data_len); } + return (scsi->data_len); } static void @@ -494,15 +491,14 @@ spock_process_imm_cmd(spock_t *scsi) spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; case CMD_INVALID_412: - spock_log("Invalid 412\n"); + spock_log("Invalid 412.\n"); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; case CMD_RESET: - spock_log("Reset Command, attention = %d.\n", scsi->attention & 0x0f); + spock_log("Reset command, attention=%02x.\n", scsi->attention & 0x0f); if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) scsi_device_reset(&scsi_devices[scsi->bus][i]); - } for (i = 6; i > -1; i--) { if (scsi_device_present(&scsi_devices[scsi->bus][i])) { @@ -514,10 +510,21 @@ spock_process_imm_cmd(spock_t *scsi) spock_log("Adapter Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); } } + } else if ((scsi->attention & 0x0f) < 7) { /*Device reset*/ + scsi_device_reset(&scsi_devices[scsi->bus][scsi->attention & 0x0f]); - scsi->scb_state = 0; + for (i = 6; i > -1; i--) { + if (scsi_device_present(&scsi_devices[scsi->bus][i])) { + spock_log("Device Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + scsi->present[j] = i; + j++; + } else { + scsi->present[j] = 0xff; + spock_log("Device Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + } + } } - + scsi->scb_state = 0; spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); break; @@ -535,18 +542,10 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) int old_scb_state; if (scsi->in_reset) { - spock_log("Reset type=%d\n", scsi->in_reset); - scsi->status &= ~STATUS_BUSY; - scsi->irq_status = 0; - for (c = 0; c < SCSI_ID_MAX; c++) - spock_clear_irq(scsi, c); - - if (scsi->in_reset == 1) - scsi->basic_ctrl |= CTRL_IRQ_ENA; - - spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); + scsi->irq_status = 0x0f; + spock_rethink_irqs(scsi); /*Reset device mappings*/ for (c = 0; c < 7; c++) { @@ -558,7 +557,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) scsi->in_reset = 0; - for (c = 6; c > -1; c--) { + for (c = 6; c >= 0; c--) { if (scsi_device_present(&scsi_devices[scsi->bus][c])) { spock_log("Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); scsi->present[j] = c; @@ -678,7 +677,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) get_pos_info->pos = scsi->spock_16bit ? 0x8efe : 0x8eff; get_pos_info->pos1 = scsi->pos_regs[3] | (scsi->pos_regs[2] << 8); get_pos_info->pos2 = scsi->irq | (scsi->pos_regs[4] << 8); - get_pos_info->pos3 = 1 << 12; + get_pos_info->pos3 = scsi->spock_16bit ? (1 << 12) : (0 << 12); get_pos_info->pos4 = (7 << 8) | 8; get_pos_info->pos5 = (16 << 8) | scsi->pacing; get_pos_info->pos6 = (30 << 8) | 1; @@ -965,6 +964,8 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) else sd->buffer_length = spock_get_len(scsi, scb); + scsi_device_identify(sd, scsi->temp_cdb[1] >> 5); + scsi_device_command_phase0(sd, scsi->temp_cdb); spock_log("SCSI ID %i: Current CDB[0]=%02x, LUN=%i, buffer len=%i, max len=%i, phase val=%02x, data len=%d, enable bit 10=%03x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase, scsi->data_len, scb->enable & 0x400); @@ -1018,8 +1019,12 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) break; case SCSI_STATE_END_PHASE: + sd = &scsi_devices[scsi->bus][scsi->cdb_id]; scsi->scsi_state = SCSI_STATE_IDLE; + if (sd->type != SCSI_NONE) + scsi_device_identify(sd, SCSI_LUN_USE_CDB); + spock_log("State to idle, cmd timer %d\n", scsi->cmd_timer); if (!scsi->cmd_timer) scsi->cmd_timer = 1; @@ -1045,7 +1050,7 @@ spock_callback(void *priv) spock_execute_cmd(scsi, scb); } - if (scsi->attention_wait && ((scsi->scb_state == 0) || (scsi->attention_pending & 0xf0) == 0xe0)) { + if (scsi->attention_wait) { scsi->attention_wait--; if (!scsi->attention_wait) { scsi->attention = scsi->attention_pending; @@ -1094,6 +1099,7 @@ spock_callback(void *priv) case 0x0e: /*EOI*/ scsi->irq_status = 0; + scsi->status &= ~STATUS_IRQ; spock_clear_irq(scsi, scsi->attention & 0x0f); break; @@ -1118,23 +1124,30 @@ spock_mca_write(int port, uint8_t val, void *priv) if (port < 0x102) return; - io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + io_removehandler((((scsi->pos_regs[2] >> 1) & 7) << 3) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); mem_mapping_disable(&scsi->bios_rom.mapping); scsi->pos_regs[port & 7] = val; scsi->adapter_id = (scsi->pos_regs[3] & 0xe0) >> 5; - if (scsi->pos_regs[2] & 1) { - io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); - if (scsi->pos_regs[4] & 2) { - if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { - mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); - mem_mapping_enable(&scsi->bios_rom.mapping); + if (scsi->pos_regs[2] & 0x01) { + io_sethandler((((scsi->pos_regs[2] >> 1) & 7) << 3) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + if (scsi->pos_regs[4] & 0x02) { + if (scsi->pos_regs[4] & 0x80) { + if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); + mem_mapping_enable(&scsi->bios_rom.mapping); + } + } else { + if (((scsi->pos_regs[2] >> 4) & 0x0f) != 0x0f) { + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x4000); + mem_mapping_enable(&scsi->bios_rom.mapping); + } } } } - spock_log("[%04X:%08X]: POS Write Port = %x, val = %02x, rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000); + spock_log("%04X:%08X: POS Write Port=%x, val=%02x.\n", CS, cpu_state.pc, port & 7, val); } static uint8_t @@ -1142,7 +1155,7 @@ spock_mca_read(int port, void *priv) { const spock_t *scsi = (spock_t *) priv; - spock_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, + spock_log("%04X:%08X: POS Read Port=%x, temp=%02x.\n", CS, cpu_state.pc, port & 7, scsi->pos_regs[port & 7]); return scsi->pos_regs[port & 7]; } @@ -1155,12 +1168,13 @@ spock_mca_feedb(void *priv) return (scsi->pos_regs[2] & 0x01); } + static void -spock_mca_reset(void *priv) +spock_reset(void *priv) { spock_t *scsi = (spock_t *) priv; - scsi->in_reset = 2; + scsi->in_reset = 1; scsi->cmd_timer = SPOCK_TIME * 50; scsi->status = STATUS_BUSY; scsi->scsi_state = SCSI_STATE_IDLE; @@ -1169,13 +1183,15 @@ spock_mca_reset(void *priv) scsi->attention_wait = 0; scsi->basic_ctrl = 0; - /* Reset all devices on controller reset. */ - for (uint8_t i = 0; i < 8; i++) { - scsi_device_reset(&scsi_devices[scsi->bus][i]); - scsi->present[i] = 0xff; - } + spock_log("Actual Reset.\n"); +} - spock_log("Reset.\n"); +static void +spock_mca_reset(void *priv) +{ + spock_t *scsi = (spock_t *) priv; + + spock_reset(scsi); mem_mapping_disable(&scsi->bios_rom.mapping); scsi->pos_regs[4] = 0x02; spock_mca_write(0x102, 0, scsi); @@ -1213,10 +1229,6 @@ spock_init(const device_t *info) scsi->pos_regs[4] = 0x02; mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi); - scsi->in_reset = 2; - scsi->cmd_timer = SPOCK_TIME * 50; - scsi->status = STATUS_BUSY; - for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) scsi->dev_id[c].phys_id = -1; @@ -1230,6 +1242,8 @@ spock_init(const device_t *info) scsi_bus_set_speed(scsi->bus, 5000000.0); + spock_reset(scsi); + return scsi; } @@ -1278,7 +1292,7 @@ const device_t spock_device = { .local = 0, .init = spock_init, .close = spock_close, - .reset = NULL, + .reset = spock_reset, .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, @@ -1292,7 +1306,7 @@ const device_t tribble_device = { .local = 1, .init = spock_init, .close = spock_close, - .reset = NULL, + .reset = spock_reset, .available = spock_available, .speed_changed = NULL, .force_redraw = NULL, From a2534c1f4f655c6675f1b324344aa7233900ec0b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:41:59 +0100 Subject: [PATCH 5/6] Trantor T128/MediaVision SCSI changes of the day (March 8th, 2025) 1. Made as best as possible implementation of the status bits 1-2 of the Trantor 128 so to make a more accurate speed for SCSI devices (CD-ROM and HDD) without stalls. 2. Slightly reorganized the timer of the T128. --- src/scsi/scsi_t128.c | 292 +++++++++++++++++++++---------------------- 1 file changed, 142 insertions(+), 150 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 5ac3b5d67..6b73ae131 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -77,11 +77,8 @@ 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)) { - if ((val & 0x02) && !(t128->ctrl & 0x02)) - t128->status |= 0x02; - + t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA); t128->ctrl = val; - t128_log("T128 ctrl write=%02x\n", val); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ncr5380_write((addr - 0x1d00) >> 5, val, ncr); else if ((addr >= 0x1e00) && (addr < 0x2000)) { @@ -90,13 +87,15 @@ t128_write(uint32_t addr, uint8_t val, void *priv) t128->buffer[t128->host_pos] = val; t128->host_pos++; - t128_log("T128 Write transfer, addr = %i, pos = %i, val = %02x\n", - addr & 0x1ff, t128->host_pos, val); + t128_log("T128 Write transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); if (t128->host_pos == MIN(512, dev->buffer_length)) { + t128_log("T128 Transfer busy write, status=%02x, period=%lf, enabled=%d, loaded=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded); + t128->status &= ~0x04; - t128_log("Transfer busy write, status = %02x\n", t128->status); - timer_on_auto(&t128->timer, 0.02); + timer_on_auto(&t128->timer, 1.0); } } } @@ -119,31 +118,45 @@ t128_read(uint32_t addr, void *priv) ret = t128->ext_ram[addr & 0x7f]; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { ret = t128->ctrl; - t128_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 ctrl read=%02x, dma=%02x, load=%d, cnt=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, t128->block_count); } else if ((addr >= 0x1c20) && (addr < 0x1c40)) { ret = t128->status; - t128_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 status read=%02x, dma=%02x, blockload=%d, timer=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, timer_is_enabled(&t128->timer)); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ret = ncr5380_read((addr - 0x1d00) >> 5, ncr); else if (addr >= 0x1e00 && addr < 0x2000) { - if ((t128->host_pos >= MIN(512, dev->buffer_length)) || - (scsi_bus->tx_mode != DMA_IN_TX_BUS)) - ret = 0xff; - else { + if ((scsi_bus->tx_mode == DMA_IN_TX_BUS) && + (t128->host_pos < MIN(512, dev->buffer_length))) { ret = t128->buffer[t128->host_pos++]; - t128_log("T128 Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, - t128->host_pos); + t128_log("T128 Read transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); if (t128->host_pos == MIN(512, dev->buffer_length)) { - t128->status &= ~0x04; - t128_log("T128 Transfer busy read, status = %02x, period = %lf\n", - t128->status, scsi_bus->period); - if ((scsi_bus->period == 0.2) || (scsi_bus->period == 0.02)) - timer_on_auto(&t128->timer, 40.2); - } else if ((t128->host_pos < MIN(512, dev->buffer_length)) && - (scsi_device_get_callback(dev) > 100.0)) - cycles += 100; /*Needed to avoid timer de-syncing with transfers.*/ + t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + + if (!t128->block_loaded) { + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 read irq\n"); + ncr5380_irq(ncr, 1); + } + t128->status &= ~0x04; + scsi_bus->bus_out |= BUS_CD; + scsi_bus->tx_mode = PIO_TX_BUS; + timer_stop(&t128->timer); + } else if (!timer_is_enabled(&t128->timer)) + timer_on_auto(&t128->timer, 1.0); + else + t128->status &= ~0x04; + } + } else { + /*According to the WinNT DDK sources, just get the status timeout bit from here.*/ + if (!(t128->status & 0x02)) + t128->status |= 0x02; + + t128_log("Read not allowed.\n"); } } @@ -151,24 +164,20 @@ t128_read(uint32_t addr, void *priv) } static void -t128_dma_mode_ext(void *priv, void *ext_priv, UNUSED(uint8_t val)) +t128_dma_mode_ext(void *priv, void *ext_priv, uint8_t val) { t128_t *t128 = (t128_t *) ext_priv; ncr_t *ncr = (ncr_t *) priv; scsi_bus_t *scsi_bus = &ncr->scsibus; - /*Don't stop the timer until it finishes the transfer*/ - if (t128->block_loaded && (ncr->mode & MODE_DMA)) { - t128_log("Continuing DMA mode\n"); - timer_on_auto(&t128->timer, scsi_bus->period + 1.0); - } - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!t128->block_loaded && !(ncr->mode & MODE_DMA)) { - t128_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - scsi_bus->tx_mode = PIO_TX_BUS; + if (!t128->block_loaded) { + if (!(val & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; + t128_log("End of DMA.\n"); + } } } @@ -180,9 +189,9 @@ t128_dma_send_ext(void *priv, void *ext_priv) scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; - if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA OUT, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = 0; t128->block_count = dev->buffer_length >> 9; @@ -190,6 +199,7 @@ t128_dma_send_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; + t128->status |= 0x04; } return 1; } @@ -202,9 +212,9 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; - if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA IN, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = MIN(512, dev->buffer_length); t128->block_count = dev->buffer_length >> 9; @@ -212,7 +222,8 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; - timer_on_auto(&t128->timer, 0.02); + t128->status &= ~0x04; + timer_on_auto(&t128->timer, 1.0); } return 1; } @@ -222,16 +233,16 @@ t128_timer_on_auto(void *ext_priv, double period) { t128_t *t128 = (t128_t *) ext_priv; - if (period == 0.0) + if (period <= 0.0) timer_stop(&t128->timer); - else + else if ((period > 0.0) && !timer_is_enabled(&t128->timer)) timer_on_auto(&t128->timer, period); } void t128_callback(void *priv) { - t128_t *t128 = (void *) priv; + t128_t *t128 = (t128_t *) priv; ncr_t *ncr = &t128->ncr; scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; @@ -240,128 +251,110 @@ t128_callback(void *priv) uint8_t temp; uint8_t status; - if ((scsi_bus->tx_mode != PIO_TX_BUS) && (ncr->mode & MODE_DMA) && t128->block_loaded) { - if ((t128->host_pos == MIN(512, dev->buffer_length)) && t128->block_count) - t128->status |= 0x04; - - timer_on_auto(&t128->timer, scsi_bus->period / 55.0); - } + if (scsi_bus->tx_mode != PIO_TX_BUS) + timer_on_auto(&t128->timer, scsi_bus->period / 65.0); if (scsi_bus->data_wait & 1) { scsi_bus->clear_req = 3; scsi_bus->data_wait &= ~1; - if (scsi_bus->tx_mode == PIO_TX_BUS) - return; + } + + if (scsi_bus->tx_mode == PIO_TX_BUS) { + t128_log("Timer CMD=%02x.\n", scsi_bus->command[0]); + return; } switch (scsi_bus->tx_mode) { case DMA_OUT_TX_BUS: - if (!(t128->status & 0x04)) { - t128_log("Write status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); - break; - } - - if (!t128->block_loaded) { - t128_log("Write block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -write_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - temp = t128->buffer[t128->pos]; - - bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(temp); - - scsi_bus_update(scsi_bus, bus | BUS_ACK); - scsi_bus_update(scsi_bus, bus & ~BUS_ACK); - - t128->pos++; - t128_log("T128 Buffer pos for writing = %d\n", t128->pos); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("T128 write irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto write_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + + /* Data ready. */ + temp = t128->buffer[t128->pos]; + + bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); + + t128->pos++; + t128_log("T128 Buffer pos for writing = %d\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 write irq\n"); + ncr5380_irq(ncr, 1); + } + scsi_bus->tx_mode = PIO_TX_BUS; + timer_stop(&t128->timer); + t128_log("IO End of write transfer\n"); + } + break; + } + } break; case DMA_IN_TX_BUS: - if (!(t128->status & 0x04)) { - t128_log("Read status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); - break; - } - - if (!t128->block_loaded) { - t128_log("Read block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -read_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - bus = scsi_bus_read(scsi_bus); - temp = BUS_GETDATA(bus); - - bus = ncr5380_get_bus_host(ncr); - - scsi_bus_update(scsi_bus, bus | BUS_ACK); - scsi_bus_update(scsi_bus, bus & ~BUS_ACK); - - t128->buffer[t128->pos++] = temp; - t128_log("T128 Buffer pos for reading=%d, temp=%02x, len=%d.\n", t128->pos, temp, dev->buffer_length); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto read_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + /* Data ready. */ + bus = scsi_bus_read(scsi_bus); + temp = BUS_GETDATA(bus); + + bus = ncr5380_get_bus_host(ncr); + + scsi_bus_update(scsi_bus, bus | BUS_ACK); + scsi_bus_update(scsi_bus, bus & ~BUS_ACK); + + t128->buffer[t128->pos++] = temp; + t128_log("T128 Buffer pos for reading = %d\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be read=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + scsi_bus->bus_out |= BUS_REQ; + t128_log("IO End of read transfer\n"); + } + break; + } + } break; default: @@ -374,7 +367,7 @@ read_again: t128_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; scsi_bus->tx_mode = PIO_TX_BUS; - timer_on_auto(&t128->timer, 10.0); + t128->block_loaded = 0; } } @@ -513,7 +506,7 @@ t128_init(const device_t *info) scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; - t128->status = 0x00 /*0x04*/; + t128->status = 0x00; t128->host_pos = 512; if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) t128->status |= 0x80; @@ -528,7 +521,6 @@ t128_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 1.0; scsi_bus->multi = 1.0; - return t128; } From 5f833a0963a1e868b107157d75a09e7ccec77bd7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:45:41 +0100 Subject: [PATCH 6/6] Mach32 LFB changes of the day (March 8th, 2025) Do not subtract from the linear base when it's not in the range, should fix NT 3.x graphics bugs using the LFB. --- src/video/vid_ati_mach8.c | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 6e2798295..0c8fb6691 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -5223,11 +5223,11 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) { + if (addr & 0x100) { mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); } else { @@ -5238,9 +5238,9 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_log("Linear WORDB Write=%08x, val=%02x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_write_common(addr - mach->linear_base, val, 1, mach, svga); + mach32_write_common(addr, val, 1, mach, svga); else - svga_write_linear(addr - mach->linear_base, val, svga); + svga_write_linear(addr, val, svga); } } @@ -5250,11 +5250,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) { + if (addr & 0x100) { mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val, mach); } else { @@ -5265,9 +5265,9 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writew_linear(addr - mach->linear_base, val, mach); + mach32_writew_linear(addr, val, mach); else - svga_writew_linear(addr - mach->linear_base, val, svga); + svga_writew_linear(addr, val, svga); } } @@ -5277,11 +5277,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) { + if (addr & 0x100) { mach_log("Port WORDL Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val & 0xffff, mach); mach_accel_outw(0x02ee + (port_dword << 8) + 4, val >> 16, mach); @@ -5294,9 +5294,9 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writel_linear(addr - mach->linear_base, val, mach); + mach32_writel_linear(addr, val, mach); else - svga_writel_linear(addr - mach->linear_base, val, svga); + svga_writel_linear(addr, val, svga); } } @@ -5307,19 +5307,19 @@ mach32_ap_readb(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) + if (addr & 0x100) temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); else temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_read_common(addr - mach->linear_base, 1, mach, svga); + temp = mach32_read_common(addr, 1, mach, svga); else - temp = svga_read_linear(addr - mach->linear_base, svga); + temp = svga_read_linear(addr, svga); mach_log("Linear WORDB Read=%08x, ret=%02x, fast=%d.\n", addr, temp, svga->fast); } @@ -5338,15 +5338,15 @@ mach32_ap_readw(uint32_t addr, void *priv) if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) + if (addr & 0x100) temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); else temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_readw_linear(addr - mach->linear_base, mach); + temp = mach32_readw_linear(addr, mach); else - temp = svga_readw_linear(addr - mach->linear_base, svga); + temp = svga_readw_linear(addr, svga); mach_log("Linear WORDW Read=%08x, ret=%04x.\n", addr, temp); } @@ -5361,11 +5361,11 @@ mach32_ap_readl(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if ((addr - mach->linear_base) & 0x100) { + if (addr & 0x100) { temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); } else { @@ -5374,9 +5374,9 @@ mach32_ap_readl(uint32_t addr, void *priv) } } else { if (dev->on) - temp = mach32_readl_linear(addr - mach->linear_base, mach); + temp = mach32_readl_linear(addr, mach); else - temp = svga_readl_linear(addr - mach->linear_base, svga); + temp = svga_readl_linear(addr, svga); mach_log("Linear WORDL Read=%08x, ret=%08x, ON%d.\n", addr, temp, dev->on); }