From 252c3034af521c618d321a39f4ea55e053abaf43 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 00:57:18 +0200 Subject: [PATCH 1/6] Reworked the unit attention workaround, fixes #4770. --- src/scsi/scsi_cdrom.c | 96 ++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 2645659c7..e9abdd0d1 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1182,7 +1182,7 @@ scsi_cdrom_cmd_error(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) + if (dev->unit_attention > 2) dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; @@ -1199,7 +1199,7 @@ scsi_cdrom_unit_attention(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) + if (dev->unit_attention > 2) dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; @@ -1546,12 +1546,40 @@ scsi_cdrom_insert(void *priv) if (!dev) return; - dev->unit_attention = 0x11; + dev->unit_attention = 1; /* Turn off the medium changed status. */ dev->drv->cd_status &= ~CD_STATUS_MEDIUM_CHANGED; scsi_cdrom_log("CD-ROM %i: Media insert\n", dev->id); } +static int +scsi_command_check_ready(scsi_cdrom_t *dev, uint8_t *cdb) +{ + int ret = 0; + + if (scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) { + /*Note by TC1995: Some vendor commands from X vendor don't really check for ready status + but they do on Y vendor. Quite confusing I know.*/ + if (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY) switch (dev->drv->type) { + default: + ret = 1; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + if (cdb[0] == 0xC0) + break; + ret = 1; + break; + } else + ret = 1; + } + + return ret; +} + static int scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) { @@ -1598,23 +1626,24 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1); - /* Transition, pretend we're not ready for one check so that - Windows XP can recognize a medium change. */ - if ((dev->unit_attention & 0xf0) == 0x10) { - ready = 0; - goto skip_ua_check; - } - skip_ready_check: /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ - if (!ready && dev->unit_attention) + if (!ready && (dev->unit_attention > 2)) dev->unit_attention = 0; /* If the UNIT ATTENTION condition is set and the command does not allow execution under it, error out and report the condition. */ - if (dev->unit_attention == 1) { + if ((dev->unit_attention > 0) && (dev->unit_attention < 3)) { + dev->media_status = MEC_MEDIA_REMOVAL; + if (scsi_command_check_ready(dev, cdb)) { + dev->unit_attention++; + scsi_cdrom_log("CD-ROM %i: Simulated not ready phase (%02X)\n", dev->id, cdb[0]); + scsi_cdrom_not_ready(dev); + return 0; + } + } else if (dev->unit_attention == 3) { /* Only increment the unit attention phase if the command can not pass through it. */ if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { /* scsi_cdrom_log("CD-ROM %i: Unit attention now 2\n", dev->id); */ @@ -1624,53 +1653,31 @@ skip_ready_check: scsi_cdrom_unit_attention(dev); return 0; } - } else if (dev->unit_attention == 2) { + } else if (dev->unit_attention == 4) { if (cdb[0] != GPCMD_REQUEST_SENSE) { /* scsi_cdrom_log("CD-ROM %i: Unit attention now 0\n", dev->id); */ dev->unit_attention = 0; } } -skip_ua_check: /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* the UNIT ATTENTION condition if it's set. */ if (cdb[0] != GPCMD_REQUEST_SENSE) scsi_cdrom_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ - if (!ready) + if (!ready || ((dev->unit_attention > 0) && (dev->unit_attention < 3))) dev->media_status = MEC_MEDIA_REMOVAL; else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + dev->media_status = (dev->unit_attention > 2) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - if ((scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { - if (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY) { /*Note by TC1995: Some vendor commands from X vendor don't really check for ready status - but they do on Y vendor. Quite confusing I know.*/ - switch (dev->drv->type) { - case CDROM_TYPE_DEC_RRD45_0436: - case CDROM_TYPE_SONY_CDU541_10i: - case CDROM_TYPE_SONY_CDU561_18k: - case CDROM_TYPE_SONY_CDU76S_100: - case CDROM_TYPE_TEXEL_DMXX24_100: - if (cdb[0] == 0xC0) - break; - scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); - scsi_cdrom_not_ready(dev); - return 0; - default: - scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); - scsi_cdrom_not_ready(dev); - return 0; - } - } else { - scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); - scsi_cdrom_not_ready(dev); - return 0; - } + if (!ready && scsi_command_check_ready(dev, cdb)) { + scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + scsi_cdrom_not_ready(dev); + return 0; } scsi_cdrom_log("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); - return 1; } @@ -1719,7 +1726,7 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt buffer[2] = SENSE_ILLEGAL_REQUEST; buffer[12] = ASC_AUDIO_PLAY_OPERATION; buffer[13] = (dev->drv->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } else if (dev->unit_attention && ((dev->unit_attention & 0xf0) != 0x10) && + } else if ((dev->unit_attention > 2) && ((scsi_cdrom_sense_key == 0) || (scsi_cdrom_sense_key == 2))) { buffer[2] = SENSE_UNIT_ATTENTION; buffer[12] = ASC_MEDIUM_MAY_HAVE_CHANGED; @@ -1728,9 +1735,6 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt scsi_cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); - if ((dev->unit_attention & 0xf0) == 0x10) - dev->unit_attention &= 0x0f; - if (buffer[2] == SENSE_UNIT_ATTENTION) { /* If the last remaining sense is unit attention, clear that condition. */ @@ -1746,7 +1750,7 @@ scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t al if (dev->drv->cd_status & CD_STATUS_MEDIUM_CHANGED) scsi_cdrom_insert((void *) dev); - if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) { + if ((dev->drv->cd_status == CD_STATUS_EMPTY) && (dev->unit_attention > 2)) { /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ From 3c209818ae0a0388b466c4e1966558c0ce302cda Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 05:18:34 +0200 Subject: [PATCH 2/6] P6: Fix the restoration of the A20 state when exiting SMM, fixes #4771. --- src/cpu/386_common.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 1d130cd8a..87d1008cc 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1016,9 +1016,14 @@ smram_restore_state_p6(uint32_t *saved_state) cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_gs); - mem_a20_alt = 0x00; - mem_a20_key = saved_state[SMRAM_FIELD_P6_A20M] ? 0x00 : 0x02; - mem_a20_recalc(); + rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + if (is6117) + rammask |= 0x3000000; + + if (saved_state[SMRAM_FIEL_P6_A20M] & 0x01) + rammask &= ~0xffefffff; + + flushmmucache(); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) smbase = saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET]; From db946015734df06f47f659088b7dada17ae22516 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 05:22:33 +0200 Subject: [PATCH 3/6] Voodoo 3/Banshee: Implement XRGB8888 LFB format, fixes POD. --- src/include/86box/vid_voodoo_regs.h | 1 + src/video/vid_voodoo_fb.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/include/86box/vid_voodoo_regs.h b/src/include/86box/vid_voodoo_regs.h index f05029a8d..379219d35 100644 --- a/src/include/86box/vid_voodoo_regs.h +++ b/src/include/86box/vid_voodoo_regs.h @@ -341,6 +341,7 @@ enum { LFB_FORMAT_RGB565 = 0, LFB_FORMAT_RGB555 = 1, LFB_FORMAT_ARGB1555 = 2, + LFB_FORMAT_XRGB8888 = 4, LFB_FORMAT_ARGB8888 = 5, LFB_FORMAT_DEPTH = 15, LFB_FORMAT_MASK = 15 diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index 94394e115..5156cfdad 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -364,6 +364,15 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) addr >>= 1; break; + case LFB_FORMAT_XRGB8888: + colour_data[0].b = val & 0xff; + colour_data[0].g = (val >> 8) & 0xff; + colour_data[0].r = (val >> 16) & 0xff; + alpha_data[0] = 0xff; + write_mask = LFB_WRITE_COLOUR; + addr >>= 1; + break; + case LFB_FORMAT_DEPTH: depth_data[0] = val; depth_data[1] = val >> 16; From 54ab778d4a5130b64db323524a43560172973f48 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 05:32:26 +0200 Subject: [PATCH 4/6] Fixed a compile-breaking typo in cpu/386_common.c. --- src/cpu/386_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 87d1008cc..ea9cc1126 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1020,7 +1020,7 @@ smram_restore_state_p6(uint32_t *saved_state) if (is6117) rammask |= 0x3000000; - if (saved_state[SMRAM_FIEL_P6_A20M] & 0x01) + if (saved_state[SMRAM_FIELD_P6_A20M] & 0x01) rammask &= ~0xffefffff; flushmmucache(); From fe4ad0d4e16b50610821a295eba2f5b801ba685c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 06:01:52 +0200 Subject: [PATCH 5/6] S3: Make sure to absolutely restore everything to the original state on reset, even the contents of vram and changedvram, fixes #4768. --- src/video/vid_s3.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 3f64d3b3a..6fe5f1ad6 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -9441,12 +9441,18 @@ s3_disable_handlers(s3_t *s3) { s3_io_remove(s3); + mem_mapping_set_addr(&s3->linear_mapping, 0, 0); mem_mapping_disable(&s3->linear_mapping); + mem_mapping_set_addr(&s3->mmio_mapping, 0, 0); mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_set_addr(&s3->new_mmio_mapping, 0, 0); mem_mapping_disable(&s3->new_mmio_mapping); + mem_mapping_set_addr(&s3->svga.mapping, 0xa0000, 0x20000); mem_mapping_disable(&s3->svga.mapping); - if (s3->pci) + if (s3->pci) { + mem_mapping_set_addr(&s3->bios_rom.mapping, 0xc0000, 0x8000); mem_mapping_disable(&s3->bios_rom.mapping); + } /* Save all the mappings and the timers because they are part of linked lists. */ reset_state->linear_mapping = s3->linear_mapping; @@ -9457,6 +9463,11 @@ s3_disable_handlers(s3_t *s3) reset_state->svga.timer = s3->svga.timer; reset_state->svga.timer8514 = s3->svga.timer8514; + + memset(s3->svga.vram, 0x00, s3->svga.vram_max + 8); + memset(s3->svga.changedvram, 0x00, (s3->svga.vram_max >> 12) + 1); + + pci_clear_irq(s3->pci_slot, PCI_INTA, &s3->irq_state); } static void @@ -9471,6 +9482,7 @@ s3_reset(void *priv) reset_state->pci_slot = s3->pci_slot; *s3 = *reset_state; + s3_io_set(s3); } } From 91cf90c63a07cec0abff3ce3b1cc19a8f6ed180a Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Aug 2024 07:52:55 +0200 Subject: [PATCH 6/6] Olivetti M19's video adapter has control register on port 3DBh instead of 3DEh, fixes #4739. --- src/include/86box/vid_ogc.h | 1 + src/machine/m_xt_olivetti.c | 2 ++ src/video/vid_ogc.c | 13 +++++++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/include/86box/vid_ogc.h b/src/include/86box/vid_ogc.h index 839769e69..efafb180e 100644 --- a/src/include/86box/vid_ogc.h +++ b/src/include/86box/vid_ogc.h @@ -23,6 +23,7 @@ typedef struct ogc_t { cga_t cga; + uint16_t ctrl_addr; /* unused in OGC, required for M19 video card structure idiom */ uint8_t ctrl_3dd; uint8_t ctrl_3de; diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index b13db6bf9..817b0d0cc 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -2038,6 +2038,8 @@ m19_vid_init(m19_vid_t *vid) vid->ogc.mono_display = 0; else vid->ogc.mono_display = 1; + + vid->ogc.ctrl_addr = 0x3db; /* OGC emulation part end */ /* Plantronics emulation part begin*/ diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index c3073898d..9ac94169c 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -97,11 +97,14 @@ ogc_out(uint16_t addr, uint8_t val, void *priv) cga_out(addr, val, &ogc->cga); break; + case 0x3db: case 0x3de: - /* set control register */ - ogc->ctrl_3de = val; - /* select 1st or 2nd 16k vram block to be used */ - ogc->base = (val & 0x08) ? 0x4000 : 0; + if (addr == ogc->ctrl_addr) { + /* set control register */ + ogc->ctrl_3de = val; + /* select 1st or 2nd 16k vram block to be used */ + ogc->base = (val & 0x08) ? 0x4000 : 0; + } break; default: @@ -622,6 +625,8 @@ ogc_init(UNUSED(const device_t *info)) else ogc->mono_display = 1; + ogc->ctrl_addr = 0x3de; + return ogc; }